剑指 Offer(第 2 版)所有题目答案 突击面试 Java(建议收藏!)

剑指 Offer(第 2 版)所有题目答案 突击面试

剑指Offer第二版所有题目,自己编写整理笔记,保证能够运行!

题库链接

https://leetcode.cn/problem-list/xb9nqhhg/

数组中重复的数字

class Solution {
    public int findRepeatNumber(int[] nums) {
        Set<Integer> dic = new HashSet<>();
        for (int num : nums) {
            if (dic.contains(num)) return num;
            dic.add(num);
        }
        return -1;
    }
}

二维数组中的查找

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        int  i = matrix.length-1;
        int j = 0;
        while (i >= 0 && j < matrix[0].length) {
            if (matrix[i][j] > target) i--;
            else if (matrix[i][j] <target) j++;
            else return true;
        }
        return false;
    }
}

替换空格

class Solution {
    public String replaceSpace(String s) {
        StringBuilder res = new StringBuilder();
        for (Character c : s.toCharArray()) {
            if (c == ' ') {
                res.append("%20");
            } else {
                res.append(c);
            }
        }
        return res.toString();
    }
}

从尾到头打印链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] reversePrint(ListNode head) {
        LinkedList<Integer> stack = new LinkedList<Integer>();
        while (head != null) {
            stack.addLast(head.val);
            head = head.next;
        }
        int[] res = new int[stack.size()];
        for (int i = 0; i < res.length; i++) {
            res[i] = stack.removeLast();
        }
        return res;
    }
}

不使用栈

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] reversePrint(ListNode head) {
        ListNode node = head;
        int count = 0;
        while (node != null) {
            ++count;
            node = node.next;
        }
        int[] nums = new int[count];
        node = head;
        for (int i = count - 1; i >= 0; i--) {
            nums[i] = node.val;
            node = node.next;
        }
        return nums;
    }
}

重建二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    Map<Integer, Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length <= 0) return null;
        for (int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        TreeNode root = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
        return root;
    }

    TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2) {
        if (l1 > r1 && l2 > r2) return null;
        TreeNode root = new TreeNode(preorder[l1]);
        int i = map.get(preorder[l1]);
        root.left = f(preorder, l1 + 1, l1 + (i - l2), inorder, l2, i - 1);
        root.right = f(preorder, l1 + (i - l2) + 1, r1, inorder, i + 1, r2);
        return root;
    }
}

用两个栈实现队列

class CQueue {
    Stack<Integer> st1;
    Stack<Integer> st2;
    public CQueue() {
        st1 = new Stack<>();
        st2 = new Stack<>();
    }
    
    public void appendTail(int value) {
        st1.push(value);
    }
    
    public int deleteHead() {
        if (!st2.isEmpty()) {
            return st2.pop();
        }
        if (!st1.isEmpty()) {
            while (!st1.isEmpty()) {
                st2.push(st1.pop());
            }
            return st2.pop();
        }
        return -1;
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

斐波那契数列

class Solution {
    public int fib(int n) {
        int a = 0, b = 1, sum;
        for (int i = 1; i <= n; i++) {
            sum = (a + b) % 1000000007;
            a =b;
            b = sum;
        }
        return a;
    }
}

青蛙跳台阶问题

class Solution {
    public int numWays(int n) {
        int[] dp = new int[n + 2];
        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];
    }
}

旋转数组的最小数字

class Solution {
    public int minArray(int[] numbers) {
        int l = 0, r = numbers.length - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (numbers[mid] < numbers[r]) r = mid;
            else if (numbers[mid] > numbers[r]) l = mid + 1;
            else r -= 1;
        }
        return numbers[l];
    }
}

矩阵中的路径

class Solution {
    public boolean exist(char[][] board, String word) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (dfs(board, word, 0, i, j)) return true;
            }
        }
        return false;
    }

    int[] dx = new int[]{1,0,0,-1};
    int[] dy = new int[]{0,1,-1,0};

    boolean dfs(char[][] board, String word, int u, int x, int y) {
        if (board[x][y] != word.charAt(u)) return false;
        if (u == word.length() - 1) return true;
        char t = board[x][y];
        board[x][y] = '.';
        for (int i = 0; i < 4; i++) {
            int xx = x + dx[i], yy = y + dy[i];
            if (xx < 0 || xx > board.length - 1 || yy < 0 || yy > board[0].length - 1 || board[xx][yy] == '.') continue;
            if (dfs(board, word, u + 1, xx, yy)) return true;
        }
        board[x][y] = t;
        return false;
    }
}

剪绳子

dp

class Solution {
    public int cuttingRope(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            for (int j = 2; j < i; j ++) {
                dp[i] = Math.max(dp[i], Math.max(j * dp[i - j], j * (i - j)));
            }
        }
        return dp[n];
    }
}
class Solution {
    public int cuttingRope(int n) {
        if (n < 4) return n - 1;
        int res = 1;
        while ( n > 4) {
            res  =  res * 3;
            n -= 3;
        }
        return res * n;
    }
}

剪绳子 II

dp

import java.math.BigInteger;
class Solution {
    public int cuttingRope(int n) {
        //大数
        BigInteger[] dp = new BigInteger[n + 1];
        Arrays.fill(dp, BigInteger.valueOf(1));
        for (int i = 3; i <= n; i++) {
            for (int j = 1; j < i; j++){
                dp[i] = dp[i].max(BigInteger.valueOf(j * ((i - j))).max(dp[i - j].multiply(BigInteger.valueOf(j))));
            }
        }
        return dp[n].mod(BigInteger.valueOf(1000000007)).intValue();
    }
}

贪心

import java.math.BigInteger;
class Solution {
    public int cuttingRope(int n) {
        if (n <= 3) return n- 1;
        long res = 1L;
        long mod =1000000007;
        while (n > 4) {
            res=res*3%mod;
            n-=3;
        } 
        return (int)( res * n % mod);
    }
}

二进制中1的个数

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int res = 0;
        for (int  i = 0; i < 32; i++) {
            if((n & (1 << i)) != 0) {
                res ++;
            }
        }
        return res;
    }
}
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int sum = 0;
        while (n != 0) {
            n = n & (n - 1);
            sum++;
        }
        return sum;
    }
}

数值的整数次方

class Solution {
    public double myPow(double x, int n) {
        double res = 1;
        long y = n;
        if (y < 0) {
            y = -y;
            x = 1/ x;
        }
        while (y > 0) {
            if (y % 2 == 1) {
                res = res * x;
            }
            x = x * x;
            y = y / 2;
        }
        return res ;
    }
}

打印从1到最大的n位数

class Solution {
    public int[] printNumbers(int n) {
        int m = (int)Math.pow(10, n) - 1;
        int[] res = new int[m];
        for (int i = 0; i < m; i++){
            res[i] = i + 1;
        }
        return res;
    }
}

格雷编码

class Solution {
    public List<Integer> grayCode(int n) {
        /*
    N = 3;
    000  0
    001  1
    011  3
    010  2

    110  6
    111  7
    101  5
    100  4 
    */
        List<Integer> res = new ArrayList<>();
        res.add(0);
        if (n == 0) return res;
        int c =  1;
        while (c <= n) {
            int index = res.size() - 1;
            while (index >= 0) {
                res.add(res.get(index--) + (int)Math.pow(2, c - 1));
            }
            c++;
        }
        return res;
    }
}

删除链表的节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        if (head.val == val) return head.next;
        ListNode pre = head, cur = head.next;
        while (cur != null && cur.val != val) {
            pre = cur;
            cur = cur.next;
        }
        if (cur != null) pre.next = cur.next;
        return head;
    }
}

正则表达式匹配

class Solution {
    public boolean isMatch(String s, String p) {
        int n = s.length();
        int m = p.length();
        boolean[][] dp = new boolean[n + 1][m + 1];
        dp[0][0] = true;
        for (int i = 0; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (p.charAt(j - 1) == '*') {
                     dp[i][j] = dp[i][j- 2];
                    if (matches(s, p, i, j - 1)) {
                        dp[i][j] = dp[i][j] || dp[i - 1][j];
                    }
                } else {
                    if (matches(s, p, i, j)) {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                }
            }
        }
        return dp[n][m];
    }
    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) return false;
        if (p.charAt(j - 1)=='.') return true;
        return s.charAt(i - 1) == p.charAt(j - 1);
    }
}

表示数值的字符串

class Solution {
    public boolean isNumber(String s) {
        if (s == null || s.length() == 0) return false;
        s = s.trim(); //去掉首位的空格
        boolean numFlag = false; //是否出现数字
        boolean dotFlag = false;//是否出现小数点
        boolean eFlag = false;//是否出现e
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) >= '0' && s.charAt(i) <='9') { //判断为出现数字
                numFlag = true;
            } 
            else if (s.charAt(i) == '.' && dotFlag == false && !eFlag) { //出现为小数点,且只能出现一次
                dotFlag = true;
            }
            else if ((s.charAt(i) == 'e' || s.charAt(i) == 'E') && eFlag == false && numFlag == true) {
                eFlag = true;
                numFlag = false;
            }
            else if ((s.charAt(i) == '+' || s.charAt(i) == '-') && (i == 0 ||s.charAt(i - 1) == 'e' || s.charAt(i - 1) == 'E')){ //如果是+-号
                continue;
            } else {
                return false;
            }
        }
        return numFlag;
    }
}

调整数组顺序使奇数位于偶数前面

class Solution {
    public int[] exchange(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        int l = 0, r = nums.length - 1;
        while (l < r) {
            while (l < r && nums[l] % 2 == 1) l++;
            while (l < r && nums[r] % 2 == 0) r--;
            int temp = nums[l];
            nums[l] =nums[r];
            nums[r] = temp; 
        }
        return nums;
    }
}

链表中倒数第k个节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        if (head == null) return null;
        ListNode fast = head;
        ListNode slow = head;
        for (int i = 0; i < k; i++) {
            if (fast == null) return null;
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

反转链表

递归

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode temp = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return temp;
    }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode cur = head, pre = null;
        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

合并两个排序的链表

迭代法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode merge = new ListNode(0);
        ListNode temp = merge;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                temp.next = l1;
                l1 = l1.next;
            } else {
                temp.next = l2;
                l2 = l2.next;
            }
            temp = temp.next;
        }
        temp.next = l1 == null ? l2 : l1;
        return merge.next;
    }
}

递归法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        else if (l2 == null) return l1;
        else if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1; 
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

树的子结构

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A == null || B == null) return false;
        if (isTree(A, B)) return true;
        else if (isSubStructure(A.left, B) || isSubStructure(A.right, B)) return true;
        return false;
    }
    boolean isTree(TreeNode TA, TreeNode TB) {
        if (TB == null) return true;
        if (TA == null) return false;
        if (TA.val != TB.val) return false;
        return isTree(TA.left, TB.left) && isTree(TA.right, TB.right);
    }
}

二叉树的镜像

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if (root == null) return root;
        TreeNode left = null;
        TreeNode right = null;
        if (root.left != null) left = mirrorTree(root.left);
        if (root.right != null) right =mirrorTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }
}

对称的二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null || (root.left == null && root.right == null)) return true;
        return f(root.left, root.right);
    }
    boolean f(TreeNode left , TreeNode right) {
        if (left == null && right == null) return true;
        if (left == null || right == null) return false;
        if (left.val != right.val) return false;
        return f(left.left, right.right) && f(left.right, right.left);
    }
}

顺时针打印矩阵

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if (matrix.length == 0) return new int[0];
        int l = 0, r = matrix[0].length - 1, t  = 0, b = matrix.length - 1;
        int[] res =  new int[(r +1) * (b + 1)];
        int k = 0;
        while (true) {
            //从左向右
            for (int i = l; i <= r; i++) {
                res[k++] = matrix[t][i];
            }
            if (++t > b) break; 
            //从上往下
            for (int i = t; i <= b; i++) {
                res[k++] = matrix[i][r];
            }
            if (l > --r) break;
            //从右往左
            for (int i = r; i >= l; i--) {
                res[k++] = matrix[b][i];
            }
            if (t > --b) break;
            //从下往上
            for (int i = b; i >= t; i--) {
                res[k++] = matrix[i][l];
            }
            if (++l > r) break;
        }
        return res;
    }
}

包含min函数的栈

class MinStack {
    Stack<Integer> stack1;
    Stack<Integer> stack2;
    /** initialize your data structure here. */
    public MinStack() {
        this.stack1 = new Stack();
        this.stack2 = new Stack();
    }
    
    public void push(int x) {
        stack1.push(x);
        if (stack2.isEmpty() || stack2.peek().intValue() >= x) {
            stack2.push(x);
        }
    }
    
    public void pop() {
        if (!stack1.isEmpty()) {
            if (stack1.peek().intValue() == stack2.peek().intValue()) {
                stack2.pop();
            }
            stack1.pop();
        }
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        return stack2.peek();
    }
}

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

栈的压入、弹出序列

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        if (pushed.length == 0 || pushed == null) return true;
        Stack<Integer> stack = new Stack<>();
        int k = 0;
        for (int i = 0; i < pushed.length; i++) {
            stack.push(pushed[i]);
            while (!stack.isEmpty() && stack.peek() == popped[k]) {
                k++;
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

从上到下打印二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] levelOrder(TreeNode root) {
        if (root == null) {
            return new int[0];
        }
        Queue<TreeNode> queue = new LinkedList<>();
        List<Integer> res = new ArrayList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            res.add(node.val);
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }
        int[] arr = new int[res.size()];
        for (int i = 0; i < res.size(); i++) {
            arr[i] = res.get(i);
        }
        return arr;
    }
}

从上到下打印二叉树 II

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        while (!q.isEmpty()) {
            int k = q.size();
            List<Integer> arr = new ArrayList<>();
            while (k-- >0) {
                TreeNode node = q.peek();
                if (node.left != null) q.add(node.left);
                if (node.right != null) q.add(node.right);
                TreeNode kk = q.poll();
                arr.add(kk.val);
            }
            res.add(arr);
        }
        return res;
    }
}

从上到下打印二叉树 III

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) return new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int num = 1;//判断奇数偶数 奇数就从左往右;
        while (!q.isEmpty()) {
            int k = q.size();
            LinkedList<Integer> cnt = new LinkedList<>();
            while (k-- >0) {
                TreeNode node = q.poll();
                if (num % 2 == 1) {
                    cnt.add(node.val);
                    if (node.left != null) q.add(node.left);
                    if (node.right != null) q.add(node.right);
                } else {
                    cnt.addFirst(node.val);
                    if (node.left != null) q.add(node.left);
                    if (node.right != null) q.add(node.right);
                }
            }
            res.add(cnt);
            num ++ ;
        }
        return res;
    }
}

二叉搜索树的后序遍历序列

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return f(postorder, 0, postorder.length - 1);
    }
    boolean f(int[] postorder, int l, int r) {
        if (l >= r) return true;
        int p = l;
        while (postorder[p] < postorder[r]) p++;
        int m = p;
        //左子树为l m - 1, m r - 1;
        while (postorder[p] > postorder[r]) p++;
        return p==r && f(postorder, l, m - 1) && f(postorder, m, r - 1);
    }
}

使用栈

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        Stack<Integer>  stack = new Stack<>();
        int root =  Integer.MAX_VALUE;
        for (int i = postorder.length - 1; i >= 0; i--) {
            int cur = postorder[i];
            while (!stack.isEmpty() && cur < stack.peek()) {
                root = stack.pop();
            }
            if (cur > root) return false;
            stack.add(cur);
        }
        return true;
    }
}

二叉树中和为某一值的路径

/**
 * 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 {
    List<List<Integer>> res = new LinkedList<>();
    Deque<Integer> path = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        dfs(root, target);
        return res;
    }
    void dfs(TreeNode root, int target) {
        if (root == null) return ;
        path.offerLast(root.val);
        target -= root.val;
        if (target == 0 && root.left == null && root.right == null) {
            res.add(new LinkedList<Integer>(path));
        }
        dfs(root.left, target);
        dfs(root.right, target);
        target += root.val;
        path.pollLast();
    }
}

复杂链表的复制

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/
class Solution {
    public Node copyRandomList(Node head) {
        if (head == null) return null;
        //复制节点
        Node cur = head;
        while (cur != null) {
            Node next = cur.next;
            cur.next = new Node(cur.val);
            cur.next.next = next;
            cur = next;
        }
        //复制random节点
        cur = head;
        while (cur != null) {
            Node curNew = cur.next;
            curNew.random = cur.random == null ? null : cur.random.next;
            cur = cur.next.next;
        }
        //拆分
        Node newHead = head.next;
        cur = head;
        Node curNew = head.next;
        while (cur != null) {
            cur.next = cur.next.next;
            cur = cur.next;
            curNew.next = cur == null ? null : cur.next;
            curNew = curNew.next;
        }
        return newHead;
    }
}

二叉搜索树与双向链表

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
    public Node treeToDoublyList(Node root) {
        if (root == null) return null;
        Queue<Node> q = new LinkedList<>();
        inordered(q, root);
        Node head = q.poll();
        Node pre = head;
        while (!q.isEmpty()) {
            Node cur = q.poll();
            pre.right = cur;
            cur.left = pre;
            pre = cur;
        }
        pre.right = head;
        head.left = pre;
        return head;
    }
    public void inordered(Queue q, Node root) {
        if (root == null) return ;
        inordered(q, root.left);
        q.add(root);
        inordered(q, root.right);
    }
}

序列化二叉树

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

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if (root == null) return "[]";
        StringBuilder res = new StringBuilder("[");
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            if (node!=null) {
                res.append(node.val + ",");
                q.add(node.left);
                q.add(node.right);
            }
            else res.append("null,");
        }
        res.deleteCharAt(res.length() - 1);
        res.append("]");
        return res.toString();
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data.equals("[]")) {
            return null;
        }
        String[] vals = data.substring(1, data.length() - 1).split(",");
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int i = 1;
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            if (!vals[i].equals("null")) {
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                q.add(node.left);
            }
            i++;
            if (!vals[i].equals("null")) {
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                q.add(node.right);
            }
            i++;
        }
        return root;
    }



}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

数组中出现次数超过一半的数字

class Solution {
    public int majorityElement(int[] nums) {
        int x= 0, votes = 0, count = 0;
        for (int num : nums) {
            if (votes == 0) x = num;
            votes += num == x ? 1 : -1;
        }
        for (int num : nums) {
            if (num == x) count ++;
        }
        return count > nums.length / 2 ? x : 0;
    }
}

最小的k个数

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        quickSort(arr, 0, arr.length - 1);
        return Arrays.copyOf(arr, k);
    }
    private void quickSort(int[] arr, int l, int r) {
        if (l >= r) return ;
        int i = l , j = r;
        while (i < j) {
            while (i < j && arr[j] >= arr[l]) j--;
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, l);
        quickSort(arr, l, i - 1);
        quickSort(arr, i + 1, r);
    }
    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if (k >= arr.length) return arr;
        return quickSort(arr, k, 0, arr.length - 1);
    }
    private int[] quickSort(int[] arr, int k, int l, int r) {
        int i = l, j = r;
        while (i < j) {
            while (i < j && arr[j] >= arr[l]) j--;
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, l);
        if (i > k) return quickSort(arr, k, l, i - 1);
        if (i < k) return quickSort(arr, k, i + 1, r);
        return Arrays.copyOf(arr, k);
    }
    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

数据流中的中位数

采用大根堆和小根堆

class MedianFinder {
    Queue<Integer> min, max;
    /** initialize your data structure here. */
    public MedianFinder() {
        min = new PriorityQueue<>(); //小根堆
        max = new PriorityQueue<>((x, y) -> (y - x)); //大根堆
    }
    
    public void addNum(int num) {
        if (min.size() == max.size()) {
            min.add(num);
            max.add(min.poll());
        } else {
            max.add(num);
            min.add(max.poll());
        }
    }
    
    public double findMedian() {
        //如果是偶数
        if(min.size() == max.size()) {
            return (min.peek() + max.peek()) / 2.0;
        } else {
            return max.peek() * 1.0;
        }
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

1~n 整数中 1 出现的次数

class Solution {
    public int countDigitOne(int n) {
        long bit = 1;
        long sum = 0;
        while (bit <= n) {
            long cur = n / bit % 10;
            long low = n % bit;
            long high = n /bit / 10;
            if (cur > 1) {
                sum += (high + 1) * bit;
            } else if (cur == 1) {
                sum += (high * bit) + (1 + low);
            } else if (cur == 0){
                sum += high * bit;
            }
            bit *= 10;
        }
        return (int)sum;
    }
}

数字序列中某一位的数字

class Solution {
    public int findNthDigit(int n) {
        if (n == 0) return 0;
        long bit = 1;
        int i = 1;
        long count = 9;
        while (count < n) {
            n = (int)(n - count) ;
            bit *= 10;
            i++;
            count = bit *i * 9;
        }
        //确定是在这个区间的哪个数
        long num = bit + (n - 1)/i;
        //确定在Num的那个字符上
        int index = (n - 1) % i + 1;
        int res =(int) (num / Math.pow(10, i - index)) % 10;
        return res;
    }
}

把数字翻译成字符串

class Solution {
    public int translateNum(int num) {
        String s = String.valueOf(num);
        int a = 1, b = 1;
        for (int i = 2; i <= s.length(); i++) {
            String tmp = s.substring(i - 2, i);
            int c = tmp.compareTo("10") >= 0 && tmp.compareTo("25") <=0 ? a+ b:a;
            b = a;
            a = c;
        }
        return a;
    }
}

礼物的最大价值

class Solution {
    public int maxValue(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (i > 0 && j > 0) {
                    grid[i][j] = Math.max(grid[i][j-1],  grid[i - 1][j]) + grid[i][j];
                } else if (i > 0) {
                    grid[i][j] = grid[i - 1][j] + grid[i][j];
                } else if (j > 0) {
                    grid[i][j] =  grid[i][j - 1] + grid[i][j];
                }
            }
        }
        return grid[n - 1][m - 1];
    }
}

最长不含重复字符的子字符串

哈希表

使用双指针的方法 不断更新左指针

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> dic = new HashMap<>();
        int i = -1, res = 0;
        for (int j = 0; j < s.length(); j++) {
            if (dic.containsKey(s.charAt(j))) {
                i = Math.max(i, dic.get(s.charAt(j)));
            }
            dic.put(s.charAt(j), j);//更新hash记录
            res = Math.max(res, j - i);
        }
        return res;
    }
}

丑数

class Solution {
    public int nthUglyNumber(int n) {
        int[] factors = {2, 3, 5};
        Set<Long> seen = new HashSet<>();
        PriorityQueue<Long> heap = new PriorityQueue<>();
        seen.add(1L);
        heap.offer(1L);
        int ugly = 0;
        for (int i = 0; i < n; i++) {
            long curr = heap.poll();
            ugly = (int) curr;
            for (int factor : factors) {
                Long next = factor * curr;
                if (seen.add(next)) {
                    heap.offer(next);
                }
            }
        }
        return ugly;
    }
}

动态规划

巧妙

class Solution {
    public int nthUglyNumber(int n) {
        int[] dp = new int[n + 1];
        dp[1] = 1;
        int p2 = 1, p3 = 1, p5 = 1;//丑数一定是前面的丑数程2 3 5得来的,所以从第一个数开始
        for (int i  = 2; i <= n; i++) {
            int num2 = dp[p2] * 2, num3 = dp[p3] * 3, num5 = dp[p5] * 5;
            dp[i] = Math.min(num2, Math.min(num3, num5));
            if (num2 == dp[i]) p2++;
            if (num3 == dp[i]) p3++;
            if (num5 == dp[i]) p5++;
        }
        return dp[n];
        
    }
}

第一个只出现一次的字符

class Solution {
    public char firstUniqChar(String s) {
        Map<Character, Integer> frequency = new HashMap<>();
        for (int i = 0 ; i < s.length(); i++) {
            char ch = s.charAt(i);
            frequency.put(ch, frequency.getOrDefault(ch, 0) + 1);
        }
        for (int i = 0 ; i < s.length(); i++) {
            if (frequency.get(s.charAt(i)) == 1) return s.charAt(i);
        }
        return ' ';
    }
}

数组中的逆序对

class Solution {
    int res;
    public int reversePairs(int[] nums) {
        res = 0;
        mergeSort(nums, 0, nums.length - 1);
        return res;
    }
    public void mergeSort(int[] nums, int l, int r) {
        if (l >= r) return ;
        int mid = l + r >>1;
        mergeSort(nums, l, mid);
        mergeSort(nums, mid + 1, r);
        int[] tmp = new int[r - l + 1];
        int i = l , j = mid +1;
        int t = 0;
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                tmp[t++] = nums[i++];
            } else {
                res += mid - i + 1;
                tmp[t++] = nums[j++];
            }
        }
        while (i <= mid) {
            tmp[t++] = nums[i++];
        }
        while (j <= r) {
            tmp[t++] = nums[j++];
        }
        for (int k = 0; k < tmp.length; k++) {
            nums[l + k] = tmp[k];
        }
    }
}

两个链表的第一个公共节点

哈希表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        
        Set<ListNode> vis = new HashSet<>();
        ListNode tmp = headA;
        while (tmp != null) {
            vis.add(tmp);
            tmp = tmp.next;
        }
        tmp = headB;
        while (tmp!=null) {
            if (vis.contains(tmp)) return tmp;
            tmp = tmp.next;
        }
        return null;
    }
}

双指针

class Solution {
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headB == null || headA == null) return null;
        ListNode pA = headA, pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pB;
    }
}

在排序数组中查找数字 I

二分

class Solution {
    public int search(int[] nums, int target) {
        if (nums.length == 0) return 0;
        int l = 0;
        int r = nums.length - 1;
        //搜索右边界
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (nums[mid] <= target) l = mid;
            else r = mid - 1;
        }
        int right = l;
        if (r >= 0 &&nums[r] != target) return 0;
        l = 0;
        r = nums.length - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (nums[mid] >= target) r = mid;
            else l = mid + 1;
        }
        int left = l;
        return right - left + 1;
    }
}

0~n-1中缺失的数字

class Solution {
    public int missingNumber(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != i) return i;
        }
        return nums.length;
    }
}

二叉搜索树的第k大节点

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res, k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    void dfs(TreeNode root) {
        if (root == null) return ;
        dfs(root.right);
        if (k == 0) return ;
        if (--k == 0) res = root.val;
        dfs(root.left);
    }
}

二叉树的深度

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        } else {
            int leftHeight = maxDepth(root.left);
            int rightHeight = maxDepth(root.right);
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }
}

平衡二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null) {
            return true;
        } else {
            return Math.abs(height(root.left) - height(root.right) ) <= 1 && (isBalanced(root.right) && isBalanced(root.left));
        }
    }
    public int height(TreeNode root) {
        if (root == null) return 0;
        else {
            return Math.max(height(root.left), height(root.right)) + 1;
        }
    }
}

数组中数字出现的次数

class Solution {
    public int[] singleNumbers(int[] nums) {
        int x = 0, y = 0, n = 0, m = 1;
        for (int num : nums) {
            n ^= num;
        }
        while ((n & m) == 0) {
            m <<= 1;
        }
        for (int num :nums) {
            if ((num &m) != 0) x ^= num;
            else y ^= num;
        }
        return new int[] {x, y};
    }
}

数组中数字出现的次数 II

class Solution {
    public int singleNumber(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if (entry.getValue() == 1) return entry.getKey();
        }
        return -1;
    }
}

和为s的两个数字

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int i = 0, j = nums.length - 1;
        while (i <j) {
            int s= nums[i] +nums[j];
            if (s < target) i++;
            else if (s > target) j--;
            else return new int[] {nums[i], nums[j]};
        }
        return new int[0];
    }
}

和为s的连续正数序列

class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> res = new ArrayList<int[]>();
        for (int l = 1, r = 2; l < r;) {
            int sum = (l + r)*(r - l +1) / 2;
            if (sum == target) {
                int[] ans = new int[r - l + 1];
                for (int i = l; i <= r; i++ ) {
                    ans[i - l] = i;
                }
                res.add(ans);
                l++;
            } else if (sum < target) {
                r++;
            } else l++;
        }
        return res.toArray(new int[res.size()][]);
    }
}

翻转单词顺序

class Solution {
    public String reverseWords(String s) {
        // s = s.trim();
        // List<String> wordList = Arrays.asList(s.split("\\s+"));
        // Collections.reverse(wordList);
        // return String.join(" ", wordList);

        int left = 0, right = s.length() - 1;
        while (left <= right && s.charAt(left) == ' ') {
            left ++;
        }
        while (right >= left && s.charAt(right) == ' ') {
            right --;
        }
        Deque<String> d = new ArrayDeque<String>();
        StringBuilder word = new StringBuilder();
        while (left <= right) {
            char c = s.charAt(left);
            if (word.length() != 0 && c == ' ') {
                d.offerFirst(word.toString());
                word.setLength(0);
            } else if (c != ' ') {
                word.append(c);
            }
            left++;
        }
        d.offerFirst(word.toString());
        return String.join(" ", d);
    }
}

滑动窗口的最大值

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 0 || k == 0 ) return new int[0];
        Deque<Integer> deque = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];
        for (int i = 0;  i < k; i++) {
            while (!deque.isEmpty() && deque.peekLast() < nums[i]) {
                deque.removeLast();
            }
            deque.addLast(nums[i]);
        }
        res[0] = deque.peekFirst();
        for (int i = k; i < nums.length; i++) {
            if (deque.peekFirst() == nums[i - k]) deque.removeFirst();
            while (!deque.isEmpty() && deque.peekLast() < nums[i]) {
                deque.removeLast();
            }
            deque.addLast(nums[i]);
            res[i - k + 1] = deque.peekFirst();
        }
        return res;
    }
}

n个骰子的点数

class Solution {
    public double[] dicesProbability(int n) {
        double[][] dp = new double[n + 1][6 *n + 1];
        for (int i = 1; i <= 6; i++) dp[1][i] = (double) 1/6;
        for (int i = 2; i <= n; i++){
            for (int j = i; j <= 6 * i; j++) {
                for (int k = 1; k <= 6; k++ ){
                    if (j - k < 1) continue;
                    dp[i][j] += dp[1][k] * dp[i - 1][j - k];
                }
            }
        }
        double[] res = new double[5 * n + 1];
        int id = n;
        for (int i = 0; i < res.length; i++) {
            res[i] = dp[n][id++];
        }
        return res;
    }
}

圆圈中最后剩下的数字

class Solution {
    public int lastRemaining(int n, int m) {
       // return f(n , m);
       int f = 0;
       for (int i = 2; i != n +1; i++) {
           f = (f +m ) %i;
       }
       return f;
    }
    // public int f(int n, int m) {
    //     if (n == 1) return 0;
    //     return (f(n - 1, m) + m) % n;
    // }
}

股票的最大利润

class Solution {
    public int maxProfit(int[] prices) {
        int cost = Integer.MAX_VALUE, profit = 0;
        for (int price :prices) {
            cost = Math.min(cost, price);
            profit = Math.max(profit, price - cost);
        }
        return profit;
    }
}

求1+2+…+n

class Solution {
    public int sumNums(int n) {
        return n == 0 ? 0 : n + sumNums(n - 1);
    }
}

不用加减乘除做加法

class Solution {
    public int add(int a, int b) {
        while (b != 0) {
            int carry = (a & b) << 1;
            a = a ^ b;
            b = carry;
        }
        return a;
    }
}

构建乘积数组

class Solution {
    public int[] constructArr(int[] a) {
        int len = a.length;
        if (len == 0) return new int[0];
        int[] b = new int[len];
        b[0] = 1;
        int tmp = 1;
        for (int i = 1; i < len; i++) {
            b[i] = b[i - 1] * a[i - 1];
        }
        for (int i = len - 2; i >= 0; i--) {
            tmp *= a[i + 1];
            b[i] *= tmp;
        }
        return b;
    }
}

二叉搜索树的最近公共祖先

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode ancestor = root;
        while (true) {
            if (p.val < ancestor.val && q.val < ancestor.val) {
                ancestor = ancestor.left;
            } else if (p.val > ancestor.val && q.val > ancestor.val) {
                ancestor = ancestor.right;
            } else break;
        }
        return ancestor;
    }
}

二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right= lowestCommonAncestor(root.right, p, q);
        if (left == null) return right;
        if (right == null) return left;
        return root;
    }
}

机器人的运动范围

class Solution {
    public int movingCount(int m, int n, int k) {
        if (k == 0) return 1;
        Queue<int[]> queue = new LinkedList<int[]>();
        int[] dx = {0, 1};
        int[] dy = {1, 0};
        boolean[][] vis = new boolean[m][n];
        queue.offer(new int[]{0, 0});
        int res = 1;
        vis[0][0] = true;
        while (queue.size() != 0) {
            int[] cell = queue.poll();
            int x= cell[0], y  = cell[1];
            for (int i= 0; i < 2; i++) {
                int xx = x + dx[i];
                int yy = y + dy[i];
                if (xx >= 0 && xx < m&& yy >= 0 && yy < n&&vis[xx][yy] == false && (get(xx) + get(yy) <= k)) {
                    vis[xx][yy] = true;
                    res ++;
                    queue.offer(new int[]{xx, yy});
                }
            }
        }
        return res;
    }
    public int get(int x) {
        int res = 0;
        while (x != 0) {
            res += x % 10;
            x /= 10;
        }
        return res;
    }
}

把数组排成最小的数

class Solution {
    public String minNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for (int i = 0; i < nums.length; i++) {
            strs[i] = String.valueOf(nums[i]);
        }
        Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
        StringBuilder res = new StringBuilder();
        for (String s : strs) {
            res.append(s);
        }
        return res.toString();
    }
}

队列的最大值

class MaxQueue {
    int[] q = new int[20000];
    int begin = 0, end = 0;
    public MaxQueue() {

    }
    
    public int max_value() {
        int ans = -1;
        for (int i = begin; i != end; ++i) {
            ans = Math.max(ans, q[i]);
        }
        return ans;
    }
    
    public void push_back(int value) {
        q[end++] = value;
    }
    
    public int pop_front() {
        if (begin == end) return -1;
        return q[begin++];
    }
}

/**
 * Your MaxQueue object will be instantiated and called as such:
 * MaxQueue obj = new MaxQueue();
 * int param_1 = obj.max_value();
 * obj.push_back(value);
 * int param_3 = obj.pop_front();
 */

扑克牌中的顺子

class Solution {
    public boolean isStraight(int[] nums) {
        Set<Integer> set = new HashSet<>();
        int max = 0, min = 14;
        for (int num : nums ) {
            if (num == 0) continue;
            max = Math.max(max, num);
            min = Math.min(min, num);
            if (set.contains(num)) return false;
            set.add(num);
        }
        return max - min < 5;
    }
}

把字符串转换成整数

class Solution {
public:
    int strToInt(string str) {
        if (str.empty()) return 0;
        int index = 0, n = str.size(), sign = 1, res = 0;
        while (index < n && str[index] == ' ') index++;
        if (index < n && (str[index]=='-' || str[index]=='+')) sign = str[index++] == '+' ? 1 : -1;
        while (index < n && isdigit(str[index])) {
            int digit = str[index] - '0';
            if (res > (INT_MAX - digit) / 10) return sign == 1 ? INT_MAX : INT_MIN;
            res = res * 10 + digit;
            index++;
        }
        return res*sign;
    }
};
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值