- 剑指offer 03.数组中的重复数字
- 剑指offer 04.二维数组中的查找
- 剑指offer 05.替换空格
- 剑指offer 06.从尾到头打印链表
- 剑指offer 07.重建二叉树
- 剑指offer 09.用两个栈实现队列
- 剑指offer 10-1.斐波那契数列
- 剑指offer 10-2.青蛙跳台阶问题
- 剑指offer 11.旋转数组的最小数字
- 剑指offer 12.矩阵中的路径
- 剑指offer 13.机器人的运动范围
- 剑指offer 14-|.减绳子
- 剑指offer 14-||.减绳子||
- 剑指offer 15.二进制中1的个数
- 剑指offer 16.数值的整数次方
- 剑指offer 17.打印从1到最大的n位数
- 剑指offer 18.删除链表的节点
- 剑指offer 19.正则表达式匹配
- 剑指offer 20.表示数值的字符串
- 剑指offer 21.调整数组顺序使奇数位于偶数前
- 剑指offer 22.链表中倒数第k个节点
- 剑指offer 24.反转链表
- 剑指offer 25.合并两个排序的链表
- 剑指offer 26.树的子结构
- 剑指offer 27.二叉树的镜像
- 剑指offer 28.对称的二叉树
- 剑指offer 29.顺序打印矩阵
- 剑指offer 30.包含min函数的栈
- 剑指offer 31.栈的压入,弹出序列
- 剑指offer 32-1.从上到下打印二叉树
- 剑指offer 32-2.从上到下打印二叉树
- 剑指offer 32-3.从上到下打印二叉树
- 剑指offer 33.二叉树的后序遍历序列
- 剑指offer 34.二叉树中和为某一值的路径
- 剑指offer 35.复杂链表的复制
- 剑指offer 36.二叉搜索树与双向链表
- 剑指offer 37.序列化二叉树
- 剑指offer 38.字符串的排列
- 剑指offer 39.数组中出现次数超过一半的数字
- 剑指offer 40.最小的k个数
- 剑指offer 41.数据流中的中位数
- 剑指offer 42.连续子数组的最大和
- 剑指offer 43.1~n整数中1出现的次数
- 剑指 Offer 44. 数字序列中某一位的数字">剑指 Offer 44. 数字序列中某一位的数字
- 剑指 Offer 45. 把数组排成最小的数">剑指 Offer 45. 把数组排成最小的数
- 剑指 Offer 46. 把数字翻译成字符串">剑指 Offer 46. 把数字翻译成字符串
- 剑指 Offer 47. 礼物的最大价值">剑指 Offer 47. 礼物的最大价值
- 剑指 Offer 48. 最长不含重复字符的子字符串">剑指 Offer 48. 最长不含重复字符的子字符串
- 剑指 Offer 49. 丑数">剑指 Offer 49. 丑数
- 剑指 Offer 50. 第一个只出现一次的字符">剑指 Offer 50. 第一个只出现一次的字符
- 剑指 Offer 51. 数组中的逆序对">剑指 Offer 51. 数组中的逆序对
- 剑指 Offer 52. 两个链表的第一个公共节点">剑指 Offer 52. 两个链表的第一个公共节点
- 剑指 Offer 53 - I. 在排序数组中查找数字 I">剑指 Offer 53 - I. 在排序数组中查找数字 I
- 剑指 Offer 53 - II. 0~n-1中缺失的数字">剑指 Offer 53 - II. 0~n-1中缺失的数字
- 剑指 Offer 54. 二叉搜索树的第k大节点">剑指 Offer 54. 二叉搜索树的第k大节点
- 剑指 Offer 55 - I. 二叉树的深度">剑指 Offer 55 - I. 二叉树的深度
- 剑指 Offer 55 - II. 平衡二叉树">剑指 Offer 55 - II. 平衡二叉树
- 剑指 Offer 56 - I. 数组中数字出现的次数">剑指 Offer 56 - I. 数组中数字出现的次数
- 剑指 Offer 56 - II. 数组中数字出现的次数 II">剑指 Offer 56 - II. 数组中数字出现的次数 II
- 剑指 Offer 57. 和为s的两个数字">剑指 Offer 57. 和为s的两个数字
- 剑指 Offer 57 - II. 和为s的连续正数序列">剑指 Offer 57 - II. 和为s的连续正数序列
- 剑指 Offer 58 - I. 翻转单词顺序">剑指 Offer 58 - I. 翻转单词顺序
- 剑指 Offer 58 - II. 左旋转字符串">剑指 Offer 58 - II. 左旋转字符串
- 剑指 Offer 59 - I. 滑动窗口的最大值">剑指 Offer 59 - I. 滑动窗口的最大值
- 剑指 Offer 59 - II. 队列的最大值">剑指 Offer 59 - II. 队列的最大值
- 剑指 Offer 60. n个骰子的点数">剑指 Offer 60. n个骰子的点数
- 剑指 Offer 61. 扑克牌中的顺子">剑指 Offer 61. 扑克牌中的顺子
- 剑指 Offer 62. 圆圈中最后剩下的数字">剑指 Offer 62. 圆圈中最后剩下的数字
- 剑指 Offer 63. 股票的最大利润">剑指 Offer 63. 股票的最大利润
- 剑指 Offer 64. 求1+2+…+n">剑指 Offer 64. 求1+2+…+n
- 剑指 Offer 65. 不用加减乘除做加法">剑指 Offer 65. 不用加减乘除做加法
- 剑指 Offer 66. 构建乘积数组">剑指 Offer 66. 构建乘积数组
- 剑指 Offer 67. 把字符串转换成整数">剑指 Offer 67. 把字符串转换成整数
- 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先">剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
- 剑指 Offer 68 - II. 二叉树的最近公共祖先">剑指 Offer 68 - II. 二叉树的最近公共祖先
解题视频https://www.bilibili.com/video/BV1cz4y1S7AX?p=1
剑指offer 03.数组中的重复数字


class Solution {public int findRepeatNumber(int[] nums) {Set<Integer> set = new HashSet<>();int repeat = -1;for(int num:nums){if(!set.add(num)){repeat = num;break;}}return repeat;}}
剑指offer 04.二维数组中的查找

class Solution {public boolean findNumberIn2DArray(int[][] matrix, int target) {if(matrix == null || matrix.length == 0 || matrix[0].length == 0){return false;}int rows = matrix.length;int cols = matrix[0].length;int row = 0;int col = cols - 1;while(row < rows && col >=0){if(matrix[row][col] == target){return true;}else if(matrix[row][col] > target){col--;}else{row++;}}return false;}}
剑指offer 05.替换空格

class Solution {public String replaceSpace(String s) {int length = s.length();char[] carry = new char[length * 3];int size = 0;for(int i = 0; i< length; i++){char c = s.charAt(i);if(c == ' '){carry[size++] = '%';carry[size++] = '2';carry[size++] = '0';}else{carry[size++] = c;}}String newStr = new String(carry,0,size);return newStr;}}
剑指offer 06.从尾到头打印链表


/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/class Solution {public int[] reversePrint(ListNode head) {if(head == null){return new int[]{};}Stack<Integer> stack = new Stack<>();ListNode cur = head;while(cur != null){stack.push(cur.val);cur = cur.next;}int[] res = new int[stack.size()];for(int i = 0; i < res.length; i++){res[i] = stack.pop();}return res;}}
剑指offer 07.重建二叉树


/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/class Solution {public TreeNode buildTree(int[] preorder, int[] inorder) {if(preorder == null || preorder.length == 0){return null;}HashMap<Integer,Integer> hashmap = new HashMap<>();for(int i = 0; i < inorder.length; i++){hashmap.put(inorder[i],i);}return dfs(preorder,0,preorder.length - 1,0,hashmap);}public TreeNode dfs(int[] preorder,int pl,int pr,int il,HashMap<Integer,Integer> hashmap){if(pl > pr){return null;}TreeNode curRoot = new TreeNode(preorder[pl]);int k = hashmap.get(curRoot.val);curRoot.left = dfs(preorder,pl+1,pl+(k-il),il,hashmap);curRoot.right = dfs(preorder,pl+(k-il)+1,pr,k+1,hashmap);return curRoot;}}
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/class Solution {public TreeNode buildTree(int[] preorder, int[] inorder) {if(preorder == null || preorder.length == 0){return null;}Map<Integer, Integer> indexMap = new HashMap<>();int length = preorder.length;for(int i = 0; i < length; i++){indexMap.put(inorder[i],i);}TreeNode root = buildTree(preorder,0,length -1,inorder,0,length-1,indexMap);return root;}public TreeNode buildTree(int[] preorder, int preorderStart,int preorderEnd,int[] inorder,int inorderStart,int inorderEnd,Map<Integer,Integer> indexMap){if(preorderStart > preorderEnd){return null;}int rootVal = preorder[preorderStart];TreeNode root = new TreeNode(rootVal);if(preorderStart == preorderEnd){return root;}else{int rootIndex = indexMap.get(rootVal);int leftNodes = rootIndex - inorderStart,rightNodes = inorderEnd - rootIndex;TreeNode leftSubtree = buildTree(preorder,preorderStart+1,preorderStart+leftNodes,inorder,inorderStart,rootIndex -1,indexMap);TreeNode rightSubtree = buildTree(preorder,preorderEnd - rightNodes + 1,preorderEnd,inorder,rootIndex + 1,inorderEnd,indexMap);root.left = leftSubtree;root.right = rightSubtree;return root;}}}
剑指offer 09.用两个栈实现队列


class CQueue {private Stack<Integer> stackin;private Stack<Integer> stackout;public CQueue() {stackin = new Stack<>();stackout = new Stack<>();}public void appendTail(int value) {stackin.push(value);}public int deleteHead() {if(stackout.isEmpty()){while(!stackin.isEmpty()){stackout.push(stackin.pop());}}if(!stackout.isEmpty()){return stackout.pop();}else{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 CQueue {private Deque<Integer> stackin;private Deque<Integer> stackout;public CQueue() {stackin = new LinkedList<>();stackout = new LinkedList<>();}public void appendTail(int value) {stackin.push(value);}public int deleteHead() {if(stackout.isEmpty()){while(!stackin.isEmpty()){stackout.push(stackin.pop());}}if(!stackout.isEmpty()){return stackout.pop();}else{return -1;}}}/*** Your CQueue object will be instantiated and called as such:* CQueue obj = new CQueue();* obj.appendTail(value);* int param_2 = obj.deleteHead();*/
剑指offer 10-1.斐波那契数列


class Solution {public int fib(int n) {if(n == 0){return 0;}int a = 0;int b = 1;int sum = 0;for(int i= 0; i < n; i++){sum = (a+b)%1000000007;a = b;b = sum;}return a;}}
剑指offer 10-2.青蛙跳台阶问题
剑指offer 11.旋转数组的最小数字

class Solution {public int minArray(int[] numbers) {int low = 0;int hight = numbers.length - 1;while(low < hight){int pivot = low + (hight - low)/2;if(numbers[pivot] < numbers[hight]){hight = pivot;}else if(numbers[pivot] > numbers[hight]){low = pivot + 1;}else if(numbers[pivot] == numbers[hight]){hight--;}}return numbers[low];}}
剑指offer 12.矩阵中的路径
class Solution {public boolean exist(char[][] board, String word) {if(board == null || board.length == 0) return false;int rows = board.length;int cols = board[0].length;boolean[][] isVisited = new boolean[rows][cols];//标记数组//路径可以从矩阵中任意一格开始,所以分别以矩阵中的每一个字符作为起点寻找for(int i = 0; i < rows;i++){for(int j = 0; j < cols; j++){if(dfs(board,word,0,i,j,isVisited)){return true;}}}return false;}//参数说明,n表示当前访问到第几个字符了,(x,y)表示当前要访问的字符在board中的坐标private boolean dfs(char[][] board,String word,int n,int x,int y,boolean[][] isVisited){//当前位置和我们需要的字符word.charAt(n)不同,该路径行不通if(board[x][y] != word.charAt(n)) return false;//我们要查找的最后一个字符都通过了上面那条if语句,该单词路径存在if(n == word.length() - 1) return true;isVisited[x][y] = true;//标记board[x][y]已经被访问过了//定义左右上下四个方向(偏移量技巧)int[] dx = {-1,1,0,0};int[] dy = {0,0,-1,1};for(int i = 0; i < 4;i++){//分别尝试往左右上下四个方向走//改变方向,注意这里不是用x = x+dx[i],而是用a和b接收,以保证下轮循环时x,y是原来的值int a = x + dx[i];int b = y + dy[i];//保证a,b不越界,且board[a][b]还未被访问过if(a >= 0 && a < board.length && b >= 0 && b < board[0].length && !isVisited[a][b]){if(dfs(board,word,n+1,a,b,isVisited)){return true;}}}isVisited[x][y] = false; //状态回退return false;}}

class Solution {public boolean exist(char[][] board, String word) {char[] words = word.toCharArray();for(int i = 0; i < board.length; i++){for(int j = 0; j < board[0].length; j++){if(dfs(board, words, i, j, 0)){return true;}}}return false;}public boolean dfs(char[][] board, char[] word, int i, int j, int k){if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]){return false;}if(k == word.length - 1){return true;}board[i][j] = '\0';boolean res = dfs(board, word, i+1, j, k+1) || dfs(board, word, i - 1, j, k+1) ||dfs(board, word, i, j + 1, k+1) || dfs(board, word, i ,j -1, k+1);board[i][j] = word[k];return res;}}
剑指offer 13.机器人的运动范围
递归参数的设置,与变量的作用域有关,局部 变量不可以调用,必须设置为全局变量才可以






class Solution {private int count = 0;public int movingCount(int m, int n, int k) {if(m < 0||n < 0){return -1;}boolean[][] isVisited = new boolean[m][n];dfs(m,n,k,isVisited,0,0);return count;}private void dfs(int m,int n,int k,boolean[][] isVisited,int x,int y){//坐标越界或者已经访问过,直接返回退出本次调用栈if(x < 0 || x >=m||y < 0 ||y >= n|| isVisited[x][y]){return;}isVisited[x][y] = true;//标记该坐标访问过了;//当确定机器人可以进入该坐标之后,才需要从这坐标向四个方向扩散if(getSum(x,y) <= k){count++;int[] dx = {-1,1,0,0};int[] dy = {0,0,-1,1};for(int i = 0; i < 4; i++){int a = x + dx[i];int b = y + dy[i];dfs(m,n,k,isVisited,a,b);}}else{return; //机器人无法到达}}private int getSum(int x,int y){int res = 0;while(x > 0){res += x % 10;x /=10;}while(y > 0){res += y % 10;y /= 10;}return res;}}
剑指offer 14-|.减绳子




class Solution {public int cuttingRope(int n) {if(n <= 3){return n-1;}int a = n/3;int b = n%3;if(b == 1){return (int)Math.pow(3,(a-1))*4;}if(b == 0){return (int)Math.pow(3,a);}return (int)Math.pow(3,a)*2;}}
剑指offer 14-||.减绳子||


class Solution {public int cuttingRope(int n) {if(n<=3) return n-1;int a=n/3;int b=n%3;//循环a-1次:res=pow(3,a-1)long res=1;int mod=1000000007;for(int i=0;i<a-1;i++){res=res*3;res=res%mod;}if(b==0)//乘3 pow(3,a)return (int)(res*3%mod);if(b==1)//乘4 pow(3,a-1)*4return (int)(res*4%mod);else//乘3 乘2 pow(3,a)*2return (int)((res*3%mod)*2%mod);}}
剑指offer 15.二进制中1的个数

public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n) {int result = 0;while(n != 0){result = result + (n & 1);n = n >>> 1;}return result;}}
剑指offer 16.数值的整数次方



class Solution {public double myPow(double x, int n) {//快速幂//n可以用二进制表示//9=1001=1*1 + 0*2 + 0*4 + 1*8//x^9 = x^(1*1) x^(0*2) x^(0*4) x^(1*8)if(x == 0){return 0;}//int范围[−2147483648,2147483647],当n = -2147483648,时执行 n = -n会越界,使用long类型long b = n;double res = 1.0;if(b < 0){b = -b;x = 1/x;}while(b > 0){if((b & 1) == 1){res = res * x; //累乘 //指数}x = x * x; //相当于x^2 //底数 每次都要平方b = b >>> 1; //右移一位}return res;}}
剑指offer 17.打印从1到最大的n位数

class Solution {public int[] printNumbers(int n) {if(n <= 0){return new int[0];}int max = (int)Math.pow(10, n);int[] arr = new int[max - 1];for(int i = 0; i < max-1; i++){arr[i] = i + 1;}return arr;}}
剑指offer 18.删除链表的节点

/*** 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) {ListNode domp = new ListNode(-1);domp.next = head;ListNode tem = domp;while(tem.next != null){if(tem.next.val == val){tem.next = tem.next.next;break;}tem = tem.next;}return domp.next;}}

/*** 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 == null){return head;}if(head.val == val){return head.next;}ListNode pre = head;ListNode last = head.next;while(last.next != null && last.val != val){pre = last;last = last.next;}pre.next = (last == null) ? null:last.next;return head;}}
剑指offer 19.正则表达式匹配

class Solution {static boolean[][] dp;static int n,m;public static boolean isMatch(String s, String p){char[] ss = s.toCharArray();char[] ps = p.toCharArray();dp = new boolean[ss.length + 1][ps.length + 1];n = ss.length;m = ps.length;dp[n][m] = true;return dp(0,0,ss,ps);}private static boolean dp(int i, int j, char[] ss, char[] ps){if (dp[i][j]){return dp[i][j];}// 模式串匹配完成,判断是否匹配完字符串if (j == m){return dp[i][j] = i == n;}// 出现两个串字符相同或者模式串为'.'时则为trueboolean firstMatch = i < n && (ss[i] == ps[j] || ps[j] == '.');boolean ans;if (j + 1 < m && ps[j + 1] == '*'){// j + 2意味着 *号和之前的一个元素没有被匹配到则跳过ans = dp(i,j + 2, ss, ps) || firstMatch && dp(i + 1, j, ss, ps);}else {ans = firstMatch && dp(i + 1, j + 1, ss, ps);}return dp[i][j] = ans;}}
class Solution {public boolean isMatch(String s, String p) {int m = s.length();int n = p.length();boolean[][] f = new boolean[m + 1][n + 1];f[0][0] = true;for(int i = 0; i <= m; ++i){for(int j = 1; j <= n; ++j){if(p.charAt(j - 1) == '*'){f[i][j] = f[i][j - 2];if(matches(s, p ,i , j - 1)){f[i][j] = f[i][j] || f[i - 1][j];}}else{if(matches(s, p, i, j)){f[i][j] = f[i - 1][j - 1];}}}}return f[m][n];}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);}}
剑指offer 20.表示数值的字符串
class Solution {public boolean isNumber(String s) {int n = s.length();int index = 0;boolean hasNum = false, hasE = false;boolean hasSign = false, hasDot = false;while(index < n && s.charAt(index) == ' ')index++;while(index < n){while(index < n && s.charAt(index) >= '0' && s.charAt(index) <= '9'){index++;hasNum = true;}if(index == n){break;}char c = s.charAt(index);if(c == 'e' || c == 'E'){if(hasE || !hasNum){return false;}hasE = true;hasNum = false; hasSign = false; hasDot = false;}else if(c == '+' || c == '-'){if(hasSign || hasNum || hasDot){return false;}hasSign = true;}else if(c == '.'){if(hasDot || hasE){return false;}hasDot = true;}else if(c == ' '){break;}else{return false;}index++;}while(index < n && s.charAt(index) == ' ')index++;return hasNum && index == n;}}
剑指offer 21.调整数组顺序使奇数位于偶数前

class Solution {public int[] exchange(int[] nums) {if(nums == null || nums.length == 0) return nums;int[] res = new int[nums.length];int left = 0;int right = nums.length - 1;for(int i = 0; i < nums.length; i++){if(nums[i] % 2 != 0){res[left++] = nums[i]; //奇数从前往后放}else{res[right--] = nums[i]; //偶数从后往前放}}return res;}}

class Solution {public int[] exchange(int[] nums) {if(nums.length == 0){return nums;}int length = nums.length;int length1 = length - 1;int length2 = 0;int[] arr = new int[length];for(int i = 0; i < length; i++){if(nums[i] % 2 != 0){arr[length2] = nums[i];length2++;}else{arr[length1] = nums[i];length1--;}}return arr;}}
剑指offer 22.链表中倒数第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) {ListNode fir = head;ListNode sec = head;for(int i = 0; i < k; i++){fir = fir.next;}while(fir != null){fir = fir.next;sec = sec.next;}return sec;}}
剑指offer 24.反转链表

/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/class Solution {public ListNode reverseList(ListNode head) {ListNode pre = null;ListNode cur = head;while(cur != null){ListNode next = cur.next;cur.next = pre;pre = cur;cur = next;}return pre;}}
剑指offer 25.合并两个排序的链表
/*** 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;if(l2 == null) return l1;ListNode p1 = l1; //用于遍历l1ListNode p2 = l2; //用于遍历l2ListNode dummy = new ListNode(0); //新建链表虚拟头节点ListNode cur = dummy; //辅助构建新链表//两个链表都未遍历结束时,比较当前节点的大小,拼接到新链表之后while(p1 != null && p2 != null){if(p1.val < p2.val){cur.next = p1;p1 = p1.next;cur = cur.next;}else{cur.next = p2;p2 = p2.next;cur = cur.next;}}//退出while循环后,说明肯定有一个链表遍历结束if(p1 == null){cur.next = p2;}if(p2 == null){cur.next = p1;}return dummy.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) {ListNode pom = new ListNode(0);ListNode cur = pom;while(l1 != null && l2 != null){if(l1.val < l2.val){cur.next = l1;l1 = l1.next;}else{cur.next = l2;l2 = l2.next;}cur = cur.next;}cur.next = l1 != null ? l1:l2;return pom.next;}}
剑指offer 26.树的子结构
/*** 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;//直接判断A是否是B作为根节点的开始的一部分,不是再递归A,让A的左右节点分别作为新树的根节点if(isPart(A,B)) return true;return isSubStructure(A.left,B) || isSubStructure(A.right,B);}public boolean isPart(TreeNode A,TreeNode B){//A和B根节点相同,再递归的判断他们各自的左右节点的值是否相同,递归的终止条件是://到达了树A或树B的叶子节点,或者两个的值不相等if(B == null) return true;//通过上面的if判断,说明B当前节点不是空,//如果此时A空了,或者A和B当前节点的值不同,则B不是A的子结构if(A == null || A.val != B.val) return false;return isPart(A.left, B.left) && isPart(A.right, B.right);}}

/*** 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) {return (A != null && B != null) && (res(A,B) || isSubStructure(A.left, B) || isSubStructure(A.right,B));}private boolean res(TreeNode A, TreeNode B){if(B == null){return true;}if(A == null || A.val != B.val){return false;}return res(A.left, B.left) && res(A.right, B.right);}}
剑指offer 27.二叉树的镜像

/*** 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 null;swap(root);mirrorTree(root.left);mirrorTree(root.right);return root;}//交换根节点的左右子节点,root的左右孩子是null也可以用swap函数,只要root不是null即可//毕竟root是null,root.legt root.right就空指针异常了private void swap(TreeNode root){TreeNode temp = root.left;root.left = root.right;root.right = temp;}}
剑指offer 28.对称的二叉树

/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*///递归判断两个子树是否互为镜像。//两个子树互为镜像当且仅当://1. 两个子树的根节点值相等;//2. 第一棵子树的左子树和第二棵子树的右子树互为镜像,且第一棵子树 的右子树和第二棵子树的左子树互为镜像。class Solution {public boolean isSymmetric(TreeNode root) {if(root == null) return true;return dfs(root,root);}public boolean dfs(TreeNode p, TreeNode q){if(p == null && q == null) return true; //两树空视为想等if(p == null || q == null) return false; //结合上一个if,代表一个为空,另一个不为空,不可能相等if(p.val != q.val) return false; //镜像的值不同return dfs(p.left, q.right) && dfs(p.right, q.left);}}
剑指offer 29.顺序打印矩阵

class Solution {public int[] spiralOrder(int[][] matrix) {if(matrix.length == 0) return new int[0];int l = 0; //左边界int r = matrix[0].length-1; //右边界int t = 0; //上边界int b = matrix.length - 1; //下边界int x = 0;int[] res = new int[(r + 1) * (b + 1)];while(true){for(int i = l;i <= r;i++) res[x++] = matrix[t][i];// left to right.if(++t > b) break;for(int i = t;i <= b;i++) res[x++] = matrix[i][r];// top to bottom.if(l > --r) break;for(int i = r;i >= l;i--) res[x++] = matrix[b][i];// right to left.if(t > --b) break;for(int i = b;i >= t;i--) res[x++] = matrix[i][l];// bottom to top.if(++l > r) break;}return res;}}
剑指offer 30.包含min函数的栈
class MinStack {
Stack<Integer> stack;//实际数据栈
Stack<Integer> minStack;//辅助栈,栈顶一直存储当前最小元素,数据个数和实际数据栈中个数一致
/** initialize your data structure here. */
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int x) {
stack.push(x);
//辅助栈为空或者当前入栈元素小于之前的最小值,说明当前元素就是最小值
if(minStack.isEmpty() || x < minStack.peek()){
minStack.push(x);
}else{//辅助栈顶元素仍然是最小的,让他再次入栈
int temp = minStack.peek();
minStack.push(temp);
}
}
public void pop() {
stack.pop();
//数据栈弹出了一个元素,辅助栈相应弹出一个元素
minStack.pop();
}
public int top() {
return stack.peek();
}
public int min() {
return minStack.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();
*/
剑指offer 31.栈的压入,弹出序列

class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
if(pushed == null){
return false;
}
Stack<Integer> stack = new Stack<>();
int i = 0;
for(int num : pushed){
stack.push(num);
while(!stack.isEmpty() && popped[i] == stack.peek()){
stack.pop();
i++;
}
}
return stack.isEmpty();
}
}
剑指offer 32-1.从上到下打印二叉树

/**
* 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<>();
ArrayList<Integer> arr = new ArrayList<>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
arr.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
int[] res = new int[arr.size()];
for(int i = 0; i < res.length; i++){
res[i] = arr.get(i);
}
return res;
}
}
剑指offer 32-2.从上到下打印二叉树

/**
* 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<>();
ArrayList<Integer> arr = new ArrayList<>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
arr.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
int[] res = new int[arr.size()];
for(int i = 0; i < res.length; i++){
res[i] = arr.get(i);
}
return res;
}
}
剑指offer 32-3.从上到下打印二叉树

/**
* 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) {
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root != null){
queue.add(root);
}
while(!queue.isEmpty()){
int size = queue.size();
LinkedList<Integer> list = new LinkedList<>();
for(int i = 0; i < size; i++){
TreeNode node = queue.poll();
if(res.size() % 2 == 0){
list.addLast(node.val);
}else{
list.addFirst(node.val);
}
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
res.add(list);
}
return res;
}
}
剑指offer 33.二叉树的后序遍历序列

class Solution {
public boolean verifyPostorder(int[] postorder) {
return res(postorder, 0 , postorder.length - 1);
}
private boolean res(int[] postorder, int i, int j){
if(i >= j){
return true;
}
int p = i;
while(postorder[p] < postorder[j]) p++;
int m = p;
while(postorder[p] > postorder[j]) p++;
return p==j&&res(postorder, i , m-1)&&res(postorder, m ,j-1);
}
}
剑指offer 34.二叉树中和为某一值的路径

/**
* 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 {
LinkedList<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
res(root, target);
return res;
}
public void res(TreeNode root, int target){
if(root == null){
return;
}
path.add(root.val);
target = target - root.val;
if(target == 0 && root.left== null && root.right==null){
res.add(new LinkedList(path));
}
res(root.left, target);
res(root.right, target);
path.removeLast();
}
}
剑指offer 35.复杂链表的复制


/*
// 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 copy = new Node(cur.val);
copy.next = cur.next;
cur.next = copy;
cur = cur.next.next;;
}
//第二步:复制random指针
cur = head;
while(cur != null ){
if(cur.random != null){
cur.next.random = cur.random.next;
}
cur = cur.next.next;
}
//第三步:分开两个链表,并将原链表还原。
Node dummy = new Node(-1);//复制链表的虚拟头节点
Node help = dummy;//辅助建立复制的链表
cur = head;
while(cur != null){
help.next = cur.next;
help = help.next;
cur.next = cur.next.next;
cur = cur.next;
}
return dummy.next;
}
}
剑指offer 36.二叉搜索树与双向链表


/*
// 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 {
Node head, pre;
public Node treeToDoublyList(Node root) {
if(root==null) return null;
dfs(root);
pre.right = head;
head.left =pre;//进行头节点和尾节点的相互指向,这两句的顺序也是可以颠倒的
return head;
}
public void dfs(Node cur){
if(cur==null) return;
dfs(cur.left);
//pre用于记录双向链表中位于cur左侧的节点,即上一次迭代中的cur,
//当pre==null时,cur左侧没有节点,即此时cur为双向链表中的头节点
if(pre==null) head = cur;
//反之,pre!=null时,cur左侧存在节点pre,需要进行pre.right=cur的操作。
else pre.right = cur;
cur.left = pre;//pre是否为null对这句没有影响,且这句放在上面两句if else之前也是可以的。
pre = cur;//pre指向当前的cur
dfs(cur.right);//全部迭代完成后,pre指向双向链表中的尾节点
}
}
剑指offer 37.序列化二叉树


/**
* 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 t = q.poll();
if(t != null){
res.append(t.val + ",");
q.add(t.left);
q.add(t.right);
}else{
res.append("null,");
}
}
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));
剑指offer 38.字符串的排列

class Solution {
Set<String> res = new HashSet<>();
public String[] permutation(String s) {
if(s == null) return new String[]{};
boolean[] visisted = new boolean[s.length()];
dfs(s, "", visisted);
return res.toArray(new String[res.size()]);
}
private void dfs(String s, String ch, boolean[] visisted){
if(s.length() == ch.length()){
res.add(ch); //abc
return;
}
for(int i = 0; i < s.length(); i++){
char temp = s.charAt(i);
if(visisted[i]) continue;
visisted[i] = true;
dfs(s, ch + String.valueOf(temp), visisted);
visisted[i] = false;
}
}
}
剑指offer 39.数组中出现次数超过一半的数字

class Solution {
public int majorityElement(int[] nums) {
int val = -1;
int cnt = 0;
for(int num: nums){
if(num == val){
cnt++;
}else{
if(cnt >= 1){
cnt--;
}else{
val = num;
cnt = 1;
}
}
}
return val;
}
}
剑指offer 40.最小的k个数

class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] res = new int[k];
//PriorityQueue是Queue的一个实现类
//默认是小顶堆,建立大顶堆则需要构造时传自定义的Comparator参数
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o2 - o1;//从大到小排
}
});
//大顶堆中保留最小的k个数
for(int i = 0;i < arr.length;i++){
queue.add(arr[i]);
if(queue.size() > k) queue.poll();
}
for(int i = 0;i < k;i++){
res[i] = queue.poll();
}
return res;
}
}

class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(k == 0 || arr.length == 0){
return new int[0];
}
return qsk(arr, 0, arr.length - 1, k - 1);
}
private int[] qsk(int[] nums, int l, int r, int k){
int j = quicksort(nums, l , r);
if(j == k){
return Arrays.copyOf(nums, j+1);
}
return j > k ? qsk(nums, l , j - 1, k): qsk(nums, j+1, r, k);
}
private int quicksort(int[] nums, int l ,int r){
int v = nums[l];
int i = l, j = r + 1;
while(true){
while(++i <= r && nums[i] < v);
while(--j >=l && nums[j] > v);
if(i >= j){
break;
}
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
nums[l] = nums[j];
nums[j] = v;
return j; //保证Nums[j] 左边是最小的j个数字
}
}
剑指offer 41.数据流中的中位数


class MedianFinder {
Queue<Integer> minQueue;
Queue<Integer> maxQueue;
/** initialize your data structure here. */
public MedianFinder() {
minQueue = new PriorityQueue<>();
maxQueue = new PriorityQueue<>(new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o2 - o1;
}
});
}
public void addNum(int num) {
maxQueue.add(num);
if(!minQueue.isEmpty() && maxQueue.peek() > minQueue.peek()){
int temp1 = maxQueue.poll();
int temp2 = minQueue.poll();
maxQueue.add(temp2);
minQueue.add(temp1);
}
if(maxQueue.size() > minQueue.size() + 1){
int temp = maxQueue.poll();
minQueue.add(temp);
}
}
public double findMedian() {
int count = minQueue.size() + maxQueue.size();//数据流中当前共有多少数
if((count & 1) != 0){//奇数
return maxQueue.peek();
}else{//偶数
//注意需要返回的是double类型,故除2.0,写成2的话是整数除法,返回int型
return (maxQueue.peek() + minQueue.peek()) / 2.0;
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/



class MedianFinder {
Queue<Integer> A, B;
/** initialize your data structure here. */
public MedianFinder() {
A = new PriorityQueue<>();//小根堆 存大的一半数字
B = new PriorityQueue<>((x,y) -> (y - x));//大根堆 存小的一半数字
}
public void addNum(int num) {
if(A.size() != B.size()){
A.add(num);//无脑放进小根堆
B.add(A.poll());//把小根堆中较小数字 放进大根堆
}else{
//堆顶比较 确保大小根堆的 一半的特性
B.add(num);//大数字 在堆顶
A.add(B.poll());//通过添加堆顶数字 确保 特性
}
}
public double findMedian() {
return A.size() == B.size() ? (A.peek() + B.peek())/2.0 : A.peek();
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
剑指offer 42.连续子数组的最大和

class Solution {
public int maxSubArray(int[] nums) {
int res = nums[0];
for(int i = 1; i < nums.length; i++){
nums[i] += Math.max(nums[i - 1], 0);
res = Math.max(res, nums[i]);
}
return res;
}
}

class Solution {
public int maxSubArray(int[] nums) {
// int res = nums[0];
// for(int i = 1; i < nums.length; i++){
// nums[i] = nums[i] + Math.max(nums[i - 1], 0);
// res = Math.max(res, nums[i]);
// }
// return res;
int length = nums.length;
int[] dp = new int[length];
dp[0] = nums[0];
int res = nums[0];
for(int i = 1; i < length; i++){
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
res = Math.max(res, dp[i]);
}
return res;
}
}
剑指offer 43.1~n整数中1出现的次数


class Solution {
public int countDigitOne(int n) {
int x = 1, res = 0;
int high = n / 10, cur = n % 10, low = 0;
while(cur != 0 || high != 0){
if(cur == 0){
res += high * x;
}else if(cur == 1){
res += high * x + low + 1;
}else{
res += (high + 1) * x;
}
low += cur * x;
cur = high % 10;
high /= 10;
x *= 10;
}
return res;
}
}
剑指 Offer 44. 数字序列中某一位的数字

class Solution {
public int findNthDigit(int n) {
int digit = 1;
long start = 1;
long count = 9;
while(n > count){
n -= count;
digit += 1;
start *= 10;
count = digit * start * 9;
}
long num = start + (n - 1)/digit;
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}
剑指 Offer 45. 把数组排成最小的数


class Solution {
public String minNumber(int[] nums) {
String[] str = new String[nums.length];
for(int i = 0; i < nums.length; i++){
str[i] = String.valueOf(nums[i]);
}
//字符串排序
strsort(str, 0, str.length - 1);
//Arrays.sort(str, (x,y) -> (x+y).compareTo(y+x));//内置函数
StringBuilder res = new StringBuilder();
for(String s : str){
res.append(s);
}
return res.toString();
}
public void strsort(String[] str, int l, int r){
if(l >= r) return ;
int i = l, j = r;
String temp = str[i];
while(i < j){
while((str[j] + str[l]).compareTo(str[l] + str[j]) >= 0 && i < j) j--;
while((str[i] + str[l]).compareTo(str[l] + str[i]) <= 0 && i < j) i++;
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
str[i] = str[l];
str[l] = temp;
strsort(str, l, i - 1);
strsort(str, i + 1, r);
}
}
剑指 Offer 46. 把数字翻译成字符串

class Solution {
public int translateNum(int num) {
//0 ~ 25
//dp[i] = dp[i -1] + dp[i -2]
String s = String.valueOf(num);
int a = 1, b = 1;
for(int i = 2; i <= s.length(); i++){
String temp = s.substring(i - 2, i);
int c = temp.compareTo("10") >= 0 && temp.compareTo("25") <= 0 ? a+b :a;
b = a;
a = c;
}
return a;
}
}
剑指 Offer 47. 礼物的最大价值

class Solution {
public int maxValue(int[][] grid) {
//最经典二维动态规划
//f[i][j] = max(f[i-1][j], f[i][j - 1])
int m = grid.length, n = grid[0].length;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(i == 0 && j == 0) continue;
if( i == 0){
grid[i][j] += grid[i][j - 1];
}
else if(j == 0){
grid[i][j] += grid[i - 1][j];
}else{
grid[i][j] += Math.max(grid[i - 1][j], grid[i][j - 1]);
}
}
}
return grid[m - 1][n - 1];
}
}
剑指 Offer 48. 最长不含重复字符的子字符串

class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> hash = new HashMap<>();
int res = 0, left = 0;
for(int i = 0; i< s.length(); i++){
char c = s.charAt(i);
//判断c是否出现过
if(hash.containsKey(c)){
left = Math.max(left, hash.get(c) + 1);
}
hash.put(c, i);
res = Math.max(res, i - left + 1);
}
return res;
}
}
剑指 Offer 49. 丑数

class Solution {
public int nthUglyNumber(int n) {
int[] f = new int[n]; //前n个丑数
int[] pos = new int[3]; //对应2 3 5 三个质因子
f[0] = 1; //第一个丑数
for(int i = 1; i < n; i++){
int a = f[pos[0]] * 2;
int b = f[pos[1]] * 3;
int c = f[pos[2]] * 5;
int mini = Math.min(Math.min(a,b),c);
if(f[pos[0]] * 2 == mini) pos[0]++;
if(f[pos[1]] * 3 == mini) pos[1]++;
if(f[pos[2]] * 5 == mini) pos[2]++;
f[i] = mini;
}
return f[n - 1];
}
}
剑指 Offer 50. 第一个只出现一次的字符

class Solution {
public char firstUniqChar(String s) {
HashMap<Character, Boolean> hash = new HashMap<>();
char[] ch = s.toCharArray();
for(char c : ch){
hash.put(c, !hash.containsKey(c)); //先插入true, 重复插入为false
}
for(char c : ch){
if(hash.get(c)){
return c;
}
}
return ' ';
}
}
剑指 Offer 51. 数组中的逆序对


class Solution {
int[] nums, tmp;
public int reversePairs(int[] nums) {
this.nums = nums;
tmp = new int[nums.length];
return mergeSort(0, nums.length - 1);
}
private int mergeSort(int l, int r) {
// 终止条件
if (l >= r) return 0;
// 递归划分
int m = (l + r) / 2;
int res = mergeSort(l, m) + mergeSort(m + 1, r);
// 合并阶段
int i = l, j = m + 1;
for (int k = l; k <= r; k++)
tmp[k] = nums[k];
for (int k = l; k <= r; k++) {
if (i == m + 1)
nums[k] = tmp[j++];
else if (j == r + 1 || tmp[i] <= tmp[j])
nums[k] = tmp[i++];
else {
nums[k] = tmp[j++];
res += m - i + 1; // 统计逆序对
}
}
return res;
}
}
剑指 Offer 52. 两个链表的第一个公共节点


/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode idxA = headA;
ListNode idxB = headB;
while(idxA != idxB){
if(idxA == null){
idxA =headB;
}else{
idxA = idxA.next;
}
if(idxB == null){
idxB = headA;
}else{
idxB = idxB.next;
}
}
return idxA;
}
}
剑指 Offer 53 - I. 在排序数组中查找数字 I

class Solution {
public int search(int[] nums, int target) {
if(nums == null || nums.length == 0){
return 0;
}
int start = binarySearch(nums, target);
int end = binarySearch(nums, target + 1);
return end - start + (nums[end] == target ? 1 : 0);
}
private int binarySearch(int[] nums, int tar){
int l = 0, r = nums.length - 1;
while(l < r){
int mid = l + (r - l)/2;
if(nums[mid] < tar){
l = mid + 1;
}else{
r = mid;
}
}
return l;
}
}
剑指 Offer 53 - II. 0~n-1中缺失的数字


class Solution {
public int missingNumber(int[] nums) {
if(nums == null || nums.length == 0){
return 0;
}
int l = 0;
int r = nums.length - 1;
while(l < r){
int mid = l + (r - l) / 2;
if(nums[mid] != mid){
r = mid;
}else{
l = mid + 1;
}
}
if(nums[r] == r){
r++;
}
return r;
}
}
剑指 Offer 54. 二叉搜索树的第k大节点


/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int k1, res;
public int kthLargest(TreeNode root, int k) {
k1 = k;
dfs(root);
return res;
}
private void dfs(TreeNode root){
if(root == null || k1 == 0){
return;
}
dfs(root.right); //右子树
if(--k1 == 0) res = root.val; //根节点
dfs(root.left); //左子树
}
}
剑指 Offer 55 - I. 二叉树的深度

/**
* 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;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return left > right ? left + 1 : right + 1;
}
}
剑指 Offer 55 - II. 平衡二叉树

/**
* 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;
}
int left = treeDepth(root.left);
int right = treeDepth(root.right);
return Math.abs(left - right) > 1 ? false : true && isBalanced(root.left) &&
isBalanced(root.right);
}
//树的深度
public int treeDepth(TreeNode root){
if(root == null){
return 0;
}
int a = treeDepth(root.left);
int b = treeDepth(root.right);
return a > b ? a + 1:b + 1;
}
}
剑指 Offer 56 - I. 数组中数字出现的次数

class Solution {
public int[] singleNumbers(int[] nums) {
//1.数组中只出现一次的两个数字的异或结果
int sum = 0;
for(int x : nums){
sum ^= x;
}
//2.找到异或二进制中1所在的位置
int index = 0;
while((sum >> index & 1) == 0){
index++;
}
int first = 0;
for(int x : nums){
if((x >> index & 1) == 0){
first ^= x;
}
}
int second = sum ^ first;
return new int[]{first, second};
}
}
剑指 Offer 56 - II. 数组中数字出现的次数 II


class Solution {
public int singleNumber(int[] nums) {
int[] count = new int[32];
for(int num : nums){
for(int i = 0; i < 32; i++){
count[i] += num & 1;
num >>= 1;
}
}
int res = 0, mod = 3;
for(int i = 0; i< 32; i++){
res <<= 1;
res += count[31 - i] % mod;
}
return res;
}
}
剑指 Offer 57. 和为s的两个数字


class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0;
int 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 null;
}
}
class Solution{
public int[] twoSum(int[] nums, int target){
Set<Integer> s = new HashSet<>();
for(int i = 0; i < nums.length; i++){
s.add(nums[i]);
}
for(int i = 0; i < nums.length; i++){
if(s.contains(target - nums[i])){
return new int[]{nums[i], target - nums[i]};
}
}
return null;
}
}
剑指 Offer 57 - II. 和为s的连续正数序列

class Solution {
public int[][] findContinuousSequence(int target) {
int i = 1;
int j = 1;
int sum = 0;
List<int[]> res = new ArrayList<>();
while(i <= target / 2){
if(sum < target){
sum += j; //右边界向右移动
j++;
}else if(sum > target){
sum -= i; //左边界向右移动
i++;
}else{
int[] arr = new int[j - i];
for(int k = i; k < j; k++){
arr[k -i] = k;
}
res.add(arr);
sum -= i; //左边界向右移动
i++;
}
}
return res.toArray(new int[res.size()][]);
}
}
剑指 Offer 58 - I. 翻转单词顺序

class Solution {
public String reverseWords(String s) {
s = s.trim(); //去除收尾空格
int j = s.length() - 1, i = j;
StringBuilder res = new StringBuilder();
while(i >= 0){
while(i >= 0 && s.charAt(i) != ' ') i--; //找到空格
res.append(s.substring(i + 1, j + 1) + " "); //添加单词
while(i >= 0 && s.charAt(i) == ' ') i--; //跳过空格
j = i;
}
return res.toString().trim();
}
}
剑指 Offer 58 - II. 左旋转字符串

class Solution {
public String reverseLeftWords(String s, int n) {
String res = "";
for(int i = n; i < s.length(); i++)
res += s.charAt(i);
for(int i = 0; i < n; i++)
res += s.charAt(i);
return res;
}
}
剑指 Offer 59 - I. 滑动窗口的最大值


class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0 || k == 0){
return new int[0];
}
int[] res =new int[nums.length - k + 1];
Deque<Integer> q = new LinkedList<>();
int j = 0;
for(int i = 0; i < nums.length; i++){
if(q.size() > 0 && i - q.peekFirst() >= k){ //判断队头是否需要出队
q.pollFirst();
}
while(q.size() > 0 && nums[q.peekLast()] < nums[i]){
q.pollLast();
}
q.add(i);
if(i >= k - 1){
res[j++] = (nums[q.peekFirst()]); //取队头作为窗口最大元素
}
}
return res;
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//边界条件判断
if (nums == null || nums.length == 0)
return new int[0];
int res[] = new int[nums.length - k + 1];
for (int i = 0; i < res.length; i++) {
int max = nums[i];
//在每个窗口内找到最大值
for (int j = 1; j < k; j++) {
max = Math.max(max, nums[i + j]);
}
res[i] = max;
}
return res;
}
}
剑指 Offer 59 - II. 队列的最大值




class MaxQueue {
Queue<Integer> que;
Deque<Integer> deq; //记录最大值
public MaxQueue() {
que = new LinkedList<>();
deq = new LinkedList<>();
}
public int max_value() {
//取双端队列的队首作为最大值
return deq.size() > 0 ? deq.peek() : -1;
}
public void push_back(int value) {
que.add(value);
while(deq.size() > 0 && deq.peekLast() < value){
deq.pollLast(); //保证双端队列存的就是最大的值,将队尾小于value的元素全部删除
}
deq.add(value);
}
public int pop_front() {
int v = que.size() > 0 ? que.poll() : -1;
if(deq.size() > 0 && deq.peekFirst() == v){
deq.pollFirst();
}
return v;
}
}
/**
* 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();
*/
剑指 Offer 60. n个骰子的点数

class Solution {
public double[] dicesProbability(int n) {
double all = Math.pow(6, n); //方案总数
int[][] dp = new int[n + 1][6*n + 1]; //状态数组
dp[0][0] = 1;
//dp[i][j]有i个骰子,点数和为j的方案总数
for(int i = 1; i <= n; i++){ //n个骰子
for(int j = 1; j <= 6 * i; j++){
for(int k = 1; k <= Math.min(j, 6); k++){
dp[i][j] += dp[i - 1][j - k]; //前i次总和为j的方案总数
}
}
}
double[] res = new double[1 + 5 * n];
for(int i = n; i <= n * 6; i++){
res[i - n] = dp[n][i] / all; //转换成概率
}
return res;
}
}
剑指 Offer 61. 扑克牌中的顺子

class Solution {
public boolean isStraight(int[] nums) {
if(nums.length != 5){
return false;
}
Arrays.sort(nums); // 0 0 xxxxx
int k = 0; //去除0 nums[k] != 0
while(nums[k] == 0){
k++;
}
for(int i = k + 1; i < nums.length; i++){ //查看有无重复数字
if(nums[i] == nums [i - 1]){
return false;
}
}
return nums[4] - nums[k] <= 4; //最小 <= 4;
}
}
剑指 Offer 62. 圆圈中最后剩下的数字


class Solution {
public int lastRemaining(int n, int m) {
if(n == 1){
return 0;
}
return (lastRemaining(n - 1, m) + m) % n;
}
}
剑指 Offer 63. 股票的最大利润

class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0){
return 0;
}
int maxv = 0; //最大利润
int minv = prices[0]; //最小价格,默认第一个最小
for(int i = 1; i < prices.length; i++){
maxv = Math.max(prices[i] - minv, maxv);
minv = Math.min(minv, prices[i]);
}
return maxv;
}
}
剑指 Offer 64. 求1+2+…+n

class Solution {
public int sumNums(int n) {
return n == 0 ? 0 : n + sumNums(n - 1);
}
}
剑指 Offer 65. 不用加减乘除做加法

class Solution {
public int add(int a, int b) {
while( b != 0){
int c = (a & b) << 1; //c进位
a ^= b; //a非进位部分的和
b = c;
}
return a;
}
}
剑指 Offer 66. 构建乘积数组

class Solution {
public int[] constructArr(int[] a) {
//避开在i时避开 x ai
int n = a.length;
int[] res = new int[n];
for(int i = 0, p = 1; i < n; i++){
res[i] = p; //a1 ***** ai - 1
p *= a[i];
}
for(int i = n - 1, p = 1; i >= 0; i--){
res[i] *= p; //ai + 1 ***** an -1
p *= a[i];
}
return res;
}
}
剑指 Offer 67. 把字符串转换成整数

class Solution {
public int strToInt(String str) {
char[] c = str.trim().toCharArray();
if(c.length == 0){
return 0;
}
int res = 0, sign = 1; //res返回结果 sign 1正数 -1负数
int temp = Integer.MAX_VALUE / 10;
int index = 1;
if(c[0] == '-'){
sign = -1;
}else if(c[0] != '+'){
index = 0;
}
for(int i = index; i < c.length; i++){
if(c[i] < '0' || c[i] > '9') break;
if(res > temp || (res == temp && c[i] > '7')){
return sign == 1 ? Integer.MAX_VALUE: Integer.MIN_VALUE;
}
res = res * 10 + c[i] - '0';
}
return sign * (int)res;
}
}
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先


/**
* 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(p.val > q.val){
TreeNode temp = p;
p = q;
q = temp;
}
while(root != null){
if(root.val < p.val){
root = root.right;
}else if(root.val > q.val){
root = root.left;
}else{
break;
}
}
return root;
}
}
class Solution{
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q){
if(root.val < p.val && root.val < q.val){
return lowestCommonAncestor(root.right, p, q);
}
if(root.val > p.val && root.val > q.val){
return lowestCommonAncestor(root.left, p, q);
}
return root;
}
}
剑指 Offer 68 - II. 二叉树的最近公共祖先

/**
* 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;
}
}

