上岸算法 发表于 2022-4-17 17:19:24

上岸算法LeetCode Weekly Contest 289解题报告

【 NO.1 计算字符串的数字和】

解题思路
签到题,循环处理即可。

代码展示

class Solution {
   public String digitSum(String s, int k) {
       while (s.length() > k) {
         StringBuilder builder = new StringBuilder();
         for (int i = 0; i < s.length(); i += k) {
               int sum = 0;
               for (int j = i; j < i + k && j < s.length(); j++) {
                   sum += s.charAt(j) - '0';
            }
               builder.append(sum);
          }
         s = builder.toString();
      }
       return s;
}
}


【 NO.2 完成所有任务需要的最少轮数】

解题思路
使用 Map 维护每种任务的数量,然后使用 dp 求解。

dp 表示完成 i 个任务完成所需的最少轮数,于是有 dp = min(dp, dp) + 1。

代码展示

class Solution {
   public int minimumRounds(int[] tasks) {
       Map<Integer, Integer> count = new HashMap<>();
       for (int task : tasks) {
         count.put(task, count.getOrDefault(task, 0) + 1);
      }
       int res = 0;
       int[] mem = new int;
       mem = mem = 1;
       mem = mem = 2;
       for (var entry : count.entrySet()) {
         int cnt = entry.getValue();
         if (cnt == 1) {
               return -1;
          }
         res += dp(cnt, mem);
      }
       return res;
}

   private int dp(int cnt, int[] mem) {
       if (mem > 0) {
         return mem;
      }
       mem = Math.min(dp(cnt - 3, mem) + 1, dp(cnt - 2, mem) + 1);
       return mem;
}
}


【 NO.3 转角路径的乘积中最多能有几个尾随零】

解题思路
尾随 0 的个数其实就是 MIN(因数 2 的个数, 因数 5 的个数)

代码虽然很长,但大部分是重复的逻辑,详见注释。

代码展示

class Solution {
   public int maxTrailingZeros(int[][] grid) {
       // up2 表示 grid 开始连续往上走最多能累计到因数 2 的个数
       // up5 表示 grid 开始连续往上走最多能累计到因数 5 的个数
       int[][] up2 = new int.length];
       int[][] up5 = new int.length];
       for (int i = 0; i < grid.length; i++) {
         for (int j = 0; j < grid.length; j++) {
               up2 = num(grid, 2);
               up5 = num(grid, 5);
               if (i > 0) {
                   up2 += up2;
                   up5 += up5;
            }
          }
      }
       // left2 表示 grid 开始连续往左走最多能累计到因数 2 的个数
       // left5 表示 grid 开始连续往左走最多能累计到因数 5 的个数
       int[][] left2 = new int.length];
       int[][] left5 = new int.length];
       for (int i = 0; i < grid.length; i++) {
         for (int j = 0; j < grid.length; j++) {
               left2 = num(grid, 2);
               left5 = num(grid, 5);
               if (j > 0) {
                   left2 += left2;
                   left5 += left5;
            }
          }
      }
       // down2 表示 grid 开始连续往下走最多能累计到因数 2 的个数
       // down5 表示 grid 开始连续往下走最多能累计到因数 5 的个数
       int[][] down2 = new int.length];
       int[][] down5 = new int.length];
       for (int i = grid.length - 1; i >= 0; i--) {
         for (int j = grid.length - 1; j >= 0; j--) {
               down2 = num(grid, 2);
               down5 = num(grid, 5);
               if (i < grid.length - 1) {
                   down2 += down2;
                   down5 += down5;
            }
          }
      }
       // right2 表示 grid 开始连续往右走最多能累计到因数 2 的个数
       // right5 表示 grid 开始连续往右走最多能累计到因数 5 的个数
       int[][] right2 = new int.length];
       int[][] right5 = new int.length];
       for (int i = grid.length - 1; i >= 0; i--) {
         for (int j = grid.length - 1; j >= 0; j--) {
               right2 = num(grid, 2);
               right5 = num(grid, 5);
               if (j < grid.length - 1) {
                   right2 += right2;
                   right5 += right5;
            }
          }
      }

       int res = 0;
       for (int i = 0; i < grid.length; i++) {
         for (int j = 0; j < grid.length; j++) {
               // 有四种转角形态
               // 1. up + left
               if (i > 0) {
                   res = Math.max(res, Math.min(up2 + left2, up5 + left5));
            }
               // 2. up + right
               if (i > 0) {
                   res = Math.max(res, Math.min(up2 + right2, up5 + right5));
            }
               // 3. down + left
               if (i < grid.length - 1) {
                   res = Math.max(res, Math.min(down2 + left2, down5 + left5));
            }
               // 4. down + right
               if (i < grid.length - 1) {
                   res = Math.max(res, Math.min(down2 + right2, down5 + right5));
            }
               // 不转角
               // 5. up/down/left/right
               res = Math.max(res, Math.min(up2, up5));
               res = Math.max(res, Math.min(down2, down5));
               res = Math.max(res, Math.min(left2, left5));
               res = Math.max(res, Math.min(right2, right5));
          }
      }
       return res;
}

   private int num(int x, int y) {
       int res = 0;
       while (x % y == 0) {
         res++;
         x /= y;
      }
       return res;
}
}

【 NO.4 相邻字符不同的最长路径】

解题思路
求出每个节点向下走能得到的最长路径,在每个节点的所有子节点中,挑出最长的和次长的连接,可以得到经过当前节点的最长路径。

代码展示

class Solution {
   int res;

   public int longestPath(int[] parent, String s) {
       Map<Integer, List<Integer>> children = new HashMap<>();
       for (int i = 0; i < parent.length; i++) {
         if (parent != -1) {
               if (!children.containsKey(parent)) {
                   children.put(parent, new ArrayList<>());
            }
               children.get(parent).add(i);
          }
      }

       int[] maxLength = new int;
       res = 1;
       dfs(0, children, maxLength, s);
       return res;
}

   private void dfs(int cur, Map<Integer, List<Integer>> children, int[] maxLength, String s) {
       maxLength = 1;
       if (!children.containsKey(cur)) {
         return;
      }
       var curChildren = children.get(cur);
       int first = 0, second = 0;
       for (int child : curChildren) {
         dfs(child, children, maxLength, s);
         if (s.charAt(child) != s.charAt(cur)) {
               maxLength = Math.max(maxLength, maxLength + 1);
               if (maxLength >= first) {
                   second = first;
                   first = maxLength;
            } else if (maxLength > second) {
                   second = maxLength;
            }
          }
      }
       res = Math.max(res, maxLength);
       res = Math.max(res, first + second + 1);
}
}
页: [1]
查看完整版本: 上岸算法LeetCode Weekly Contest 289解题报告