LeetCode笔记:Weekly Contest 310

Posted Espresso Macchiato

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode笔记:Weekly Contest 310相关的知识,希望对你有一定的参考价值。

0. 总结

这次的比赛真心被伤到了,第一名的大佬6分钟就搞定了4道题,然而我却有两道题没有搞定,第三题倒还好,思路一开始想歪了,后来看了大佬的解答之后修正了思路之后还是基本没啥难度的,不过第四题就有点尴尬了,到现在还没能搞定。

不过后来看了其他大佬们的解答之后发现,其实这次的第四题是一个套路问题,不过即便如此还是没有能够搞定这道题,虽然大致是理解了这是什么个结构,不过自己实现还是失败了,有点烦躁,回头再看看吧……

唉,有时候真的觉得还是好好刷一遍算法导论吧,真心好多东西不知道啊……

1. 题目一

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

1. 解题思路

这一题思路上就是一个两步的筛选,首先找出偶数的元素,然后计数之后找到最大的元素即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def mostFrequentEven(self, nums: List[int]) -> int:
        nums = [x for x in nums if x % 2 == 0]
        if nums == []:
            return -1
        cnt = Counter(nums)
        nums = sorted(nums, key=lambda x: (-cnt[x], x))
        return nums[0]

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

2. 题目二

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

1. 解题思路

这一题我的思路就是使用贪婪算法,不断地切分字符串直至出现重复字符,然后统计最后的子串数目即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def partitionString(self, s: str) -> int:
        res = 0
        i, n = 0,len(s)
        while i < n:
            cnt = [0 for _ in range(26)]
            while i < n and cnt[ord(s[i]) - ord('a')] == 0:
                cnt[ord(s[i]) - ord('a')] += 1
                i += 1
            res += 1
        return res

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

3. 题目三

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

1. 解题思路

这一题我一开始的思路还是使用贪婪算法进行处理,不过贪婪算法存在逻辑上的漏洞,因为没有证明贪婪算法得到的局域最优解一定是全局最优解。

后来看了一下大佬们的解法之后发现这道题其实有一个更加直接也更加简单的思路,因为最终可以分成的最小的组数必然是所有区间当中重叠次数最多的区域被重叠的次数。

因此,我们就可以通过一个累积数组来直接获得答案了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minGroups(self, intervals: List[List[int]]) -> int:
        s = []
        for st, ed in intervals:
            s.append((st, 1))
            s.append((ed+1, -1))
        s = sorted(s)
        cnt = 0
        res = 0
        for _, c in s:
            cnt += c
            res = max(res, cnt)
        return res

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

4. 题目四

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

1. 解题思路

这一题本质上就是在有限制的范围内求数组的最大值。

我们考察一个dp数组,然后每一个数组的元素表示以该元素作为最后一个元素时能够形成的最长严格递增数组的长度。

因此,我们顺序考察数组中的每一个数 x x x,就是考察范围从 x − k x-k xk x − 1 x-1 x1的最大值加一与当前值的较大一个更新为当前的最大值。

最后从dp数组当中取出最大值即为我们所需要的答案。

但是上述如何从从 x − k x-k xk x − 1 x-1 x1的取出最大值的操作却有些麻烦,正常操作的话会是一个 O ( k ) O(k) O(k)复杂度的操作,由于 k k k可能很大,因此我们需要对这个进行优化,但是我实在是想不到什么优化方法。

不过后续看大佬们的解答之后发现有一个叫做分段树的数据结构(SegmentTree)就是专门用于处理这类问题的,换言之这就是一个套路题目,难怪大佬们可以做得那么快……

但是,悲剧的是我看了一晚上还是没有完全搞明白这玩意,所以这里就不班门弄斧了,有兴趣的读者可以自行去查阅一下这方面的资料。

这里,我们仅仅给出线上的大佬们的解答如下:

class Solution:
    def lengthOfLIS(self, nums: List[int], k: int) -> int:
        u = max(nums)
        mx = [0] * (4 * u)

        def modify(o: int, l: int, r: int, i: int, val: int) -> None:
            if l == r:
                mx[o] = val
                return
            m = (l + r) // 2
            if i <= m: modify(o * 2, l, m, i, val)
            else: modify(o * 2 + 1, m + 1, r, i, val)
            mx[o] = max(mx[o * 2], mx[o * 2 + 1])

        # 返回区间 [L,R] 内的最大值
        def query(o: int, l: int, r: int, L: int, R: int) -> int:  # L 和 R 在整个递归过程中均不变,将其大写,视作常量
            if L <= l and r <= R: return mx[o]
            res = 0
            m = (l + r) // 2
            if L <= m: res = query(o * 2, l, m, L, R)
            if R > m: res = max(res, query(o * 2 + 1, m + 1, r, L, R))
            return res

        for x in nums:
            if x == 1:
                modify(1, 1, u, 1, 1)
            else:
                res = 1 + query(1, 1, u, max(x - k, 1), x - 1)
                modify(1, 1, u, x, res)
        return mx[1]

以上是关于LeetCode笔记:Weekly Contest 310的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode笔记:Weekly Contest 317

LeetCode笔记:Weekly Contest 288

LeetCode笔记:Weekly Contest 299

LeetCode笔记:Weekly Contest 307

LeetCode笔记:Weekly Contest 325

LeetCode笔记:Weekly Contest 314