• 算法-题目汇总-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

  • 相关阅读:
    指针与数组实例练习(指针运算)
    C语言数组和函数实例练习(二)
    C语言数组和函数实例练习(一)
    近一个月的学习总结(4.8—5.12)
    Java网页小程序——Java Applet
    数据结构(二)线性表——链表
    JDBC的使用(MySQL数据库)
    Python变量类型及变量
    Shell编程语法
    文本处理三剑客
  • 原文地址:https://www.cnblogs.com/isnotnull/p/15094213.html
Copyright © 2020-2023  润新知