1. 某个数是否存在于二维数组中
1 public boolean search(int[][] m, int target) { 2 if (m.length == 0 || m[0].length == 0) { 3 return false; 4 } 5 int l = 0; 6 int r = m.length * m[0].length - 1; 7 int col = m[0].length; 8 while (l <= r) { 9 int mid = l + ((r - l) >> 1); 10 // mid/col 求出在哪行 11 // mid%col 求出在哪列 12 int val = m[mid / col][mid % col]; 13 if (val == target) { 14 return true; 15 } else if (val < target) { 16 l = mid + 1; 17 } else { 18 r = mid - 1; 19 } 20 } 21 return false; 22 }
2. 前序中序转树
1 public TreeNode getTree(int[] pre, int[] mid) { 2 return process(pre, 0, pre.length - 1, mid, 0, mid.length - 1); 3 } 4 5 public TreeNode process(int[] pre, int pl, int pr, int[] mid, int ml, int mr) { 6 if (pl > pr || ml > mr) { 7 return null; 8 } 9 int value = pre[pl]; 10 int help = ml; 11 while (help < mr && mid[help] != value) { 12 help++; 13 } 14 TreeNode treeNode = new TreeNode(value); 15 treeNode.left = process(pre, pl + 1, pl + help - ml, mid, ml,help - 1); 16 treeNode.right = process(pre, pl + help - ml + 1, pr, mid, help + 1, mr); 17 return treeNode; 18 }
3. 可循环的数组找最小值
1 public int search(int[] arr) { 2 if (arr.length == 0) { 3 return -1; 4 } 5 int l = 0; 6 int r = arr.length - 1; 7 if (arr[r] > arr[0] || arr[r] == arr[0]) { 8 return arr[0]; 9 } 10 while (l <= r) { 11 int mid = l + ((r - l) >> 1); 12 // 可以举例得出结论 13 if (arr[mid] > arr[mid + 1]) { 14 return arr[mid + 1]; 15 } 16 if (arr[mid - 1] > arr[mid]) { 17 return arr[mid]; 18 } 19 // 中间值大于0位置的值 说明 20 if (arr[mid] > arr[0]) { 21 l = mid + 1; 22 } else { 23 r = mid - 1; 24 } 25 } 26 return -1; 27 }
4. 统计整数 二进制形式有多少个1 (n-1)&n 可以将最右边的1设置为0
1 public int count(int n) { 2 int count = 0; 3 if (n == 0) { 4 return count; 5 } 6 while (n != 0) { 7 count++; 8 n = (n - 1) & n; 9 } 10 return count; 11 }
5. 获取链表的倒数第k个节点
1 public ListNode getLastKNode(ListNode head, int k) { 2 if (head == null || k < 1) { 3 return null; 4 } 5 ListNode fast = head; 6 ListNode slow = head;
// 注意k-- 要大于1 才能获取到最后一个node 7 while (k-- > 1) { 8 if (fast.next == null) { 9 return null; 10 } 11 fast = fast.next; 12 } 13 while (fast.next != null) { 14 fast = fast.next; 15 slow = slow.next; 16 } 17 return slow; 18 }
6. 子树判断
1 public boolean checkSubTree(TreeNode t1, TreeNode t2) { 2 if (t1 == null) { 3 return false; 4 } 5 if (t2 == null) { 6 return true; 7 } 8 return isSame(t1, t2) || checkSubTree(t1.left, t2) || checkSubTree(t2.right, t2); 9 } 10 11 public boolean isSame(TreeNode t1, TreeNode t2) { 12 if (t1 == t2) { 13 return true; 14 } 15 if (t1 == null || t2 == null) { 16 return false; 17 } 18 19 return t1.val == t2.val && isSame(t1.left, t2.left) && isSame(t1.right, t2.right); 20 }
1 class Solution { 2 public boolean checkSubTree(TreeNode t1, TreeNode t2) { 3 4 if(t1 == null){ 5 if(t2 == null){ 6 return true; 7 }else{ 8 return false; 9 } 10 } 11 //判断当前节点是否符合,递归先序左孩子,递归先序右孩子 12 return recur(t1, t2) || checkSubTree(t1.left, t2) || checkSubTree(t1.right, t2); 13 } 14 15 //递归判断两颗树是否完全相同 16 boolean recur(TreeNode root1, TreeNode root2){ 17 18 if(root1 == null && root2 == null){ 19 return true; 20 } 21 22 if(root1 == null || root2 == null){ 23 return false; 24 } 25 26 if(root1.val != root2.val){ 27 return false; 28 } 29 30 return recur(root1.left, root2.left) && recur(root1.right, root2.right); 31 32 } 33 }
7. 给你一个数组 判断数组的序列是否是搜索二叉树的后续序列
数组的最后一个数肯定是root节点,小于root值的数是左子树,大于root值的是右子树
找到左右子树的范围再递归判断
1 public boolean judgeBst(int[] arr) { 2 return isBst(arr, 0, arr.length - 1); 3 } 4 5 public boolean isBst(int[] arr, int l, int r) { 6 if (l >= r) { 7 return true; 8 } 9 int i = l; 10 while (arr[i] < arr[r]) { 11 i++; 12 } 13 for (int j = i; j <= r; j++) { 14 if (arr[j] < arr[r]) { 15 return false; 16 } 17 } 18 return isBst(arr, l, i - 1) && 19 isBst(arr, i, l - 1); 20 }
8. 二叉树 返回指定数值的节点路径 必须是到叶子节点才能算一条路径
1 public class FindPath { 2 private ArrayList<Integer> list = new ArrayList<>(); 3 private ArrayList<ArrayList<Integer>> res = new ArrayList<>(); 4 5 public ArrayList<ArrayList<Integer>> findPath(TreeNode head, int k) { 6 process(head, k); 7 return res; 8 } 9 10 public void process(TreeNode head, int rest) { 11 if (head == null) { 12 return; 13 } 14 list.add(head.val); 15 rest -= head.val; 16 if (rest == 0 && head.left == null && head.right == null) { 17 res.add(new ArrayList<>(list)); 18 } 19 process(head.left, rest); 20 process(head.right, rest);
// 返回父节点的时候删除子节点的值 21 list.remove(list.size() - 1); 22 } 23 }
9.复杂链表复制
思路1: 先根据next复制在复制过程中 用hashmap记录随机的node值 组成next链表之后再遍历设置随机node
思路2: 遍历链表 复制node A-B-C 复制成A-A`-B-B`-C-C` 然后遍历链表A`的随机node 是Anode的随机node+1 然后再把链表分成两个链表
1 public ListNode copy(ListNode head) { 2 cloneNodes(head); 3 connectSiblingNodes(head); 4 return split(head); 5 } 6 7 public void cloneNodes(ListNode head) { 8 ListNode p = head; 9 while (p != null) { 10 ListNode newNode = new ListNode(p.val); 11 newNode.next = p.next; 12 p.next = newNode; 13 p = newNode.next; 14 } 15 } 16 17 public void connectSiblingNodes(ListNode head) { 18 ListNode p = head; 19 while (p != null) { 20 ListNode pclone = p.next; 21 ListNode rNext = p.rNext; 22 if (rNext != null) { 23 pclone.rNext = rNext.next; 24 } 25 p = pclone.next; 26 } 27 } 28 29 public ListNode split(ListNode head) { 30 ListNode node = head; 31 ListNode cloneHead = null; 32 ListNode cloneNode = null; 33 if (head != null) { 34 cloneHead = cloneNode = node.next; 35 node.next = cloneNode.next; 36 node = node.next; 37 } 38 while (node != null) { 39 cloneNode.next = node.next; 40 cloneNode = cloneNode.next; 41 42 node.next = cloneNode.next; 43 node = node.next; 44 } 45 return cloneHead; 46 }
10. 求第n个丑数/ 判断这个数是否是丑数
丑数先被2除 然后被5除 然后被3除 等于1是丑数
n%2==0 n/2
n%5 ==0 n/5
n%3 == 0 n/3
求第n个丑数,第一个丑数是1 第二个丑数是前一个丑数*234的最小值,每次计算出丑数之后 更新p2 p3 p5的值会增加效率 指针要知道刚好等于或小于最后一个丑数的位置
1 public int get(int n) { 2 if (n < 1) { 3 return -1; 4 }
// 小于7的丑数就是自己 5 if (n < 7) { 6 return n; 7 } 8 int p2 = 0, p3 = 0, p5 = 0; 9 int[] help = new int[n]; 10 help[0] = 1; 11 for (int i = 1; i < n; i++) { 12 help[i] = Math.min(Math.min(help[p2] * 2, help[p3] * 3), help[p5] * 5); 13 while (help[p2] * 2 <= help[i]) { 14 p2++; 15 if (p2 > n) { 16 break; 17 } 18 } 19 while (help[p3] * 3 <= help[i]) { 20 p3++; 21 if (p3 > n) { 22 break; 23 } 24 } 25 while (help[p5] * 5 <= help[i]) { 26 p5++; 27 if (p5 > n) { 28 break; 29 } 30 } 31 } 32 return help[n - 1]; 33 }
1 public int getKthMagicNumber(int k) { 2 int p3 = 0; 3 int p5 = 0; 4 int p7 = 0; 5 int[] ugly = new int[k + 1]; 6 ugly[0] = 1; 7 for (int i = 1; i < k; i++) { 8 ugly[i] = Math.min(3 * ugly[p3], Math.min(5 * ugly[p5],7 * ugly[p7])); 9 if (ugly[i] == 3 * ugly[p3]) { 10 p3++; 11 } 12 if (ugly[i] == 5 * ugly[p5]) { 13 p5++; 14 } 15 if (ugly[i] == 7 * ugly[p7]) { 16 p7++; 17 } 18 } 19 return ugly[k-1]; 20 }