算法-题目汇总-6

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     }

 

posted @ 2021-08-12 17:39  rudynan  阅读(38)  评论(0编辑  收藏  举报