LeetCode笔记:Weekly Contest 312

  • LeetCode笔记:Weekly Contest 312
    • 1. 题目一
      • 1. 解题思路
      • 2. 代码实现
    • 2. 题目二
      • 1. 解题思路
      • 2. 代码实现
    • 3. 题目三
      • 1. 解题思路
      • 2. 代码实现
    • 4. 题目四
      • 1. 解题思路
      • 2. 代码实现
  • 比赛链接:https://leetcode.com/contest/weekly-contest-312/

1. 题目一

给出题目一的试题链接如下:

  • 2418. Sort the People

1. 解题思路

这一题思路上还是很直接的,就是用height作为指标对人名进行排序即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def sortPeople(self, names: List[str], heights: List[int]) -> List[str]:
        peoples = [(k, v) for k, v in zip(names, heights)]
        peoples = sorted(peoples, key=lambda x: x[1], reverse=True)
        return [x[0] for x in peoples]

提交代码评测得到:耗时245ms,占用内存14.4MB。

2. 题目二

给出题目二的试题链接如下:

  • 2419. Longest Subarray With Maximum Bitwise AND

1. 解题思路

这一题由于是bitwise-and,因此,要获得最大的结果,事实上就只能是最大值构成的子数组,再加上连续条件,因此事实上就是求取最大值的最长连续子序列。

因此,我们对其进行一下实现即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        k = max(nums)
        res, cnt = 0, 0
        for x in nums:
            if x == k:
                cnt += 1
            else:
                res = max(res, cnt)
                cnt = 0
        res = max(res, cnt)
        return res

提交代码评测得到:耗时2240ms,占用内存28.6MB。

3. 题目三

给出题目三的试题链接如下:

  • 2420. Find All Good Indices

1. 解题思路

这一题乍看起来有点难,但其实我们只需要考察每一个位置左侧的非递增子数组的长度以及其右侧的非递减子数组的长度,这一操作通过递推的思路事实上是可以简单求解的。

然后,我们只需要从中挑选出其中左右两侧的结果均不小于k的结果即可。

整体而言,算法复杂度就是 O ( N ) O(N) O(N)

2. 代码实现

给出python代码实现如下:

class Solution:
    def goodIndices(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        lcnt, rcnt = [1 for _ in range(n)], [1 for _ in range(n)]
        for i in range(n-1):
            if nums[i+1] <= nums[i]:
                lcnt[i+1] = lcnt[i]+1
            if nums[n-1-i] >= nums[n-2-i]:
                rcnt[n-2-i] = rcnt[n-1-i]+1
        return [i for i in range(k, n-k) if lcnt[i-1] >= k and rcnt[i+1] >= k]

提交代码评测得到:耗时2439ms,占用内存30.7MB。

4. 题目四

给出题目四的试题链接如下:

  • 2421. Number of Good Paths

1. 解题思路

这一题我的思路就是使用dsu。

具体而言,我们以节点的val为顺序,依次将对应val下所有的节点与其连接点中较小的点进行连接。

此时,在每一个时刻,我们对值为v的节点完成了连接,那么对于dsu中处于同一个集合的这样两个节点,他们之间必然存在一条good path。因为显然这两个节点相互连通,且我们只用到了val不大于v的节点,所以也满足good path的第二个条件。

故而,我们只需要统计每一次操作之后这些节点构成的全部集合,然后对每一个集合考察组合数 C n 2 C_n^{2} Cn2,并将其相加即可。

最后,由于单个节点也是一个good path,因此,我们对最后的结果加上n就是我们最终的答案。

2. 代码实现

具体翻译成python代码语言如下:

class DSU:
    def __init__(self, N):
        self.root = [i for i in range(N)]
        
    def find(self, k):
        if self.root[k] != k:
            self.root[k] = self.find(self.root[k])
        return self.root[k]
    
    def union(self, a, b):
        x = self.find(a)
        y = self.find(b)
        if x != y:
            self.root[y] = x
        return

class Solution:
    def numberOfGoodPaths(self, vals: List[int], edges: List[List[int]]) -> int:
        n = len(vals)
        
        dsu = DSU(n)
        
        edges = sorted(edges, key=lambda x: max(vals[x[0]], vals[x[1]]))
        nodes = defaultdict(list)
        for i, v in enumerate(vals):
            nodes[v].append(i)
            
        i = 0
        res = 0
        while i < n-1:
            u, v = edges[i]
            
            val = max(vals[u], vals[v])
            while i < n-1:
                u, v = edges[i]
                if max(vals[u], vals[v]) != val:
                    break
                dsu.union(u, v)
                i += 1
            
            cnt = defaultdict(int)
            for u in nodes[val]:
                cnt[dsu.find(u)] += 1
            for v in cnt.values():
                res += v * (v-1) // 2
        return res + n

提交代码评测得到:耗时2761ms,占用内存31.8MB。

你可能感兴趣的:(leetcode笔记,周赛312,leetcode,2418,leetcode,2419,leetcode,2421,leetcode,2420)