LeetCode Weekly Contest 240解题报告 职场讨论

卖大米 2021-5-10 530


No.1 人口最多的年份

解题思路

数据范围比较小,直接枚举统计即可。

代码展示


**classSolution** {
    **publicintmaximumPopulation**(**int**[][] logs){
        **int**[] population = **newint**[2051];
        **for** (var log : logs) {
            **for** (**int** i = log[0]; i < log[1]; i++) {
                population[i]++;
            }
        }
        **int** res = 1950;
        **for** (**int** i = 1951; i <= 2050; i++) {
            **if** (population[i] > population[res]) {
                res = i;
            }
        }
        **return** res;
    }
}

No.2 下标对中的最大距离

解题思路

输入的两个数组都是单调的,可以使用双指针。

代码展示


class Solution { 
   public int maxDistance(int[] nums1, int[] nums2) { 
       int n = nums1.length, m = nums2.length; 
       int res = 0; 
       for (int i = 0, j = -1; i < n; i++) { 
           while (j + 1 < m && nums1[i] <= nums2[j + 1]) { 
               j++; 
           } 
           res = Math.max(res, j - i); 
       } 
       return res; 
   } 
} 

No.3 子数组最小乘积的最大值

解题思路

单调栈的变形,可以先去做一下最大矩形回顾一下单调栈。

当子数组的最小值确定时,肯定是数组越长越好,所以我们需要知道每个元素左右第一个比它小的元素的位置,以在枚举每个元素作为子数组最小值时,这个子数组最大可以是多大。

代码展示


class Solution { 
   public int maxSumMinProduct(int[] nums) { 
       int n = nums.length; 
       long[] preSum = new long[n + 1]; 
       for (int i = 1; i <= n; ++i) { 
           preSum[i] = preSum[i - 1] + nums[i - 1]; 
       } 

       int[] l = new int[n]; 
       int[] r = new int[n]; 
       Arrays.fill(r, n - 1); 

       LinkedList<Integer> stack = new LinkedList<>(); 
       for (int i = 0; i < n; i++) { 
           while (!stack.isEmpty() && nums[stack.peekFirst()] > nums[i]) { 
               r[stack.pollFirst()] = i - 1; 
           } 
           stack.addFirst(i); 
       } 
       stack = new LinkedList<>(); 
       for (int i = n - 1; i >= 0; i--) { 
           while (!stack.isEmpty() && nums[stack.peekFirst()] > nums[i]) { 
               l[stack.pollFirst()] = i + 1; 
           } 
           stack.addFirst(i); 
       } 

       long res = 0; 
       for (int i = 0; i < n; i++) { 
           res = Math.max(res, (preSum[r[i] + 1] - preSum[l[i]]) * nums[i]); 
       } 

       return (int) (res % 1000000007L); 
   } 
}

No.4 有向图中最大颜色值 解题思路

先判断图中是否有环,有环直接返回 -1.

无环的话则使用动态规划求解。

代码展示


class Solution { 
   public int largestPathValue(String colors, int[][] edges) { 
       // 建图 
       int n = colors.length(); 
       Node[] nodes = new Node[n]; 
       for (int i = 0; i < n; i++) { 
           nodes[i] = new Node(); 
       } 
       for (int[] e : edges) { 
           nodes[e[0]].nei.add(nodes[e[1]]); 
       } 
       // 判环 
       for (Node node : nodes) { 
           if (findCircle(node)) { 
               return -1; 
           } 
       } 
       // 动态规划 
       int best = 0; 
       for (int i = 'a'; i <= 'z'; i++) { 
           for (int j = 0; j < n; j++) { 
               nodes[j].dp = -1; 
               nodes[j].val = colors.charAt(j) == i ? 1 : 0; 
           } 
           for (int j = 0; j < n; j++) { 
               best = Math.max(best, dp(nodes[j])); 
           } 
       } 
       return best; 
   } 

   public int dp(Node cur) { 
       if (cur.dp == -1) { 
           cur.dp = 0; 
           for (Node node : cur.nei) { 
               cur.dp = Math.max(cur.dp, dp(node)); 
           } 
           cur.dp += cur.val; 
       } 
       return cur.dp; 
   } 

   // 精简版的 Tarjan 算法: 
   // 仅用作判环,而无需求出强连通分量 
   // 所以并不需要真正使用栈,只需要一个标志位即可 
   boolean findCircle(Node cur) { 
       if (cur.vis) { 
           return cur.stk; 
       } 
       cur.vis = cur.stk = true; 
       for (Node node : cur.nei) { 
           if (findCircle(node)) { 
               return true; 
           } 
       } 
       cur.stk = false; 
       return false; 
   } 
} 

class Node { 
   int val, dp; 
   boolean vis, stk; 
   List<Node> nei; 

   Node() { 
       dp = -1; 
       nei = new ArrayList<>(); 
   } 
}
最新回复 (0)
返回