上岸算法 I LeetCode Weekly Contest 231解题报告 算法 刷题解法

卖大米 2021-3-7 569


上岸算法

任何只教知识的课程都是耍流氓

我们直击上岸

关注我们,第一时间获得大厂面试真题讲解

No.1

检查二进制字符串字段

解题思路

符合要求的字符串即前缀全是 1,后缀全是 0 的字符串。

代码展示


class Solution { 
   public boolean checkOnesSegment(String s) { 
       if (!s.contains("0")) { 
           return true; 
       } 
       if (s.substring(s.indexOf("0")).contains("1")) { 
           return false; 
       } 
       return true; 
   } 
}

No.2构成特定和需要添加的最少元素

解题思路

贪心即可,每次都添加绝对值尽可能大的。注意总和可能溢出 int,所以中间运算要使用 long

代码展示


class Solution { 
   public int minElements(int[] nums, int limit, int goal) { 
       long sum = 0; 
       for (int num : nums) { 
           sum += num; 
       } 
       sum = Math.abs(goal - sum); 
       int count = (int) (sum / limit); 
       if (sum % limit != 0) { 
           count++; 
       } 
       return count; 
   } 
}

No.3从第一个节点出发到最后一个节点的受限路径数

解题思路

Dijkstra + DP

代码展示


class Solution { 
   static class Edge { 
       int next; 
       int len; 

       Edge(int next, int len) { 
           this.next = next; 
           this.len = len; 
       } 
   } 

   public int countRestrictedPaths(int n, int[][] edges) { 
       // 建图 
       Map<Integer, List<Edge>> graph = new HashMap<>(); 
       for (int[] edge : edges) { 
           for (int i = 0; i < 2; i++) { 
               if (!graph.containsKey(edge[i])) { 
                   graph.put(edge[i], new ArrayList<>()); 
               } 
               graph.get(edge[i]).add(new Edge(edge[1 - i], edge[2])); 
           } 
       } 
               // dijkstra 求出 distanceToLastNode 
       var distanceToLastNode = dijkstra(n, graph); 
       // DP 
       int[] mem = new int[n + 1]; 
       Arrays.fill(mem, -1); 
       mem[n] = 1; 
       return dp(1, mem, distanceToLastNode, graph); 
   } 

   private int dp(int cur, int[] mem, Map<Integer, Integer> distanceToLastNode, Map<Integer, List<Edge>> graph) { 
       if (mem[cur] >= 0) { 
           return mem[cur]; 
       } 
       mem[cur] = 0; 
       for (var next : graph.get(cur)) { 
           if (distanceToLastNode.get(cur) > distanceToLastNode.get(next.next)) { 
               mem[cur] = (mem[cur] + dp(next.next, mem, distanceToLastNode, graph)) % 1000000007; 
           } 
       } 
       return mem[cur]; 
   } 

   static class Node { 
       int to; 
       int len; 

       Node(int to, int len) { 
           this.to = to; 
           this.len = len; 
       } 
   } 

   private Map<Integer, Integer> dijkstra(int start, Map<Integer, List<Edge>> graph) { 
       Set<Integer> visited = new HashSet<>(); 
       Map<Integer, Integer> res = new HashMap<>(); 
       PriorityQueue<Node> heap = new PriorityQueue<>((o1, o2) -> (o1.len - o2.len)); 
       res.put(start, 0); 
       heap.add(new Node(start, 0)); 
       while (!heap.isEmpty()) { 
           Node node = heap.poll(); 
           if (visited.contains(node.to)) { 
               continue; 
           } 
           visited.add(node.to); 
           for (Edge e : graph.get(node.to)) { 
               if (res.getOrDefault(e.next, Integer.MAX_VALUE) > node.len + e.len) { 
                   res.put(e.next, node.len + e.len); 
                   heap.add(new Node(e.next, node.len + e.len)); 
               } 
           } 
       } 
       return res; 
   } 
} 

No.4 使所有区间的异或结果为零

解题思路

DP

代码展示


class Solution { 
   public int minChanges(int[] nums, int k) { 
       // count[i][j] 表示在每个长度为 k 的子区间的第 i 个位置上,数字 j 出现了多少次 
       int[][] count = new int[k][1 << 10]; 
       for (int i = 0; i < nums.length; i++) { 
           count[i % k][nums[i]]++; 
       } 

       // dp[i] 表示将每个子区间的前 i 个位置变成一致的至少要改变多少个数字 
       int[][] dp = new int[k + 1][1 << 10]; 
       for (int i = 0; i <= k; i++) { 
           Arrays.fill(dp[i], nums.length); 
       } 
       dp[0][0] = 0; 

       int min = nums.length, sum = 0; 
       for (int i = 1; i <= k; i++) { 
           int[] cur = count[i - 1]; 
           int tot = 0, max = 0; 
           for (int j : cur) { 
               tot += j; 
               max = Math.max(max, j); 
           } 
           sum += tot - max; 
           min = Math.min(min, max); 
           for (int j = 0; j < (1 << 10); j++) 
               if (cur[j] > 0) { 
                   int now = tot - cur[j]; 
                   for (int K = 0; K < (1 << 10); K++) 
                       dp[i][j ^ K] = Math.min(dp[i][j ^ K], dp[i - 1][K] + now); 
               } 
       } 
       return Math.min(dp[k][0], min + sum); 
   } 
}

上岸3月公益带刷活动

最新回复 (0)
返回