LeetCode入门篇

163 阅读1分钟

一、算法思想

1.二分法

2.双指针

15.三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

思路:定住一个数,剩下两个数双向奔赴

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        int len = nums.length;
        Arrays.sort(nums);
        for(int i = 0; i < len - 2;i++) {
            if(i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int start = i + 1;
            int end = len - 1;
            while(start < end) {
                int sum = nums[i] + nums[start] + nums[end];
                if(sum == 0) {
                    res.add(List.of(nums[i], nums[start], nums[end]));
                    start++;
                    end--;
                    while(start < end && nums[start] == nums[start - 1]) {
                        start++;
                    }
                    while(start < end && nums[end] == nums[end + 1]) {
                        end--;
                    }
                } else if(sum < 0) {
                    start++;
                } else {
                    end--;
                }
            }
        }
        return res;
    }
}

18.四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n a、b、c 和 d 互不相同 nums[a] + nums[b] + nums[c] + nums[d] == target 你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

思路:定住两个数,剩下两位双向奔赴

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        int len = nums.length;
        Arrays.sort(nums);
        for(int i = 0; i < len -3;i++) {
            if(i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            for(int j = i + 1;j < len;j++) {
                if(j > i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                int start = j + 1;
                int end = len - 1;
                while(start < end) {
                    int fourSum = nums[i] + nums[j] + nums[start] + nums[end];
                    if(fourSum == target) {
                        res.add(List.of(nums[i], nums[j], nums[start], nums[end]));
                        start++;
                        end--;
                        while(start < end && nums[start] == nums[start - 1]) {
                            start++;
                        }
                        while(start < end && nums[end] == nums[end + 1]) {
                            end--;
                        }
                    } else if(fourSum > target) {
                        end--;
                    } else {
                        start++;
                    }
                }
            }
        }
        return res;
    }
}

3.滑动窗口

滑动窗口是双指针的变形,不是左右指针双向奔赴,而是快慢指针沿同一方向移动。

3.无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

思路:快指针往前走,直到遇到重复的字符,快指针停下,慢指针向前走

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = -1;
        int len = s.length();
        int slow = 0;
        int fast = slow;
        Set<Character> set = new HashSet<>();
        while(fast < len) {
            if(set.add(s.charAt(fast))) {
                res = Math.max(res, set.size());
                fast++;
            } else {
                set.remove(s.charAt(slow++));
            }
        }
        return Math.max(res, 0);
    }
}

219. 存在重复元素 II

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

输入:nums = [1,2,3,1], k = 3
输出:true

代码:初始化最大窗口k,窗口没有重复字符,快慢指针同时向前移

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        int len = nums.length;
        if(len < 2) {
            return false;
        }
        Set<Integer> set = new HashSet<>();
        k = Math.min(len - 1, k);
        for(int i = 0; i < k;i++) {
            if(!set.add(nums[i])) {
                    return true;
                }
        }
        int slow = 0;
        int fast = k;
        while(fast < len) {
            if(!set.add(nums[fast])) {
                return true;
            }
            set.remove(nums[slow++]);
            fast++;
        }   
        return false;   
    }
}

4.深度优先搜索

5.广度优先搜索

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称

示例 1:

img

输入:root = [1,2,2,3,4,4,3]
输出:true

思路:关键点是树1的左节点等于树2的右节点,树1的右节点等于树2的左节点。从Queue中一次poll两次比较。

class Solution {
    public boolean isSymmetric(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root.left);
        queue.offer(root.right);
        while(!queue.isEmpty()) {
            TreeNode node1 = queue.poll();
            TreeNode node2 = queue.poll();
            if(node1 == null && node2 == null) {
                continue;
            } else if(node1 == null || node2 == null) {
                return false;
            } else if(node1.val != node2.val) {
                return false;
            } else {
                queue.offer(node1.left);
                queue.offer(node2.right);
                queue.offer(node1.right);
                queue.offer(node2.left);
            }
        }
        return true;
    }
}

103. 二叉树的锯齿形层序遍历

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

思路:通过queue的大小来明确遍历树时的层级

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean left2Right = true;
        while(!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> curLevel = new ArrayList<>();
            for(int i = 0;i < size;i++) {
                TreeNode node = queue.poll();
                if(node != null) {
                    queue.offer(node.left);
                    queue.offer(node.right);
                    if(left2Right) {
                        curLevel.add(node.val);
                    } else {
                        curLevel.add(0, node.val);
                    }
                }
            }
            if(!curLevel.isEmpty()) {
                res.add(curLevel);
            }
            left2Right = !left2Right;
        }
        return res;
    }
}

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例: 给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

思路:通过queue的大小来明确遍历树时的层级

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int dept = 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            dept++;
            int size = queue.size();
            for(int i = 0;i < size;i++) {
                TreeNode node = queue.poll();
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
        }
        return dept;
    }
}

6.回溯法

7.动态规划

8.贪心

二、数据结构

1.字符串

2.数组

3.链表

4.队列

5.栈

6.哈希表

7.二叉树

8.图