字节面试高频算法题

无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)

复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int[] cnt = new int[128];
        int left = 0;
        char[] chars = s.toCharArray();
        int ans = 0;
        for(int right = 0; right < n; right++){
            cnt[chars[right]]++;
            while(cnt[chars[right]] > 1){
                cnt[chars[left]]--;
                left++;
            }
            ans = Math.max(right - left + 1, ans);
        }

        return ans;
    }
}

岛屿数量

200. 岛屿数量 - 力扣(LeetCode)

复制代码
class Solution {
    public int numIslands(char[][] grid) {
        int cnt = 0;
        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                if(grid[i][j] == '1'){
                    dfs(grid, i, j);
                    cnt++;
                }
            }
        }
        return cnt;
    }

    public void dfs(char[][] grid, int i, int j){
        if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != '1')
            return;

        grid[i][j] = '2';
        dfs(grid, i - 1, j);
        dfs(grid, i + 1, j);
        dfs(grid, i, j - 1);
        dfs(grid, i, j + 1);
    }
}

岛屿的最大面积

695. 岛屿的最大面积 - 力扣(LeetCode)

复制代码
class Solution {
    

    public int maxAreaOfIsland(int[][] grid) {
        int maxCnt = 0;
        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                if(grid[i][j] == 1){
                    int curr = dfs(grid, i, j);
                    maxCnt = Math.max(maxCnt, curr);
                }
            }
        }
        return maxCnt;
    }

    public int dfs(int[][] grid, int i, int j){
        if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != 1){
            return 0;
        }
        
        grid[i][j] = 2;
        return 1 + dfs(grid, i - 1, j) + dfs(grid, i + 1, j) + dfs(grid, i, j - 1) + dfs(grid, i, j + 1);

    }
}

二叉树最大宽度

662. 二叉树最大宽度 - 力扣(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 int maxW = 0;
    private List<Integer> firstIds = new ArrayList<>();

    public int widthOfBinaryTree(TreeNode root) {
        dfs(root, 1, 0);
        return maxW;
    }

    public void dfs(TreeNode node, int id, int depth){
        if(node == null) return;
        
        if(firstIds.size() == depth){
            firstIds.add(id); //记录当前层的最左侧节点id
        }

        maxW = Math.max(maxW, id - firstIds.get(depth) + 1);

        dfs(node.left, id * 2, depth + 1);
        dfs(node.right, id * 2 + 1, depth + 1);
    }
}

LRU 缓存

146. LRU 缓存 - 力扣(LeetCode)

复制代码
class LRUCache {

    private int capacity;
    private Map<Integer, Integer> map = new LinkedHashMap<>();

    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    
    public int get(int key) {
        Integer value = map.remove(key);
        if(value == null){
            return -1;
        }
        map.put(key, value);
        return value;
    }
    
    public void put(int key, int value) {
        Integer val = map.remove(key);
        if(val != null){
            map.put(key, value);
            return;
        }
        if(capacity == map.size()){
            int index = map.keySet().iterator().next();
            map.remove(index);
           
        }
        map.put(key, value);
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

最小栈

155. 最小栈 - 力扣(LeetCode)

复制代码
class MinStack {
    
    private Deque<Integer> stack;
    private Deque<Integer> minStack;


    public MinStack() {
        stack = new ArrayDeque<>();
        minStack = new ArrayDeque<>();

    }
    
    public void push(int val) {
        if(minStack.isEmpty() || val <= minStack.getLast()){
            minStack.addLast(val);
        }
        stack.addLast(val);
    }
    
    public void pop() {
        if(stack.getLast().equals(minStack.getLast())){
            
            minStack.removeLast();
        }
        stack.removeLast();
    }
    
    public int top() {
        return stack.getLast();
    }
    
    public int getMin() {
        return minStack.getLast();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

整数转罗马数字

12. 整数转罗马数字 - 力扣(LeetCode)

复制代码
class Solution {
    public String intToRoman(int num) {
        int[] val = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        String[] off = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < val.length; i++){
            while(num >= val[i]){
                num -= val[i];
                sb.append(off[i]);
            }
        }

        return sb.toString();
    }
}

求根节点到叶节点数字之和

129. 求根节点到叶节点数字之和 - 力扣(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 {
    public int sumNumbers(TreeNode root) {
        if(root == null) return 0;
        return dfs(root, 0);
    }

    public int dfs(TreeNode node, int i){
        if(node == null) return 0;
        int temp = i * 10 + node.val;
        if(node.left == null && node.right == null){
            return temp;
        }
        return dfs(node.left, temp) + dfs(node.right, temp);
    }
}

寻找旋转排序数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

复制代码
class Solution {
    public int findMin(int[] nums) {
        int l = 0;
        int r = nums.length - 1;
        while(l < r){
            int mid = l + r >>> 1;
            if(nums[mid] < nums[r]){
                //mid可能是最小值或者最小值在更左侧
                r = mid;
            }else{
                // mid肯定不是最小值,最小值在右边
                l = mid + 1;
            }
        }

        return nums[l];
    }
}

最长递增子序列的个数

673. 最长递增子序列的个数 - 力扣(LeetCode)

复制代码
class Solution {
    public int findNumberOfLIS(int[] nums) {
        int n = nums.length;

        int[] dp = new int[n];
        int[] count = new int[n];
        Arrays.fill(dp, 1);
        Arrays.fill(count, 1);//以nums[i]结尾的最长递增子序列长度
        int maxLen = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < i; j++){
                if(nums[i] > nums[j]){
                    if(dp[j] + 1 > dp[i]){ //之前的序列+1更大
                        dp[i] = dp[j] + 1;
                        count[i] = count[j];
                    }else if(dp[j] + 1 == dp[i]){//找到了相同长度的序列
                        count[i] += count[j];
                    }
                }
            }
            maxLen = Math.max(maxLen, dp[i]);
        }
        int cnt = 0;
        for(int i = 0; i < n; i++){
            if(maxLen == dp[i]){
                cnt += count[i];
            }
        }
        return cnt;
    }
}

零钱兑换

322. 零钱兑换 - 力扣(LeetCode)

复制代码
class Solution {
    public int coinChange(int[] coins, int amount) {
        int n = coins.length;
        int[] dp = new int[amount + 1];//dp表示凑成某个金额所需要的最少硬币数
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for(int i = 0; i < n; i++){
            for(int j = coins[i]; j <= amount; j++){
                if(dp[j - coins[i]] != Integer.MAX_VALUE){
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
                }
            }
        }

        return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
    }
}

合并 K 个升序链表

23. 合并 K 个升序链表 - 力扣(LeetCode)

复制代码
/**
 * 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 ListNode mergeKLists(ListNode[] lists) {
        Queue<ListNode> pq = new PriorityQueue<>((p, q) -> (p.val - q.val));
        for(ListNode list : lists){
            if(list != null){
                pq.offer(list);
            }
           
        }
        //按照队首排序
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        while(!pq.isEmpty()){
            ListNode node = pq.poll(); //取出并删除
            cur.next = node;
            cur = cur.next;
            if(node.next != null) pq.offer(node.next);
        }
        return dummy.next;
    }
}

相同的树

100. 相同的树 - 力扣(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 {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //如果都为空,true
        if(p == null && q == null) return true;
        //此外如果有一个为空,false
        if(p == null || q == null) return false;
        //如果不为空,但是value不同,false
        if(p.val != q.val) return false;

        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

另一棵树的子树

572. 另一棵树的子树 - 力扣(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 {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null) return false;

        return isSametree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);

    }

    public boolean isSametree(TreeNode p, TreeNode q){
        if(p == null && q == null) return true;
        if(p == null || q == null) return false;
        if(p.val != q.val) return false;

        return isSametree(p.left, q.left) && isSametree(p.right, q.right);
    }
}

不同路径

62. 不同路径 - 力扣(LeetCode)

复制代码
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(i == 0 || j == 0){
                    dp[i][j] = 1;
                }else{
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
}

字符串相加

415. 字符串相加 - 力扣(LeetCode)

复制代码
class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder sb = new StringBuilder();
        int n = num1.length() - 1;
        int m = num2.length() - 1;
        int flag = 0;
        while(n >= 0 || m >= 0){
            int a = n >= 0 ? num1.charAt(n) - '0' : 0;
            int b = m >= 0 ? num2.charAt(m) - '0' : 0;
            int sum = a + b + flag;
            flag = sum / 10;
            sb.append(sum % 10);
            n--;
            m--;
        }
        if(flag == 1) sb.append(1);
        return sb.reverse().toString();
    }
}

合并两个有序数组

88. 合并两个有序数组 - 力扣(LeetCode)

复制代码
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int index = m + n - 1;
        while(m - 1 >= 0 && n - 1 >= 0){
            if(nums1[m - 1] >= nums2[n - 1]){
                nums1[index] = nums1[m - 1];
                m--;
            }else{
                nums1[index] = nums2[n - 1];
                n--;
            }

            index--;
            
        }
        while(n - 1 >= 0){
            nums1[index] = nums2[index];
            index--;
            n--;
        }
    }
}

三数之和(重要)

15. 三数之和 - 力扣(LeetCode)

复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int n = nums.length;
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums);

        for(int i = 0; i < n - 2; i++){ //相当于每次拿一个num,剩下的数通过二分是否能得到和为-num
            int num = nums[i];
            if(i > 0 && num == nums[i - 1]) continue;
            if(num + nums[i + 1] + nums[i + 2] > 0) break;
            if(num + nums[n - 2] + nums[n - 1] < 0) continue;

            
            int l = i + 1;
            int r = n - 1;
            while(l < r){
                if(num + nums[l] + nums[r] > 0) r--;
                else if(num + nums[l] + nums[r] < 0) l++;
                else{
                    ans.add(List.of(num, nums[l], nums[r]));
                    for(l++; l < r && nums[l] == nums[l - 1]; l++);
                    for(r--; l < r && nums[r] == nums[r + 1]; r--);
                }
            }
        }


        return ans;
    }
}

二叉树的锯齿形层序遍历

103. 二叉树的锯齿形层序遍历 - 力扣(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 {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        List<List<Integer>> ans = new ArrayList<>();
         
        if(root != null){
            q.offer(root);
        }

        while(!q.isEmpty()){
            List<Integer> list = new ArrayList<>();
            for(int i = q.size(); i > 0; i--){
                TreeNode node = q.poll();
                list.add(node.val);
                if(node.left != null) q.offer(node.left);
                if(node.right != null) q.offer(node.right);
            }
            if(ans.size() % 2 != 0) Collections.reverse(list);
            ans.add(list);
        }

        return ans;
    }
}

接雨水

42. 接雨水 - 力扣(LeetCode)

复制代码
class Solution {
    public int trap(int[] height) {
        int n = height.length;
        int l = 0;
        int r = n - 1;
        int preMax = 0;
        int sufMax = 0;
        int sum = 0;
        while(l < r){
            preMax = Math.max(preMax, height[l]);
            sufMax = Math.max(sufMax, height[r]);
            if(preMax < sufMax){
                sum += preMax - height[l];
                l++;
            }else{
                sum += sufMax - height[r];
                r--;
            }
        }
        return sum;
    }
}

复原 IP 地址

93. 复原 IP 地址 - 力扣(LeetCode)

暴力匹配
复制代码
class Solution {
    public List<String> restoreIpAddresses(String s) {
        List<String> ans = new ArrayList<>();
        int n = s.length();
        for(int i = 1; i < 4 && i < n; i++){
            for(int j = i + 1; j < i + 4 && j < n; j++){
                for(int k = j + 1; k < j + 4 && k < n; k++){
                    String s1 = s.substring(0, i);
                    String s2 = s.substring(i, j);
                    String s3 = s.substring(j, k);
                    String s4 = s.substring(k);

                    if(valid(s1) && valid(s2) && valid(s3) && valid(s4)){
                        ans.add(s1 + "." + s2 + "." + s3 + "." + s4);
                    }
                }
            }
        }

        return ans;
    }

    public boolean valid(String str){
        if(str.length() == 0 || str.length() > 3) return false;
        if(str.length() > 1 && str.charAt(0) == '0') return false;
        int num = Integer.parseInt(str);
        return num >=0 && num <= 255;
    }
}
回溯法
复制代码
class Solution {

    List<String> ans = new ArrayList<>();

    public List<String> restoreIpAddresses(String s) {
        if(s.length() < 4 || s.length() > 12) return ans;
        
        backtrack(s, 0, new ArrayList<>());
        return ans;
    }

    public void backtrack(String s, int start, List<String> temp){
        //中止条件 temp已经有四段
        if(temp.size() == 4){
            if(start == s.length()){
                ans.add(String.join(".", temp));
            }
            return;
        }

        for(int len = 1; len <= 3; len++){
            if(start + len > s.length()) break;

            String str = s.substring(start, start + len);
            if(isValid(str)){
                temp.add(str);
                backtrack(s, start + len, temp);
                temp.remove(temp.size() - 1);
            }
        }

    }

    public boolean isValid(String s){
        if(s.length() > 1 && s.charAt(0) == '0') return false;

        int num = 0;
        for(int i = 0; i < s.length(); i++){
            num = num * 10 + (s.charAt(i) - '0');
        }

        if(num >= 0 && num <= 255) return true;
        return false;
    }
}

最大正方形

dpij 表示以 matrixij 为右下角的的最大正方形的边长。

复制代码
class Solution {
    public int maximalSquare(char[][] matrix) {
        int n = matrix.length;
        int m = matrix[0].length;
        int[][] dp = new int[n][m];
        int edge = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(matrix[i][j] == '1'){
                    if(i == 0 || j == 0){ //如果是1,并且在第一行第一列,那么边长就是1
                        dp[i][j] = 1;
                    }else{ //否则以ij为右下角的正方形的边长是由上、左上、左决定的,如果当前边长想为k,这三个点至少为k-1
                        dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i][j - 1]) + 1;
                    }
                    edge = Math.max(edge, dp[i][j]);
                }
            }
        }

        return edge * edge;
    }
}

连续的子数组和

523. 连续的子数组和 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        int n = nums.length;
        int[] s = new int[n + 1];
        s[0] = 0;
        for(int i = 1; i <= n; i++){
            s[i] = s[i - 1] + nums[i - 1];
        } //计算前缀和
        for(int i = 1; i <= n; i++){
            for(int j = i + 1; j <= n; j++){
                if((s[j] - s[i - 1]) % k == 0 && j - i >= 1){
                    return true;
                }
            }
        }

        return false;
    }
}

class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        int n = nums.length;
        int preSum = 0;
        map.put(0, - 1);
        for(int i = 0; i < n; i++){
            preSum += nums[i];
            int mod = preSum % k;
            if(map.containsKey(mod)){ //多次遇到这个余数
                if(i - map.get(mod) >= 2){
                    return true;
                } 
            }else{ //如果是第一次put
                map.put(mod, i);
            }
        }

        return false;
    }
}

路径总和

112. 路径总和 - 力扣(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 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        if(root.left == null && root.right == null) return root.val == targetSum;

        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

/**
 * 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 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        return travelPath(root, targetSum - root.val);
    }

    public boolean travelPath(TreeNode root, int count){
        if(root.left == null && root.right == null && count == 0) return true;
        if(root.left == null && root.right == null) return false;

        if(root.left != null){
            count -= root.left.val;
            if(travelPath(root.left, count)) return true;
            count += root.left.val;
        }

        if(root.right != null){
            count -= root.right.val;
            if(travelPath(root.right, count)) return true;
            count += root.right.val;
        }

        return false;
    }
}

从前序与中序遍历序列构造二叉树(重点)

105. 从前序与中序遍历序列构造二叉树 - 力扣(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 {

    Map<Integer, Integer> map;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<>();
        for(int i = 0; i < inorder.length; i++){
            map.put(inorder[i], i);
        }

        return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length);
    }

    public TreeNode findNode(int[] preorder, int preStart, int preEnd, int[]inorder, int inStart, int inEnd){
        if(preStart >= preEnd || inStart >= inEnd) return null;
        //从前序遍历找到根节点,找到根节点在中序遍历的位置,分割左右子树,重复以上过程
        int rootIndex = map.get(preorder[preStart]); //找到中序遍历中根节点的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);
        //分割数组
        int lenofLeft = rootIndex - inStart;//左子树的长度
        root.left = findNode(preorder, preStart + 1, preStart + 1 + lenofLeft, inorder, inStart, rootIndex);

        root.right = findNode(preorder, preStart + 1 + lenofLeft, preEnd, inorder, rootIndex + 1, inEnd);

        return root;
    }
}

跳跃训练

LCR 127. 跳跃训练 - 力扣(LeetCode)

复制代码
class Solution {
    public int trainWays(int num) {
        int a = 1, b = 1, sum = 0;
        //a存f(n),b存f(n + 1), sum计算f(n + 1)
        for(int i = 0; i < num; i++){
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }

        return a;
    }
}

全排列

46. 全排列 - 力扣(LeetCode)

复制代码
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        int n = nums.length;
        List<List<Integer>> ans = new ArrayList<>();
        boolean[] used = new boolean[n];
        dfs(ans, nums, 0, used, new ArrayList<>());
        return ans;
    }

    public void dfs(List<List<Integer>> ans, int[] nums, int depth, boolean[] used, List<Integer> tmp){
        if(depth == nums.length){
            ans.add(new ArrayList(tmp));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(!used[i]){
                tmp.add(nums[i]);
                used[i] = true;
                dfs(ans, nums, depth + 1, used, tmp);
                used[i] = false;
                tmp.remove(tmp.size() - 1);
            }
        }

    }
}

K 个一组反转链表

25. K 个一组翻转链表 - 力扣(LeetCode)

复制代码
/**
 * 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 ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        while(true){
            ListNode end = pre;
            for(int i = 0; i < k && end != null; i++) end = end.next;
            if(end == null) break;
            ListNode cur = pre.next;
            for(int i = 1; i < k; i++){
                ListNode next = cur.next;
                cur.next = next.next;
                next.next = pre.next;
                pre.next = next;
            }
            pre = cur;
        }

        return dummy.next;
    }
}

最长回文子串

5. 最长回文子串 - 力扣(LeetCode)

复制代码
class Solution {

    private int start = 0, end = 0;

    public String longestPalindrome(String s) {
        int n = s.length();
        if(n < 2) return s;

        for(int i = 0; i < n - 1; i++){
            reform(s, i, i);
            reform(s, i, i + 1);
        }

        return s.substring(start, end);
    }

    public void reform(String s, int l, int r){
        while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){
            l--;
            r++;
        }

        int len = r - l - 1;
        if(len > end - start){
            start = l + 1;
            end = r;
        }
    }
}

划分为 K 个相等的子集

698. 划分为k个相等的子集 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean canPartitionKSubsets(int[] nums, int k) {
        int sum = 0;
        for(int num : nums) sum += num;
        if(sum % k != 0) return false;

        int target = sum / k;
        int[] bucket = new int[k];

        return backTrack(nums, nums.length - 1, bucket, target);
    }

    public boolean backTrack(int[] nums, int index, int[] bucket, int target){
        if(index < 0) return true;
        for(int i = 0; i < bucket.length; i++){
            if(bucket[i] + nums[index] <= target){
                bucket[i] += nums[index];

                if(backTrack(nums, index - 1, bucket, target)){
                    return true;
                }

                bucket[i] -= nums[index];
            }

            if(bucket[i] == 0) break;
        }

        return false;
    }
}

验证二叉搜索树

98. 验证二叉搜索树 - 力扣(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 long maxVal = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        if(root == null) return true;

        boolean left = isValidBST(root.left);
        if(root.val > maxVal){
            maxVal = root.val;
        }else{
            return false;
        }

        boolean right = isValidBST(root.right);

        return left && right;

    }
}

旋转链表

61. 旋转链表 - 力扣(LeetCode)

用 list 存链表,用新数组存旋转后的 list

复制代码
/**
 * 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 ListNode rotateRight(ListNode head, int k) {
        List<Integer> list = new ArrayList<>();
        
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
        int n = list.size();
        int[] nums = new int[n + 1];
        for(int i = 1; i <= n; i++){
            int nextIndex = (i + k) % n;
            if(nextIndex == 0){
                nums[n] = list.get(i - 1);
            }else{
                nums[nextIndex] = list.get(i - 1);
            }
        }

        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        for(int i = 1; i <= n; i++){
            cur.next = new ListNode(nums[i]);
            cur = cur.next;
        }

        return dummy.next;
    }
}

/**
 * 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 ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null || k == 0) return head;

        ListNode oldEnd = head;
        int n = 1;
        while(oldEnd.next != null){
            n++;
            oldEnd = oldEnd.next;
        }//old已经到达尾部

        k = k % n;
        

        oldEnd.next = head; //成环
        ListNode newEnd = head;
        for(int i = 0; i < n - k - 1; i++){
            newEnd = newEnd.next;
        }
        
        ListNode ans = newEnd.next;
        newEnd.next = null;

        return ans;

    }
}

搜索旋转排序数组

33. 搜索旋转排序数组 - 力扣(LeetCode)

复制代码
class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l < r){
            int mid = l + r >>> 1;
            if(check(nums, target, mid)) r = mid;
            else l = mid + 1;
        }
        return nums[l] == target ? l : -1;
    }

    public boolean check(int[] nums, int target, int mid){
        int last = nums[nums.length - 1]; //取最后一位
        int cur = nums[mid];
        if(cur < last){ //mid在第二段,想要缩短r的话
            return cur >= target || target > last; //要么target也在第二段并且cur>=target,要么target>last,target在第一段
        }
        //mid在第一段
        return cur >= target && target > last;
    }
}

搜索旋转排序数组 II

81. 搜索旋转排序数组 II - 力扣(LeetCode)

复制代码
class Solution {
    public boolean search(int[] nums, int target) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l < r){
            int mid = l + r >>> 1;
            if(nums[mid] == target) return true;
            if(nums[mid] == nums[r]){
                r--;
                continue;
            }
            if(check(nums, target, mid, r)) r = mid;
            else l = mid + 1;
        }

        return nums[l] == target;
    }

    public boolean check(int[] nums, int target, int mid, int r){
            int cur = nums[mid];
            int last = nums[r];
            
            if(cur < last){
                return cur >= target || target > last;
            }
            return cur >= target && target > last;
    }
}

有序数组的单一元素

540. 有序数组中的单一元素 - 力扣(LeetCode)

复制代码
class Solution {
    public int singleNonDuplicate(int[] nums) {
        int l = 0;
        int r = nums.length - 1;
        while(l < r){
            int mid = l + r >>> 1;
            if(mid % 2 == 1){
                mid--;
            }
            if(nums[mid] == nums[mid + 1]){
                l = mid + 2;
            }else r = mid;
        }

        return nums[l];
    }
}

x 的平方根

69. x 的平方根 - 力扣(LeetCode)

注意 int 溢出的问题,不过耗时非常高。

复制代码
class Solution {
    public int mySqrt(int x) {
    if (x == 0) return 0;
    long ans = 1;
    // 注意:这里的 i 也必须是 long,否则 i*i 依然会先按 int 计算导致溢出
    for (long i = 1; i <= x / i; i++) {
        ans = i;
    }
    return (int) ans;
}
}

class Solution {
    public int mySqrt(int x) {
        if(x < 2) return x;

        int l = 1, r = x / 2;
        int ans = 0;
        while(l <= r){
            int mid = l + r >>> 1;
            if(mid <= x / mid){
                ans = mid;
                l = mid + 1;
            }else{
                r = mid - 1;
            }
        }

        return ans;
    }
}

前 K 个高频元素

347. 前 K 个高频元素 - 力扣(LeetCode)

复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();

        for(int num : nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        PriorityQueue<Integer> pq = new PriorityQueue<>((p, q) -> (map.get(q) - map.get(p))); //大根堆

        for(Integer num : map.keySet()){
            pq.offer(num);
        }
        int[] ans = new int[k];
        for(int i = 0; i < k; i++){
            ans[i] = pq.poll();
        }

        return ans;
    }
}

最小路径和

64. 最小路径和 - 力扣(LeetCode)

复制代码
class Solution {
    public int minPathSum(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        int[][] dp = new int[n][m];
        dp[0][0] = grid[0][0];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(i == 0 && j == 0) continue;
                else if(i == 0 && j != 0) dp[i][j] = dp[i][j - 1] + grid[i][j];
                else if(j == 0 && i != 0) dp[i][j] = dp[i - 1][j] + grid[i][j];
                else dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }

        return dp[n - 1][m - 1];
    }
}

二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(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 {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        List<List<Integer>> ans = new ArrayList<>();
        if(root == null) return ans;
        q.offer(root);
        while(!q.isEmpty()){
            List<Integer> list = new ArrayList<>();
            for(int i = q.size(); i > 0; i--){
                TreeNode node = q.poll();
                list.add(node.val);
                if(node.left != null) q.offer(node.left);
                if(node.right != null) q.offer(node.right);
            } 
            ans.add(list);
        }

        return ans;
    }
}

有效的字母异位分词

242. 有效的字母异位词 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean isAnagram(String s, String t) {
        char[] charS = s.toCharArray();
        char[] charT = t.toCharArray();
        int[] cntS = new int[128];
        int[] cntT = new int[128];
        

        for(char c : charS) cntS[c]++;
        for(char c : charT) cntT[c]++;

        for(int i = 0; i < 128; i++){
            if(cntS[i] != cntT[i]){
                return false;
            }
        }

        return true;
    }
}

删除被覆盖区间

1288. 删除被覆盖区间 - 力扣(LeetCode)

复制代码
class Solution {
    public int removeCoveredIntervals(int[][] intervals) {
        Arrays.sort(intervals, (a, b) ->(a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]));
        
        int count = intervals.length;
        int maxNum = 0;

        for(int[] num : intervals){
            if(num[1] > maxNum){
                maxNum = num[1]; //更新当前右端点最大值

            }else{ //如果num[1]<= maxNum,说明当前区间会被覆盖
                count--;
            }
        }
        return count;
    }
}

验证回文串

125. 验证回文串 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean isPalindrome(String s) {
        StringBuilder sb = new StringBuilder();
        char[] ch = s.toCharArray();
        //0-9 48-57 A-Z 65-90 a-z 97-
        for(char c : ch){
            if(c >= 'a' && c <= 'z' || c >= '0' && c <= '9'){
                sb.append(c);
            }else if(c >= 'A' && c <= 'Z'){
                sb.append((char)(c + 32));
            }else continue;
        }
        for(int i = 0; i < sb.length(); i++){
            if(sb.charAt(i) != sb.charAt(sb.length() - i - 1)){
                return false;
            }
        }


        return true;
    }
}

字符串相乘

43. 字符串相乘 - 力扣(LeetCode)

复制代码
class Solution {
    public String multiply(String num1, String num2) {

        if(num1.equals("0") || num2.equals("0")) return "0";

        int n = num1.length();
        int m = num2.length();
        int[] ans = new int[n + m];

        for(int i = n - 1; i >= 0; i--){
            int a = num1.charAt(i) - '0';
            for(int j = m - 1; j >= 0; j--){
                int b = num2.charAt(j) - '0';

                int p1 = i + j; //进位
                int p2 = i + j + 1; //存当前位值
                int sum = a * b + ans[p2];

                ans[p2] = sum % 10;
                ans[p1] += sum / 10;
            }
        }
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < ans.length; i++){
            if(i == 0 && ans[i] == 0) continue;
            sb.append(ans[i]);
        }
        return sb.toString();
    }
}

分割等和子集

416. 分割等和子集 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean canPartition(int[] nums) {
        int n = nums.length;
        if(n == 1) return false;

        int sum = 0;
        for(int i = 0; i < n; i++){
            sum += nums[i];
        }
        if(sum % 2 != 0) return false;
        int target = sum / 2;
        boolean[] dp = new boolean[target + 1];
        dp[0] = true;
        //处理过的元素和恰好为i的子集
        for(int i = 1; i < n; i++){
            for(int j = target; j >= nums[i]; j--){
                dp[j] = dp[j] || dp[j - nums[i]];
                if(dp[target]) return true;
            }
        }

        return false;
    }
}

反转链表

206. 反转链表 - 力扣(LeetCode)

复制代码
/**
 * 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 ListNode reverseList(ListNode head) {
        ListNode cur = head;
        
        

        ListNode pre = null;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

环形链表

141. 环形链表 - 力扣(LeetCode)

复制代码
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null) return false;
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast) return true;
        }

        return false;
    }
}

有效的括号

20. 有效的括号 - 力扣(LeetCode)

复制代码
class Solution {
    public boolean isValid(String s) {
        if(s.length() % 2 != 0) return false;
        Map<Character, Character> map = new HashMap<>();
        map.put('(', ')');
        map.put('{', '}');
        map.put('[', ']');
        Deque<Character> q = new ArrayDeque<>();
        char[] ch = s.toCharArray();
        for(char c : ch){
            if(map.containsKey(c)){
                q.addLast(c);
            }else{
                if(q.isEmpty() || map.get(q.removeLast()) != c){
                    return false;
                }
            }
        }
        return q.isEmpty();
    }
}

LRU 缓存

146. LRU 缓存 - 力扣(LeetCode)

复制代码
class LRUCache {

    private int capacity;
    private Map<Integer, Integer> map = new LinkedHashMap<>();

    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    
    public int get(int key) {
        Integer value = map.remove(key);
        if(value == null) return -1;
        map.put(key, value);
        return value;
    }
    
    public void put(int key, int value) {
        Integer val = map.remove(key);
        if(val != null){
            map.put(key, value);
            return;
        }

        if(map.size() == capacity){
            Integer index = map.keySet().iterator().next();
            map.remove(index);
            
        }
        map.put(key, value);
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

数组中的第 K 个最大元素

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

复制代码
class Solution {
    public int findKthLargest(int[] nums, int k) {
        List<Integer> list = new ArrayList<>();
        for(int num : nums){
            list.add(num);
        }
        return searchK(list, k);
    }

    public int searchK(List<Integer> list, int k){
        int n = list.size();
        Random r = new Random();
        int pivot = list.get(r.nextInt(n));

        List<Integer> small = new ArrayList<>();
        List<Integer> equal = new ArrayList<>();
        List<Integer> big = new ArrayList<>();

        for(int i : list){
            if(i > pivot) big.add(i);
            else if(i < pivot) small.add(i);
            else equal.add(i);
        }

        if(k <= big.size()){
            return searchK(big, k);
        }
        if(n - k < small.size()){
            return searchK(small, k - (n - small.size()));
        }

        return pivot;
    }
}

二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(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 {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>(); 
        if(root == null) return ans;
        Deque<TreeNode> q = new ArrayDeque<>();
        q.addLast(root);
        while(!q.isEmpty()){
            int n = q.size();
            List<Integer> tmp = new ArrayList<>();
            for(int i = n; i > 0; i--){
                TreeNode node = q.removeFirst();
                tmp.add(node.val);
                if(node.left != null) q.addLast(node.left);
                if(node.right != null) q.addLast(node.right);
            }
            ans.add(tmp);
        }

        return ans;
    }
}
相关推荐
野生技术架构师1 小时前
Java 23 种设计模式:从踩坑到精通 —— 开篇及系列介绍
java·开发语言·设计模式
aqiu1111111 小时前
python02
算法
折哥的程序人生 · 物流技术专研1 小时前
《Java 100 天进阶之路》第93篇:Redis实战应用:缓存策略与分布式锁(2026版)
java·redis·缓存·面试·架构·求职招聘
瓦特what?1 小时前
位运算核心技巧与应用
java·jvm·算法
无限码力1 小时前
阿里算法岗 0530笔试真题 - 荆棘林的最优砍断计划
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试真题·阿里巴巴笔试真题
人道领域1 小时前
【LeetCode刷题日记】90.子集Ⅱ--- 归纳题解
java·开发语言·leetcode
随意起个昵称1 小时前
线性dp-LIS题目5(导弹拦截,二分优化)
c++·算法·动态规划
winlife_1 小时前
全程用 AI 做一款商业级手游 · EP10 道具系统:让三个按钮真正改变棋盘
windows·算法·unity·ai编程·游戏开发·mcp·玩法系统
计算机安禾2 小时前
【数据库系统原理】第16篇:范式理论(下):多值依赖与第四范式——消除非平凡的非函数依赖
算法