算法-题目汇总-1

1. 给一个数组标识不同距离的点 给一个长度为5的绳子看最多能覆盖多少个点

思路1: 使用二分查找到大于等于当前点-5的最左的点 坐标相减得到结果 logn

思路2: 时间窗口的模式,l在第一个点 r右移 满足条件长度加一 l走完数组结束 左右两个边界都不需要回退 o(n)

 1 public int cover(int[] arr, int length) {
 2         int l = 0;
 3         int r = 1;
 4         int max = Integer.MIN_VALUE;
 5         while (l <= arr.length - 1 && r <= arr.length - 1) {
 6             if (arr[r] - arr[l] <= length) {
 7                 r++;
 8                 max = Math.max(max, r - l);
 9             } else {
10                 l++;
11             }
12         }
13         return max;
14     }

2. 装6个或8个的袋子,如何使用最少的袋子装指定数量的苹果  袋子必须装满

思路1: 奇数肯定不行,先确定8个的袋子最多能用多少 剩下的用6去装 不够8个袋子的减一 当剩余的苹果超过24的时候就可以停止

打表法: 对于输入一个整数 返回一个整数的题,先普通做法做出来 ,再根据输入输出规律 进行优化 40%可以有规律

3. 两只牛吃草,一次只能吃4的幂次方数的草 先手/后手哪个能赢

 1  public String process(int n) {
 2         if (n < 5) {
 3             return (n == 0 || n == 2) ? "后手" : "先手";
 4         }
 5         int eat = 1;
 6         while (eat <= n) {
 7             if (process(n - eat).equals("后手")) {
          // 子问题的后手是母问题的先手
8 return "先手"; 9 } 10 if (eat > n / 4) { 11 break; 12 } 13 eat *= 4; 14 } 15 return "后手"; 16 } 17 18 public String winner(int n) { 19 if (n % 5 == 0 || n % 5 == 2) { 20 return "后手"; 21 }else { 22 return "先手"; 23 } 24 }

4. RRGGR 变成 RRRGG

使用预处理辅助数组,

统计从0-n-1 有几个R

{1,2,2,2,3}

统计0-n-1有几个G

{2,2,2,1,0}

 1 public int minPaint(String s) {
 2         char[] chars = s.toCharArray();
 3         int n = chars.length;
 4         // 使用辅助数组统计从0到n-1有多少R
 5         // 使用辅助数组统计从0到n-1有多少G
 6         for (int i = 0; i < n; i++) {
 7             if (i == 0) {
 8                 // 统计0~n-1有多少个R 需要染成G
 9             } else if (i == n) {
10                 // 统计0~n-1有多少个G 需要染成R
11             }else {
12                 // 统计0~i有多少个R 需要染成G i+1~n-1有多少个G 需要染成R
13             }
14         }
15         return Math.min(1,2);
16     }

 

 5. 给定一个N*N的矩阵 只有0和1两种值,返回边框全是1的最大正方形边长长度

001110

001010

101110

答案3

n*n的矩阵

子长方形规模n^4个 子正方形规模n^3个

从00遍历各个子正方形,使用辅助矩阵判断遍历到的正方形边是否是1

辅助矩阵记录这在当前点往右有多少个连续的1

在当前点往下有多少个连续的1

 

 1  public int maxAllOneBorder(int[][] m) {
 2         int c = m.length;
 3         int r = m[0].length;
 4         //
 5         for (int row = 0; row < c; row++) {
 6             //
 7             for (int col = 0; col < r; col++) {
 8                 // 边长
 9                 for (int border = 0; border <= Math.min(c - row, r - col); border++) {
10                     // 判断在某行某列某边长上是否全是1
11                     // 使用辅助矩阵记录从左往右有多少连续的1
12                     // 使用辅助矩阵记录从上往下有多少连续的1
13                 }
14             }
15         }
16     }

 

6. 给定一个函数 可以等概率返回一个1~5的数字 加工出一个等概率返回1~7的函数

 可以等概率返回a~b的一个数,加工出可以返回c~d的函数

 p概率返回0 以1-p概率返回1 加工出一个等概率返回0和1的函数 执行两次,当出现10的时候返回0 出现01的时候返回1 因为10的概率是 p* 1-p 10的概率是1-p * p两个概率相等

 1  // 等概率返回1-5
 2     public int f() {
 3         return (int) (Math.random() * 5 + 1);
 4     }
 5     // 二进制发生器
 6     public int binaryTool() {
 7         int res = 0;
 8         do {
 9             res = f();
10         } while (res == 3);
11         return res < 3 ? 0 : 1;
12     }
13     // 等概率返回1-7
14     public int getNum() {
15         int res = 0;
16         do {
17             res = (binaryTool() << 2) + (binaryTool() << 1) + binaryTool();
18         } while (res == 7);
19         return res + 1;
20     }

 

7. 给定一个非负整数n 代表二叉树的节点数 返回能形成多少种不同结构的二叉树

 1 public int process(int n) {
 2         if (n == 0) {
 3             return 1;
 4         }
 5         if (n < 0) {
 6             return 0;
 7         }
 8         if (n == 1) {
 9             return 1;
10         }
11         if (n == 2) {
12             return 2;
13         }
14         int res = 0;
15         for (int i = 0; i <= n - 1; i++) {
          // 左树是0个节点
16 int leftNum = process(i);
         // 右树是剩余的节点 -1是要减去一个头结点
17 int rightNum = process(n - i - 1); 18 res += leftNum * rightNum; 19 } 20 return res; 21 }

8. 一个括号字符串,需要在任意位置添加括号,将其转化为一个完整的括号字符串,需要添加多少个括号

 

 1 public int addparentheses(String str) {
 2         char[] chars = str.toCharArray();
 3         int count = 0;
 4         int res = 0;
 5         for (int i = 0; i < chars.length; i++) {
 6             if (chars[i] == ')') {
 7                 if (count == 0) {
 8                     // count等于0的时候直接res++的原因是
 9                     // 这一步应该count-- 然后res++ , count-- 按照逻辑应该res++ count+1
10                     // 最后结果还是count=0 res+1
11                     res++;
12                 } else {
13                     count--;
14                 }
15             } else {
16                 count++;
17             }
18         }
19         // count代表应该添加的右括号数
20         // res代表应该添加的左括号数
21         return count + res;
22     }

9. 从一个集合中取出一个元素放到另一个集合中,要求移动之后两个集合的平均值要提高 不能把一个集合取空 不能放入集合中已有的值 求最大多能移动几次

 两个集合评价值一样返回0 只能平均值大的集合移动到平均值小的集合,先移动小的

  

 1 public int ways(int[] arr) {
 2         if (arr == null || arr.length == 0) {
 3             return -1;
 4         }
 5         int sum = 0;
 6         for (int i = 0; i < arr.length; i++) {
 7             sum += arr[i];
 8         }
 9         if (sum % arr.length != 0) {
10             return -1;
11         }
12         int avg = sum / arr.length;
13         int leftSum = 0;
14         int max = 0;
15         for (int j = 0; j < arr.length; j++) {
16             //       左边已有数量  左边的桶数 * 平均值
17             int left = leftSum - (j * avg);
18             //                左边已有  当前这个   右边的桶数*平均值
19             int right = sum - leftSum - arr[j] - ((arr.length - 1 - j) * avg);
20             if (left < 0 && right < 0) {
21                 // 两边都是负数 说明都不够平均值 取和
22                 max = Math.max(max, Math.abs(left) + Math.abs(right));
23             } else {
24                 // 一个为负数 一个为正数 或者两个都是正数
25                 max = Math.max(max, Math.max(Math.abs(left), Math.abs(right)));
26             }
27             leftSum+=arr[j];
28         }
29         return max;
30     }

 

10. 求括号字符串最大深度((()))深度是3 左括号count++ 右括号count-- count的最大值就是最大深度

11. 求括号字符串最长子串 dp问题,求对应字符前面的合法子串,''('' 字符直接为0 '')'' 字符求前面符合条件的子串

  

 1 public int maxLength(String str) {
 2         char[] chars = str.toCharArray();
 3         int[] dp = new int[chars.length];
 4         int res = 0;
 5         for (int i = 1; i < chars.length; i++) {
 6             if (chars[i] == ')') {
 7                 // 左括号直接是0 不用统计
 8                 // pre位置是符合条件的前一个位置
 9                 int pre = i - dp[i - 1] - 1;
10                 if (pre >= 0 && chars[pre] == '(') {
11                     // (())(()) 适配这种情况
12                     dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);
13                 }
14             }
15             res = Math.max(res, dp[i]);
16         }
17         return res;
18     }

12. 返回二叉树每条路径的最大权重

 使用二叉树套路解

  

 1 public int process2(TreeNode node) {
 2         if (node.left == null && node.right == null) {
 3             return node.value;
 4         }
 5         int next = Integer.MIN_VALUE;
 6         int next2 = Integer.MIN_VALUE;
 7         if (node.left != null) {
 8             next = process2(node.left);
 9         }
10         if (node.right != null) {
11             next2 = process2(node.right);
12         }
13         int max = Math.max(next, next2);
14         return node.value + max;
15     }

13. 二维数组 从左到右 从上到下都有序 找某个数

   左边都是0 右边都是1 找1最多的数组

 1   /**
 2      * 1 3 5 10 
 3      * 2 6 11 13
 4      * 7 9 12 17
 5      * --------
 6      * 00011
 7      * 01111
 8      * 01111
 9      * 00111
10      */

目标7 从最右开始10大于7左移 小于7下移 大于7左移 小于7下移 大于7左移 

从右边开始 左边是1左移 左边是0记录最大值添加list然后下移一次类推 

 

14. 洗衣机问题 n个洗衣机中有衣服 把衣服平均分到各个洗衣机中 每次只能移动一件衣服

  

 1  public int ways(int[] arr) {
 2         if (arr == null || arr.length == 0) {
 3             return -1;
 4         }
 5         int sum = 0;
 6         for (int i = 0; i < arr.length; i++) {
 7             sum += arr[i];
 8         }
 9         if (sum % arr.length != 0) {
10             return -1;
11         }
12         int avg = sum / arr.length;
13         int leftSum = 0;
14         int max = 0;
15         for (int j = 0; j < arr.length; j++) {
16             //       左边已有数量  左边的桶数 * 平均值
17             int left = leftSum - (j * avg);
18             //                左边已有  当前这个   右边的桶数*平均值
19             int right = sum - leftSum - arr[j] - ((arr.length - 1 - j) * avg);
20             if (left < 0 && right < 0) {
21                 // 两边都是负数 说明都不够平均值 取和
22                 max = Math.max(max, Math.abs(left) + Math.abs(right));
23             } else {
24                 // 一个为负数 一个为正数 或者两个都是正数
25                 max = Math.max(max, Math.max(Math.abs(left), Math.abs(right)));
26             }
27             leftSum+=arr[j];
28         }
29         return max;
30     }

 15. 顺时针打印矩阵

0   1   2   3

9  10  11 4

8   7   6   5

思路: 先定义两个点0和5 打印  再往里缩 打印

 1 public void print(int[][] matrix) {
 2         int a = 0, b = 0;
 3         int c = matrix.length - 1, d = matrix[0].length - 1;
 4         while (a <= c && b <= d) {
 5             f(matrix, a++, b++, c--, d--);
 6         }
 7     }
 8 
 9     public void f(int[][] matrix, int a, int b, int c, int d) {
10         if (a == c) {
11             for (int i = b; i <= d; i++) {
12                 System.out.print(matrix[a][i] + " ");
13             }
14         } else if (b == d) {
15             for (int i = a; i <= c; i++) {
16                 System.out.print(matrix[i][b] + " ");
17             }
18         } else {
19             int la = a;
20             int lb = b;
21             int rc = c;
22             int rd = d;
23             while (lb != d) {
24                 System.out.print(matrix[a][lb++] + " ");
25             }
26             while (la != c) {
27                 System.out.print(matrix[la++][d] + " ");
28             }
29             while (rd != b) {
30                 System.out.print(matrix[c][rd--] + " ");
31             }
32             while (rc != a) {
33                 System.out.print(matrix[rc--][a] + " ");
34             }
35         }
36     }

16. 矩阵顺时针移动数字

0  1  2  

7  8  3

6  5  4

-----

6  7  0

5  8  1

4  3  2

思路: 先四个角数子调整 0 2 4 6 再1 3 5 7 调整

 1 public void circleRotate(int[][] matrix) {
 2         int a = 0, b = 0;
 3         int c = matrix.length - 1, d = matrix[0].length - 1;
 4         while (a <= c && b <= d) {
 5             rotate(matrix, a++, b++, c--, d--);
 6         }
 7     }
 8 
 9     public void rotate(int[][] maxtrix, int a, int b, int c, int d) {
10         int times = d - b;
11         for (int i = 0; i < times; i++) {
12             int temp = maxtrix[a][b + i];
13             maxtrix[a][b + i] = maxtrix[c - i][b];
14             maxtrix[c - i][b] = maxtrix[c][d - i];
15             maxtrix[c][d - i] = maxtrix[a + i][d];
16             maxtrix[a + i][d] = temp;
17         }
18     }

17. zigzag规则打印矩阵

思路: 刚开始两个点都在左上角,然后a右移 到头的话 往下移 b往下移 到头的话 往右移 当a点移出矩阵的时候结束

 1  public void print(int[][] matrix) {
 2         int a1 = 0, b1 = 0, c1 = 0, d1 = 0;
 3         int endR = matrix.length - 1;
 4         int endC = matrix[0].length - 1;
 5         boolean flag = false;
       // 移出矩阵时结束
6 while (a1 != endR + 1) { 7 print(matrix, a1, b1, c1, d1, flag); 8 a1 = b1 == endC ? a1 + 1 : a1; 9 b1 = b1 == endC ? b1 : b1 + 1; 10 d1 = c1 == endR ? d1 + 1 : d1; 11 c1 = c1 == endR ? c1 : c1 + 1; 12 flag = !flag; 13 } 14 } 15 16 17 public void print(int[][] matrix, int a, int b, int c, int d, boolean flag) { 18 if (flag) { 19 while (a != c + 1) { 20 System.out.print(matrix[a++][b--] + " "); 21 } 22 } else { 23 while (c != a - 1) { 24 System.out.print(matrix[c--][d++] + " "); 25 } 26 } 27 28 }

 18. 字符串数组 返回前k个出现次数最多的字符

  使用hash统计出现次数,小根堆求前k个

19. 实现一个结构,可以添加add字符串 打印前k个最长的字符串 打印某个字符串个数

  建立词频表

  堆

  记录字符串在堆中的位置index

posted @ 2021-08-04 13:21  rudynan  阅读(100)  评论(0编辑  收藏  举报