
 
 
1.栈与队列(简单)
 
 
01-用两个栈实现队列
 
class CQueue {
    
    Deque<Integer> stack1;
    
    Deque<Integer> stack2;
    public CQueue() {
        stack1 = new LinkedList<>();
        stack2 = new LinkedList<>();
    }
    public void appendTail(int value) {
        
        stack1.push(value);
    }
    public int deleteHead() {
        if(stack2.isEmpty()) {
            
            if(stack1.isEmpty()) {
                
                return -1;
            }
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        
        return stack2.pop();
    }
}
 
 
02-包含min函数的栈
 
class MinStack {
    
    Deque<Integer> stack1;
    
    Deque<Integer> stack2;
    public MinStack() {
        stack1 = new LinkedList<>();
        stack2 = new LinkedList<>();
    }
    
    public void push(int x) {
        
        stack1.push(x);
        
        if(x < min()) {
            stack2.push(x);
        } else {
            stack2.push(min());
        }
    }
    
    public void pop() {
        
        stack1.pop();
        stack2.pop();
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        
        if(stack2.isEmpty()) {
            return Integer.MAX_VALUE;
        }
        return stack2.peek();
    }
}
 
 
2.链表(简单)
 
 
03-从尾到头打印链表
 
class Solution {
    private int[] result;
    private int length;
    public int[] reversePrint(ListNode head) {
        if(head == null) return new int[]{};
        dfs(head, 0);
        return result;
    }
    public void dfs(ListNode node, int index) {
        if(node == null) {
            
            result = new int[length];
            return;
        }
        length++;
        dfs(node.next, index + 1);
        result[length - index - 1] = node.val;
    }
}
 
 
04-反转链表
 
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null) return null; 
        
        ListNode prev = null, next = head.next;
        while(next != null) {
            
            head.next = prev;
            
            prev = head;
            
            head = next;
            
            next = head.next;
        }
        head.next = prev;
        return head;   
    }
}
 
 
05-复杂链表的复制
 
class Solution {
    public Node copyRandomList(Node head) {
        
        if(head == null) return null;
        Map<Node, Node> map = new HashMap<>();
        for(Node node = head; node != null; node = node.next) {
            map.put(node, new Node(node.val));
        }
        for(Node node = head; node != null; node = node.next) {
            map.get(node).next = map.get(node.next);
            map.get(node).random = map.get(node.random);
        }
        return map.get(head);
    }
}
 
 
3.字符串(简单)
 
 
06-替换空格
 
class Solution {
    public String replaceSpace(String s) {
        StringBuilder sb = new StringBuilder();
        for(char c : s.toCharArray()) {
            if(c == ' ') {
                sb.append("%20");
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
 
 
07-左旋转字符串
 
class Solution {
    public String reverseLeftWords(String s, int n) {
        return s.substring(n) + s.substring(0, n);
    }
}
 
 
4.查找算法(简单)
 
 
08-数组中重复的数字
 
class Solution {
    public int findRepeatNumber(int[] nums) {
        
        int[] hash = new int[nums.length];
        for(int i = 0; i < nums.length; i++) {
            if(++hash[nums[i]] > 1) {
                return nums[i];
            }
        }
        return -1;
    }
}
 
 
09-在排序数组中查找数字 I
 
class Solution {
    public int search(int[] nums, int target) {
        
        
        
        int left = 0, right = nums.length, count = 0;
        
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        
        while(left < nums.length && nums[left++] == target) {
            count++;
        }
        return count;
    }
}
 
 
10- (0~n-1)中缺失的数字
 
class Solution {
    public int missingNumber(int[] nums) {
        int n = nums.length, left = 0, right = n - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] == mid) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left == nums[n - 1] ? n : left;
    }
}
class Solution {
    public int missingNumber(int[] nums) {
        int result = nums.length;
        for(int i = 0; i < nums.length; i++) {
            result ^= nums[i];
            result ^= i;
        }
        return result;
    }
}
 
 
5.查找算法(中等)
 
 
11-二维数组中的查找
 
class Solution {
    
    
    
    
    
    
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        int n = matrix.length;
        if(n == 0) {
            return false;
        } 
        
        int i = 0, j = matrix[0].length - 1;
        while(i < n && j >= 0) {
            if(matrix[i][j] == target) {
                return true;
            }
            if(matrix[i][j] < target) {
                i++; 
            } else {
                j--; 
            }
        }
        return false;
    }
}
 
 
12-旋转数组的最小数字
 
class Solution {
    
    
    
    
    
    
    
    
    
    
    
    
    public int minArray(int[] numbers) {
        int left = 0, right = numbers.length - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            
            if(numbers[right] < numbers[mid]) {
                left = mid + 1;
                continue;
            }
            if(numbers[right] > numbers[mid]) {
                right = mid;
                continue;
            }
            right--;
        }
        return numbers[left];
    }
}
 
 
13-第一个只出现一次的字符
 
class Solution {
    public char firstUniqChar(String s) {
        int[] hash = new int[26];
        for(char c : s.toCharArray()) {
            hash[c - 'a']++;
        }
        for(char c : s.toCharArray()) {
            if(hash[c - 'a'] == 1) {
                return c;
            }
        }
        return ' ';
    }
}
 
 
6.搜索与回溯算法(简单)
 
 
14-从上到下打印二叉树
 
class Solution {
    
    public int[] levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<Integer> list = new LinkedList<>();
        
        if(root != null) queue.add(root);
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            list.add(node.val);
            if(node.left != null) {
                queue.offer(node.left);
            }
            if(node.right != null) {
                queue.offer(node.right);
            }
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
    }
}
 
 
15-从上到下打印二叉树 II
 
class Solution {
    
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new LinkedList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        
        if(root == null) {
            return result;
        }
        queue.offer(root);
        while(!queue.isEmpty()) {
            List<Integer> list = new LinkedList<>();
            int size = queue.size();
            for(int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                list.add(node.val);
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
            result.add(list);
        }
        return result;
    }
}
 
 
16-从上到下打印二叉树 III
 
class Solution {
    
    
    
    
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new LinkedList<>();
        LinkedList<TreeNode> queue = new LinkedList<>();
        
        boolean flag = true;
        if(root == null) {
            return result;
        }
        queue.offer(root);
        while(!queue.isEmpty()) {
            List<Integer> list = new LinkedList<>();
            int size = queue.size();
            for(int i = 0; i < size; i++) {
                TreeNode node;
                if(flag) {
                    node = queue.pollFirst();
                } else {
                    node = queue.pollLast();
                }
                list.add(node.val);
                if(flag) {
                    if(node.left != null) {
                        queue.offerLast(node.left);
                    }
                    if(node.right != null) {
                        queue.offerLast(node.right);
                    }
                } else {
                    if(node.right != null) {
                        queue.offerFirst(node.right);
                    }
                    if(node.left != null) {
                        queue.offerFirst(node.left);
                    }     
                }
            }
            flag = !flag;
            result.add(list);
        }
        return result;
    }
}
 
 
7.搜索与回溯算法(简单)
 
 
17-树的子结构
 
class Solution {
    
    
    
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A == null || B == null) return false;
        
        
        
        return dfs(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
    }
    public boolean dfs(TreeNode A, TreeNode B) {
        
        if(B == null) return true;
        
        if(A == null) return false;
        
        return A.val == B.val && dfs(A.left, B.left) && dfs(A.right, B.right);
    }
}
 
 
18-二叉树的镜像
 
class Solution {
    
    public TreeNode mirrorTree(TreeNode root) {
        dfs(root);
        return root;
    }
    public void dfs(TreeNode root) {
        if(root == null) return;
        
        TreeNode left = root.right;
        TreeNode right = root.left;
        root.left = left;
        root.right = right;
        
        dfs(root.left);
        dfs(root.right);
    }
}
 
 
19-对称的二叉树
 
class Solution {
    
    
    
    
    
    
    
    
    
    
    
    
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return dfs(root.left, root.right);
    }
    public boolean dfs(TreeNode left, TreeNode right) {
        if(left == null && right == null) {
            return true;
        }
        if(left == null || right == null) {
            return false;
        }
        return left.val == right.val && dfs(left.left, right.right) && dfs(left.right, right.left);
    }
}
 
 
8.动态规划(简单)
 
 
20-斐波那契数列
 
class Solution {
    public int fib(int n) {
        if(n <= 1) return n;
        
        int[] dp = new int[n + 1];
        dp[1] = 1;
        for(int i = 2; i <= n; i++) {
            dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
        }
        return dp[n];
    }
}
 
 
21-青蛙跳台阶问题
 
class Solution {
    
    public int numWays(int n) {
        if(n <= 1) return 1;
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2; i <= n; i++) {
            dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
        }
        return dp[n];
    }
}
 
 
22-股票的最大利润
 
class Solution {
    
    
    
    public int maxProfit(int[] prices) {
        if(prices.length == 0) {
            return 0;
        }
        int ans = 0, min = prices[0];
        for(int i = 1; i < prices.length; i++) {
            if(min < prices[i]) {
                ans = Math.max(ans, prices[i] - min);
            } else {
                min = prices[i];
            }
        }
        return ans;
    }
}
 
 
9.动态规划(中等)
 
 
23-连续子数组的最大和
 
class Solution {
    
    
    public int maxSubArray(int[] nums) {
        int res = nums[0], sum = 0;
        for(int num : nums) {
            if(sum <= 0) {
                sum = num;
            } else {
                sum += num;
            }
            res = Math.max(res, sum);
        }
        return res;
    }
}
 
 
24-礼物的最大价值
 
class Solution {
    
    
    
    
    
    
    
    public int maxValue(int[][] grid) {
        int n = grid.length, m = grid[0].length;
        int[][] dp = new int[n + 1][m + 1];
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[n][m];
    }
}
 
 
10.动态规划(中等)
 
 
25-把数字翻译成字符串
 
class Solution {
    
    
    public int translateNum(int num) {
        char[] cs = String.valueOf(num).toCharArray();
        int n = cs.length;
        
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2; i <= n; i++) {
            int j = (cs[i - 2] - '0') * 10 + (cs[i - 1] - '0');
            if(j >= 10 && j <= 25) {
                dp[i] = dp[i - 1] + dp[i - 2];
            } else {
                dp[i] = dp[i - 1];
            }
        }
        return dp[n];
    }
}
 
 
26-最长不含重复字符的子字符串
 
class Solution {
    
    
    
    
    
    
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<>();
        char[] cs = s.toCharArray();
        int res = 0;
        
        for(int left = 0, right = 0; right < cs.length; right++) {
            while(set.contains(cs[right])) {
                set.remove(cs[left++]);
            }
            set.add(cs[right]);
            res = Math.max(res, set.size());
        }
        return res;
    }
}
 
 
11.双指针(简单)
 
 
27-删除链表的节点
 
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        if(head == null) {
            return null;
        }
        if(head.val == val) {
            return head.next;
        }
        head.next = deleteNode(head.next, val);
        return head;
    }
}
 
 
28-链表中倒数第k个节点
 
class Solution {
    
    
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode left = head, right = head;
        for(int i = 0; i < k; i++) {
            right = right.next;
        }
        while(right != null) {
            left = left.next;
            right = right.next;
        }
        return left;
    }
}
 
 
12.双指针(简单)
 
 
29-合并两个排序的链表
 
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        if(l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        }
        l2.next = mergeTwoLists(l1, l2.next);
        return l2;
    }
}
 
 
30-两个链表的第一个公共节点
 
public class Solution {
    
    
    
    
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) {
            return null;
        }
        ListNode a = headA, b = headB;
        
        while(a != b) {
            a = a == null ? headB : a.next;
            b = b == null ? headA : b.next;
        }
        return a;
    }
}
 
 
13.双指针(简单)
 
 
31-调整数组顺序使奇数位于偶数前面
 
class Solution {
    
    public int[] exchange(int[] nums) {
        for(int i = 0, j = 0; i < nums.length; i++) {
            if((nums[i] & 1) == 1) {
                int temp = nums[j];
                nums[j] = nums[i];
                nums[i] = temp;
                j++;
            }
        }
        return nums;
    }
}
 
 
32-和为s的两个数字
 
class Solution {
    
    public int[] twoSum(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while(left < right) {
            int sum = nums[left] + nums[right];
            if(sum == target) {
                return new int[]{nums[left], nums[right]};
            }
            if(sum < target) {
                left++;
            } else {
                right--;
            }
        }
        return new int[]{};
    }
}
 
 
33-翻转单词顺序
 
class Solution {
    
    public String reverseWords(String s) {
        StringBuilder sb = new StringBuilder();
        String[] strings = s.split(" ");
        
        for(int i = strings.length - 1; i >= 0; i--) {
            if("".equals(strings[i].trim())) {
                continue;
            }
            sb.append(strings[i].trim() + " ");
        }
        return sb.toString().trim();
    }
}
 
 
14.搜索与回溯算法(中等)
 
 
34-矩阵中的路径
 
class Solution {
    
    public boolean exist(char[][] board, String word) {
        int n = board.length, m = board[0].length;
        
        boolean[][] visited = new boolean[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(dfs(board, word, visited, i, j, 0)) {
                    return true;
                }
            }
        }
        return false;
    }
    public boolean dfs(char[][] board, String word, boolean[][] visited, int i, int j, int z) {
        int n = board.length, m = board[0].length;
        
        if(i < 0 || j < 0 || i >= n || j >= m || visited[i][j] || board[i][j] != word.charAt(z)) {
            return false;
        }
        
        if(word.length() - 1 == z) {
            return true;
        }
        int[][] moves = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
        
        visited[i][j] = true;
        
        for(int[] move : moves) {
            int k = i + move[0];
            int v = j + move[1];
            if(dfs(board, word, visited, k, v, z + 1)) {
                return true;
            }
        }
        
        visited[i][j] = false;
        return false;
    }
}
 
 
35-机器人的运动范围
 
class Solution {
    
    
    
    public int movingCount(int m, int n, int k) {
        boolean[][] visited = new boolean[m][n];
        return dfs(visited, k, 0, 0);
    }
    public int dfs(boolean[][] visited, int k, int i, int j) {
        int m = visited.length, n = visited[0].length;
        if(i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || (i%10 + i/10 + j%10 + j/10) > k) {
            return 0;
        }
        visited[i][j] = true;
        return dfs(visited, k, i + 1, j) + dfs(visited, k, i - 1, j) + 
                dfs(visited, k, i, j + 1) + dfs(visited, k, i, j - 1) + 1;
    }
}
 
 
15.搜索与回溯算法(中等)
 
 
36-二叉树中和为某一值的路径
 
class Solution {
    
    private List<List<Integer>> list = new LinkedList<>();
    
    private List<Integer> track = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        dfs(root, target, 0);
        return list;
    }
    public void dfs(TreeNode root, int target, int count) {
        if(root == null) {
            return;
        }
        
        count += root.val;
        track.add(root.val);
        
        if(count == target && root.left == null && root.right == null) {
            list.add(new LinkedList(track));
            track.remove(track.size() - 1);
            return;
        }
        dfs(root.left, target, count);
        dfs(root.right, target, count);
        
        track.remove(track.size() - 1);
    }
}
 
 
37-二叉搜索树与双向链表
 
class Solution {
    private Node head, prev;
    public Node treeToDoublyList(Node root) {
        if(root == null) return null;
        dfs(root);
        
        
        head.left = prev;
        prev.right = head;
        return head;
    }
    public void dfs(Node node) {
        if(node == null) {
            return;
        }
        
        dfs(node.left);
        
        
        if(prev == null) {
            head = node;
        } else {
            prev.right = node;
        }
        
        node.left = prev;
        prev = node;
        
        dfs(node.right);
    }
}
 
 
38-二叉搜索树的第k大节点
 
class Solution {
    
    private int n = 0, result = 0;
    public int kthLargest(TreeNode root, int k) {
        traverse(root, k);
        return result;
    }
    public void traverse(TreeNode root, int k) {
        if(root == null) {
            return;
        }
        traverse(root.right, k);
        if(k == ++n) {
            result = root.val;
            return;
        }
        traverse(root.left, k);
    }
}
 
 
16.排序(简单)
 
 
39-把数组排成最小的数
 
class Solution {
    
    
    
    
    
    public String minNumber(int[] nums) {
        List<String> list = new LinkedList<>();
        for(int num : nums) {
            list.add(String.valueOf(num));
        }
        list.sort((a, b) -> (a + b).compareTo(b + a));
        return String.join("", list);
    }
}
 
 
40-扑克牌中的顺子
 
class Solution {
    
    
    
    public boolean isStraight(int[] nums) {
        int zero = 0, diff = 0;
        Arrays.sort(nums);
        for(int i = 0; i < nums.length - 1; i++) {
            if(nums[i] == 0) {
                zero++;
                continue;
            } 
            if(nums[i + 1] == nums[i]) {
                return false;
            }
            if(nums[i + 1] - nums[i] > 1) {
                diff += nums[i + 1] - nums[i] - 1;
            }
        }
        return zero >= diff;
    }
}
 
 
17.排序(中等)
 
 
41-最小的k个数
 
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(arr.length == k) {
            return arr;
        }
        Arrays.sort(arr);
        int[] res = new int[k];
        for(int i = 0; i < k; i++) {
            res[i] = arr[i];
        }
        return res;
    }
}
 
 
42-数据流中的中位数
 
class MedianFinder {
    
    PriorityQueue<Integer> left;
    PriorityQueue<Integer> right;
    public MedianFinder() {
        left = new PriorityQueue<>((a, b) -> (a - b));
        right = new PriorityQueue<>((a, b) -> (b - a));
    }
    
    public void addNum(int num) {
        left.offer(num);
        right.offer(left.poll());
        if(left.size() + 1 < right.size()) {
            left.offer(right.poll());
        }
    }
    
    public double findMedian() {
        if(left.size() == right.size()) {
            return (double)(left.peek() + right.peek()) / 2;
        }
        return (double)right.peek();
    }
}
 
 
18.搜索与回溯算法(中等)
 
 
43-二叉树的深度
 
class Solution {
    
    public int maxDepth(TreeNode root) {
        return dfs(root, 0);
    }
    public int dfs(TreeNode root, int deep) {
        if(root == null) {
            return deep;
        }
        return Math.max(
            dfs(root.left, deep + 1),
            dfs(root.right, deep + 1)
        );
    }
}
 
 
44-平衡二叉树
 
class Solution {
    
    
    private boolean flag = true;
    public boolean isBalanced(TreeNode root) {
        dfs(root);
        return flag;
    }
    public int dfs(TreeNode node) {
        if(node == null || !flag) {
            return 0;
        }
        int left = dfs(node.left);
        int right = dfs(node.right);
        if(Math.abs(left - right) > 1) {
            flag = false;
            return 0;
        }
        return Math.max(left, right) + 1;
    }
}
 
 
19.搜索与回溯算法(中等)
 
 
45-求1+2+…+n
 
class Solution {
    public int sumNums(int n) {
        int sum = n;
        boolean flag = n > 0 && (sum += sumNums(n - 1)) > 0;
        return sum;
    }
}
 
 
46-二叉搜索树的最近公共祖先
 
class Solution {
    
    
    
    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        
        if(p.val < root.val && q.val < root.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        
        if(p.val > root.val && q.val > root.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        return root;
    }
}
 
 
47-二叉树的最近公共祖先
 
class Solution {
    
    
    
    
    
    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) {
            return null;
        }
        
        if(root == p || root == q) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        
        if(left != null && right != null) {
            return root;
        }
        
        if(left != null) return left;
        
        if(right != null) return right;
        return null;
    }
}
 
 
20.分治算法(中等)
 
 
48-重建二叉树
 
class Solution {
    
    private Map<Integer, Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for(int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        return createTree(preorder, 0, 0, inorder.length - 1);
    }
    public TreeNode createTree(int[] preorder, int preIndex, int left, int right) {
        if(left > right) return null;
        TreeNode root = new TreeNode(preorder[preIndex]);
        
        int inIndex = map.get(preorder[preIndex]);
        
        root.left = createTree(preorder, preIndex + 1, left, inIndex - 1);
        
        
        root.right = createTree(preorder, preIndex + inIndex - left + 1, inIndex + 1, right);
        return root;
    }
}
 
 
49-数值的整数次方
 
class Solution {
    
    public double myPow(double x, int n) {
        double result = 1;
        long v = n;
        if(v < 0) {
        	x = 1 / x;
        	v = -v;
        }
        while(v > 0) {
            if((v & 1) == 1) {
                result *= x;
            }
            v >>= 1;
            x *= x;
        }
        return result;
    }
}
 
 
50-二叉搜索树的后序遍历序列
 
class Solution {
    public boolean verifyPostorder(int[] postorder) {
        Deque<Integer> stack = new LinkedList<>();
        int preValue = Integer.MAX_VALUE;
        for(int i = postorder.length - 1; i >= 0; i--) {
            if(postorder[i] > preValue) {
                return false;
            }
            while(!stack.isEmpty() && postorder[i] < stack.peek()) {
                preValue = stack.pop();
            }
            stack.push(postorder[i]);
        }
        return true;
    }
}
 
 
21.位运算(简单)
 
 
51-二进制中1的个数
 
public class Solution {
    
    
    
    public int hammingWeight(int n) {
        int count = 0;
        while(n != 0) {
            count += n & 1; 
            n >>>= 1;       
        }
        return count;
    }
}
 
 
52-不用加减乘除做加法
 
class Solution {
    
    
    public int add(int a, int b) {
        if(a == 0) return b;
        return add((a & b) << 1, a ^ b);
    }
}
 
 
22.位运算(中等)
 
 
53-数组中数字出现的次数
 
class Solution {
    public int[] singleNumbers(int[] nums) {、
        
        
        
        int sum = 0;
        for(int num : nums) {
            sum ^= num;
        }
        
        int flag = sum & (-sum), res = 0;
        for(int num : nums) {
            
            if((flag & num) != 0) {
                res ^= num;
            }
        }
        
        return new int[]{res, sum ^ res};
    }
}
 
 
54-数组中数字出现的次数 II
 
class Solution {
    
    
    public int singleNumber(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if(entry.getValue() == 1) {
                return entry.getKey();
            }
        }
        return -1;
    }
}
 
 
23.数学(简单)
 
 
55-数组中出现次数超过一半的数字
 
class Solution {
    
    
    
    public int majorityElement(int[] nums) {
        int result = 0, count = 0;
        for(int i = 0; i < nums.length; i++) {
            if(count == 0) {
                result = nums[i];
                count++;
            } else {
                if(result == nums[i]) {
                    count++;
                } else {
                    count--;
                }
            }
        }
        return result;
    }
}
 
 
56-构建乘积数组
 
class Solution {
    
    
    
    
    public int[] constructArr(int[] a) {
        int n = a.length;
        int[] b = new int[n];
        
        for(int i = 0, pre = 1; i < n; pre *= a[i], i++) {
            b[i] = pre;
        }
        
        for(int i = n - 1, pre = 1; i >= 0; pre *= a[i], i--) {
            b[i] *= pre;
        }
        return b;
    }
}
 
 
24.数学(中等)
 
 
57-剪绳子
 
class Solution {
    
    
    
    public int cuttingRope(int n) { 
        if(n <= 3) {
            return n - 1;
        }
        int m = 1;
        while(n > 4) {
            n -= 3;
            m *= 3;
        }
        
        
        return n * m;
    }
}
 
 
58-和为s的连续正数序列
 
class Solution {
    
    public int[][] findContinuousSequence(int target) {
        List<int[]> list = new LinkedList<>();
        for(int left = 1, right = 1, sum = 0; right < target; right++) {
            sum += right;
            
            while(sum > target) {
                sum -= left++;
            }
            
            if(sum == target) {
                int[] nums = new int[right - left + 1];
                for(int i = 0; i < nums.length; i++) {
                    nums[i] = left + i;
                }
                list.add(nums);
            }
        }
        int[][] result = new int[list.size()][];
        for(int i = 0; i < list.size(); i++) {
            result[i] = list.get(i);
        }
        return result;
    }
}
 
59-圆圈中最后剩下的数字
 
class Solution {
    
    
    
    public int lastRemaining(int n, int m) {
        int res = 0;
        for (int i = 2; i <= n; i++) {
            res = (res + m) % i;
        }
        return res;
    }
}
 
 
25.模拟(中等)
 
 
60-顺时针打印矩阵
 
class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0) {
            return new int[]{};
        }
        int n = matrix.length, m = matrix[0].length;
        
        boolean[][] visited = new boolean[n + 2][m + 2];
        List<Integer> list = new LinkedList<>();
        int i = 1, j = 1, flag = 0, mul = n * m;
        
        for(int k = 0; k < n + 2; k++) {
            for(int v = 0; v < m + 2; v++) {
                if(k == 0 || v == 0 || k == n + 1 || v == m + 1) {
                    visited[k][v] = true;
                }
            }
        }
        while(list.size() < mul) {
            
            if(visited[i][j + 1] && flag == 0 || visited[i + 1][j] && flag == 1
                    || visited[i][j - 1] && flag == 2 || visited[i - 1][j] && flag == 3) {
                flag = flag == 3 ? 0 : flag + 1;
            }
            list.add(matrix[i - 1][j - 1]);
            visited[i][j] = true;
            if(flag == 0) j++;
            if(flag == 1) i++;
            if(flag == 2) j--;
            if(flag == 3) i--;
        }
        int[] result = new int[list.size()];
        for(int v = 0; v < list.size(); v++) {
            result[v] = list.get(v);
        }
        return result;
    }
}
 
 
61-栈的压入、弹出序列
 
class Solution {
    
    
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        Deque<Integer> stack = new LinkedList<>();
        int n = pushed.length;
        for(int i = 0, j = 0; i < n; i++) {
            stack.push(pushed[i]);
            while(j < n && !stack.isEmpty() && stack.peek() == popped[j]) {
                stack.pop();
                j++;
            }
        }
        return stack.isEmpty();
    }
}
 
 
26.字符串(中等)
 
 
62-表示数值的字符串
 
class Solution {
    
    public boolean isNumber(String s) {
        if(s.contains("F") || s.contains("f")
            || s.contains("D") || s.contains("d")) {
                return false;
        }
        try {
            Double.valueOf(s);
        } catch(Exception e) {
            return false;
        }
        return true;
    }
}
 
 
63-把字符串转换成整数
 
class Solution {
    
    
    
    public int strToInt(String str) {
        
        str = str.trim();
        
        long result = 0;
        
        int flag = 0;
        for(int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(flag == 0) {
                
                if(c == '+' || c == '-' || c >= '0' && c <= '9') {
                    flag = c == '-' ? -1 : 1;
                    if(!(c == '+' || c == '-')) {
                        result = c - '0';
                    }
                } else {
                    
                    return 0;
                }
            } else {
                if(c >= '0' && c <= '9') {
                    result = result * 10 + (c - '0');
                    
                    if(flag == 1 && result >= Integer.MAX_VALUE)
                        return Integer.MAX_VALUE;
                    if(flag == -1 && result - 1 >= Integer.MAX_VALUE)
                        return Integer.MIN_VALUE;
                } else {
                    
                    break;
                }
            }
        }
        return flag == -1 ? (int)-result : (int)result;
    }
}
 
 
27.栈与队列(困难)
 
 
64-滑动窗口的最大值
 
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        
        
        if(nums.length == 0) return new int[]{}; 
        
        int[] res = new int[nums.length - k + 1];
        
        LinkedList<Integer> queue = new LinkedList<>();
        for(int i = 0; i < nums.length; i++) {
            
            if(!queue.isEmpty() && i - queue.peekFirst() >= k) {
                queue.pollFirst();
            } 
            
            
            while(!queue.isEmpty() && nums[i] > nums[queue.peekLast()]) {
                queue.pollLast();
            }
            
            queue.offerLast(i);
            if(i >= k - 1) {
                
                res[i - k + 1] = nums[queue.peekFirst()];
            }
        }
        return res;
    }
}
 
 
65-队列的最大值
 
class MaxQueue {
    Deque<Integer> queue;
    Deque<Integer> stack;
    public MaxQueue() {
        queue = new LinkedList<>();
        stack = new LinkedList<>();
    }
    
    public int max_value() {
        if(stack.isEmpty()) {
            return -1;
        }
        return stack.peek();
    }
    
    public void push_back(int value) {
        queue.offer(value);
        while(!stack.isEmpty() && value > stack.peekLast()) {
            stack.pollLast();
        }
        stack.offer(value);
    }
    
    public int pop_front() {
        if(queue.isEmpty()) {
            return -1;
        }
        int value = queue.pop();
        if(value == stack.peek()) {
            stack.pop();
        }
        return value;
    }
}
 
 
28.搜索与回溯算法(困难)
 
 
66-序列化二叉树
 
public class Codec {
    private String[] values;
    private int i;
    public String serialize(TreeNode root) {
        if(root == null) {
            return "#,";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(root.val + ",");
        sb.append(serialize(root.left));
        sb.append(serialize(root.right));
        return sb.toString();
    }   
    public TreeNode deserialize(String data) {
        values = data.split(",");
        return helper();
    }
    public TreeNode helper() {
        String value = values[i++];
        if("#".equals(value)) {
            return null;
        }
        TreeNode root = new TreeNode(Integer.valueOf(value));
        root.left = helper();
        root.right = helper();
        return root;
    }
}
 
 
67-字符串的排列
 
class Solution {
    
    private Set<String> set = new HashSet<>();
    private char[] cs;
    public String[] permutation(String s) {
        cs = s.toCharArray();
        dfs(0);
        return set.toArray(new String[]{});
    }
    public void dfs(int i) {
        if(i == cs.length) {
            set.add(new String(cs));
            return;
        }
        for(int j = i; j < cs.length; j++) {
            swap(i, j);
            dfs(i + 1);
            swap(i, j);
        }
    }
    public void swap(int i, int j) {
        char c = cs[i];
        cs[i] = cs[j];
        cs[j] = c;
    }
}
 
 
29.动态规划(困难)
 
 
68-正则表达式匹配
 
class Solution {
    
    public boolean isMatch(String s, String p) {
        return s.matches(p);
    }
}
 
 
69-丑数
 
class Solution {
    
    
    
    
    
    
    public int nthUglyNumber(int n) {
        int[] dp = new int[n + 1];
        int i = 1, j = 1, k = 1;
        dp[1] = 1;
        
        for(int v = 2; v <= n; v++) {
            int min = Math.min(dp[i] * 2, Math.min(dp[j] * 3, dp[k] * 5));
            if(min == dp[i] * 2) i++;
            if(min == dp[j] * 3) j++;
            if(min == dp[k] * 5) k++;
            dp[v] = min;
        }
        return dp[n];
    }
}
 
 
70-n个骰子的点数
 
class Solution {
	
	
    public double[] dicesProbability(int n) {
        double[] res = new double[6];
        Arrays.fill(res, 1.0 / 6.0);
        for(int i = 2; i <= n; i++) {
            double[] tmp = new double[i * 6 - (i - 1)];
            for(int j = 0; j < res.length; j++) {
                for(int k = 0; k < 6; k++) {
                    tmp[k + j] += res[j] * 1.0 / 6.0;
                }
            }
            res = tmp;
        }
        return res;
    }
}
 
 
30.分治算法(困难)
 
 
71-打印从1到最大的n位数
 
class Solution {
    public int[] printNumbers(int n) {
        int m = (int) Math.pow(10, n);
        int[] a = new int[m - 1];
        for(int i = 0;i < m - 1; i++){
            a[i] = i + 1;
        }
        return a;
    }
}
 
 
72-数组中的逆序对
 
class Solution {
    
    
    private int count = 0;
    public int reversePairs(int[] nums) {
        sort(nums, 0, nums.length - 1);
        return count;
    }
    public int[] sort(int[] nums, int left, int right) {
        if(left < right) {
            int mid = left + (right - left) / 2;
            sort(nums, left, mid);
            sort(nums, mid + 1, right);
            merge(nums, left, mid, right);
        }
        return nums;
    }
    public void merge(int[] nums, int left, int mid, int right) {
        int[] memo = new int[right - left + 1];
        int i = left, j = mid + 1, k = 0;
        while(i <= mid && j <= right) {
            if(nums[i] <= nums[j]) {
                memo[k++] = nums[i++];
            } else {
                count += mid - i + 1;
                memo[k++] = nums[j++];
            }
        }
        while(i <= mid) {
            memo[k++] = nums[i++];
        }
        while(j <= right) {
            memo[k++] = nums[j++];
        }
        for(int v = 0; v < memo.length; v++) {
            nums[left + v] = memo[v];
        }
    }
}
 
 
31.数学(困难)
 
 
73-剪绳子 II
 
class Solution {
    
    
    public int cuttingRope(int n) {
        if(n <= 3) {
            return n - 1;
        }
        long m = 1;
        while(n > 4) {
            n -= 3;
            m *= 3;
            m = m > 1000000007 ? m % 1000000007 : m;
        }
        return (int) (m * n % 1000000007);
    }
}
 
 
74-1~n 整数中 1 出现的次数
 
 
 
75-数字序列中某一位的数字
 
class Solution {
    
    
    public int findNthDigit(int n) {
        long start = 1, count = 9;
        int digit = 1;
        while(n > count) {
            start *= 10;
            digit += 1;
            n -= count;
            count = start * digit * 9;
        }
        long num = start + (n - 1) / digit;
        return Long.toString(num).charAt((n - 1) % digit) - '0';
    }
}