LeetCode 100题(1)(10题)

发布于:2025-07-08 ⋅ 阅读:(39) ⋅ 点赞:(0)

1 : 160. 相交链表 - 力扣(LeetCode)

题意:给定两个链表,让你返回这两个链表相交的起始节点,没有就返回null;

思路:我们让 pa 指向 A 链表的头节点,pb 指向 B 链表的头节点,然后每次都移动一个单位长度,假如 pa 移动到 A 链表的尾节点时,就让他指向 B 链表的头节点,同理,当 pb 指向 B 链表的尾节点时,就让它指向 A 链表的头节点。

我们仔细想一下,如果这两个链表后面相交的话,那么 pa 跑完一遍 A 链表,再从 B 链表的头节点跑到两个链表相交的起始节点  和  pb 跑完一遍 B 链表,再从 A 链表的头节点跑到两个链表相交的起始节点,这二者所走过的单位距离一定是相等的。

那么如果这两个链表不相交呢?会不会死循环呢?答案是不会的,他们会在两个链表长度的最大=小公倍数那里同时指向null,退出循环。

时间复杂度O(n);

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pa = headA;
        ListNode pb = headB;

        if(pa == null || pb == null) return null;

        while(pa != pb){
            pa = pa == null ? headB : pa.next;
            pb = pb == null ? headA : pb.next;
        }
        return pa;
    }
}

2:1. 两数之和 - 力扣(LeetCode)

题意:给定一个数组,和一个目标数target,让你找到两个数,使他们加起来等于target,并输出这两个数的下标,保证有解。

思路:我们遍历数组,对于每个数 num1,用 target - num1,表示出我们要找的数num2,然后如果这个数不在 HashMap 里我们就把这个数和它的下标存进去,否则我们就取出这个数的下标 break 这是个在线做法。

那么我们为什么不一开始就存入每个数的下标呢(离线)?因为数组里面会有重复的数

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> mp = new HashMap<>();
        int x = -1, y = -1;
        for(int i = 0; i < nums.length; i ++){
            int num1 = nums[i];
            int num2 = target - num1;
            if(mp.containsKey(num2)){
                x = i;
                y = mp.get(num2);
                break;
            }
            mp.put(nums[i], i);
        }
        return new int[]{x, y};
    }
}

3: 236. 二叉树的最近公共祖先 - 力扣(LeetCode)

题意:很简单,给定一个二叉树,再给定两个节点p, q,求这两个节点的公共祖先

思路:当一个节点的左子树 lson 中有 p 或 q 节点,我们就设其为 true,右子树 rson 同理,当然如果该节点本身就是 p 或 q, 我们设其为 true,所以最后如果这个节点是最近公共祖先,他要满足的条件就是 :
 

lson && rson || ((root.val == p.val && (lson || rson)) || (root.val == q.val && (lson || rson)))

详情见代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    static TreeNode ans = null;

    private boolean dfs(TreeNode root, TreeNode p, TreeNode q){
        if(root == null) return false;
        boolean lson = dfs(root.left, p, q);
        boolean rson = dfs(root.right, p, q);
        if(lson && rson || ((root.val == p.val && (lson || rson)) || (root.val == q.val && (lson || rson)))){
            ans = root;
        }
        return lson || rson || root.val == p.val || root.val == q.val;
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        dfs(root, p, q);
        return ans;
    }
}

补充:当然这是二叉树的情况,如果是多叉树呢?

P3379 【模板】最近公共祖先(LCA) - 洛谷

我们要用倍增法和 dp 的思想,预处理;

#include <iostream>
#include <vector>
#define int long long
using namespace std;

const int N = 5e5 + 10;
vector<vector<int>> e(N);
vector<vector<int>> p(N, vector<int>(21, 0));
vector<int> d(N, 0); // 深度

void dfs(int u, int fa)
{
	p[u][0] = fa;
	d[u] = d[fa] + 1;
	for(int i = 1; (1 << i) <= d[u]; i ++)
	{
		p[u][i] = p[p[u][i - 1]][i - 1];
	}
	
	for(auto v : e[u])
	{
		if(v != fa) dfs(v, u);
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int n, m, s;
	cin >> n >> m >> s;
	for(int i = 0; i < n - 1; i ++)
	{
		int u, v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	
	dfs(s, 0);
	
	while(m --)
	{
		int a, b;
		cin >> a >> b;
		if(d[a] > d[b]) swap(a, b);
		
		for(int i = 20; i >= 0; i --)
		{
			if(d[b] - (1 << i) >= d[a])
			{
				b = p[b][i];
			}
		}
		
		if(a == b) cout << a << '\n';
		else
		{
			for(int i = 20; i >= 0; i --)
			{
				if(p[a][i] != p[b][i])
				{
					a = p[a][i];
					b = p[b][i];
				}
			}
			cout << p[a][0] <<  '\n';
		}
	}
	return 0;
}

4:234. 回文链表 - 力扣(LeetCode) 

题意:给定一个链表,判断是否为回文链表;

思路:把链表中的 val 复制到一个数组中,然后用双指针判断即可

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        List<Integer> vec = new ArrayList<>();
        while(head != null){
            vec.add(head.val);
            head = head.next;
        }

        boolean f = true;
        int j = vec.size() - 1;
        int i = 0;
        while(i < j){
            if(!vec.get(i).equals(vec.get(j))){
                f = false;
                break;
            }
            i ++;
            j --;
        }
        return f;
    }
}

 5:739. 每日温度 - 力扣(LeetCode)

 题意:给定一串数组,对于其中每个数,判断后面比它大且离他最近的那个数离它有多远。

思路:单调栈板子题

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int len = temperatures.length;
        int[] ans = new int[len];

        Stack<Integer> stack = new Stack<>();
        for(int i = len - 1; i >= 0; i --){
            while(!stack.isEmpty() && temperatures[stack.peek()] <= temperatures[i]) stack.pop();
            if(stack.isEmpty()) ans[i] = 0;
            else{
                int pos = stack.peek();
                ans[i] = pos - i;
            }
            stack.push(i);
        }

        return ans;
    }
}

6:226. 翻转二叉树 - 力扣(LeetCode)

题意:给你一个二叉树,反转二叉树

思路:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private TreeNode dfs(TreeNode root){
        if(root == null){
            return null;
        }

        TreeNode tmp = root.right;
        root.right = root.left;
        root.left = tmp;
        dfs(root.left);
        dfs(root.right);
        return root;
    }

    public TreeNode invertTree(TreeNode root) {
        dfs(root);
        return root;
    }
}

7:221. 最大正方形 - 力扣(LeetCode) 

题意:给定一个 0 1 矩阵,让你算出矩阵中只包含 1 的正方形;

思路:考虑dp,dp[i][j]表示,以 i, j 坐标为右下角的正方型的最大边长,具体状态转移见代码

class Solution {
    public int maximalSquare(char[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[0].length;

        int [][] dp = new int[rows + 1][cols + 1];
        int maxsize = 0;

        for(int i = 0; i < rows; i ++){
            for(int j = 0; j < cols; j ++){
                if(matrix[i][j] == '1'){
                    if((i == 0 || j == 0)){
                        dp[i][j] = 1;
                    }else{
                        dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
                    }
                }
                maxsize = Math.max(maxsize, dp[i][j]);
            }
        }
        return maxsize * maxsize;
    }
}

8:215. 数组中的第K个最大元素 - 力扣(LeetCode) 

 题意:给定一串数组,让你求出第K大的元素是什么。

思路:最简单的方法就是直接暴力排序,但是时间复杂度是O(nlogn),但我们可以用快速排序(分治)的思想,每次选个轴点,然后经过一轮分类后,这个轴点左边的元素都是小于它的,右边的元素都是大于它的,所以这个轴点的下标 j 就是排名第 j 的元素,然后如果这个排名 j 比我们要的排名高,那就继续排序左边的区间,否则就排序右边的区间。

class Solution {

    private int quick_sort(int[] nums, int l, int r, int q){
        if(l == r) return nums[q];

        int x = nums[(l + r) / 2];
        int i = l - 1, j = r + 1;
        while(i < j){
            do i ++; while(nums[i] < x);
            do j --; while(nums[j] > x);
            if(i < j){
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        if(q <= j) return quick_sort(nums, l, j, q);
        else return quick_sort(nums, j + 1, r, q);
    }


    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;
        return quick_sort(nums, 0, n - 1, n - k);
    }
}

9:208. 实现 Trie (前缀树) - 力扣(LeetCode)

题意:实现字典树的增,查功能

思路:板子

class Trie {

    private Trie[] children;
    private boolean isEnd;

    public Trie() {
        this.children = new Trie[26];
        this.isEnd = false;
    }
    
    public void insert(String word) {
        Trie node = this;
        for(char c : word.toCharArray()){
            int idx = c - 'a';
            if(node.children[idx] == null){
                node.children[idx] = new Trie();
            }
            node = node.children[idx];
        }
        node.isEnd = true;
    }
    
    public boolean search(String word) {
        Trie f = checkPrefix(word);
        return f != null && f.isEnd;
    }
    
    public boolean startsWith(String prefix) {
        return checkPrefix(prefix) != null;
    }

    public Trie checkPrefix(String word){
        Trie node = this;
        for(char c : word.toCharArray()){
            int idx = c - 'a';
            if(node.children[idx] == null) return null;
            node = node.children[idx];
        }
        return node;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

10:207. 课程表 - 力扣(LeetCode) 

题意:给定num节课,以及几对先修课程的关系,如果一门课程有先修课程,那么必须要先学完先修课程,才能学这门课程,让你判断有没有可能学完所以课程。

思路:我们可以通过题目给的样例看出来,如果不满足情况,那么就意味有自相矛盾的地方这在图论中就意味着有存在我们可以通过简单的拓扑排序判断有无环

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<Integer> []e = new ArrayList[numCourses];
        for(int i = 0; i < numCourses; i ++){
            e[i] = new ArrayList<>();
        }
        int[] ind = new int[numCourses];
        int cnt = 0;
        Queue<Integer> q = new LinkedList<>();

        for(int[] info : prerequisites){
            int u = info[1];
            int v = info[0];
            e[u].add(v);
            ind[v] ++;
        }

        for(int i = 0; i < numCourses; i ++){
            if(ind[i] == 0){
                q.add(i);
            }
        }

        while(!q.isEmpty()){
            cnt ++;
            int t = q.poll();
            for(int v : e[t]){
                ind[v] --;
                if(ind[v] == 0){
                    q.add(v);
                }
            }
        }
        return cnt == numCourses;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到