LeetCode笔记:Biweekly Contest 45 比赛记录

  • LeetCode笔记:Biweekly Contest 45
    • 0. 赛后总结
    • 1. 题目一
      • 1. 解题思路
      • 2. 代码实现
    • 2. 题目二
      • 1. 解题思路
      • 2. 代码实现
    • 3. 题目三
      • 1. 解题思路
      • 2. 代码实现
    • 4. 题目四
      • 1. 解题思路
      • 2. 代码实现

0. 赛后总结

这一次的比赛整体还好吧,四道题都做出来了,所以整体排名就挺高的,不过后来发现其实有运气的成分,因为最后一题做的方法并非是最优解法,是会遇到超时问题的,只是比赛的时候运气好凑巧过关了而已……

总之,路还长,还是要慢慢加油啊……

1. 题目一

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

  • 5657. 唯一元素的和

1. 解题思路

第一题就没啥好说的,用一个counter记录下每个元素出现的次数然后将只出现过一次的元素进行求和即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def sumOfUnique(self, nums: List[int]) -> int:
        cnt = Counter(nums)
        eff = [x for x in cnt if cnt[x] == 1]
        return sum(eff) if eff != [] else 0

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

2. 题目二

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

  • 5658. 任意子数组和的绝对值的最大值

1. 解题思路

这一题的本质也就是求一下最大子串以及最小子串,然后取绝对值求两者的最大值。

而关于最大子串或者最小子串的获取方式,就可以求一个累积和,然后求一下单调递增/递减子串就行了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maxAbsoluteSum(self, nums: List[int]) -> int:
        s = [0] + list(accumulate(nums))
        n = len(s)
        l2r = [0]
        r2l = [0]
        res = 0
        for i in range(1, n):
            while l2r != [] and  l2r[-1] >= s[i]:
                l2r.pop()
            l2r.append(s[i])
            res = max(res, l2r[-1]-l2r[0])
            
            while r2l != [] and  r2l[-1] <= s[i]:
                r2l.pop()
            r2l.append(s[i])
            res = max(res, r2l[0] - r2l[-1])
        return res

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

3. 题目三

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

  • 5659. 删除字符串两端相同字符后的最短长度

1. 解题思路

这一题的思路感觉较之上一题而言更加直接,只要不断地按照相同的连续字符对原字符串进行聚类,然后按照题目说的将前后相同的字符进行删除即可。

唯一需要注意一下的是,当字符串被删至只剩下一种字符时,如果该字符只有一个,那么返回1,否则返回0。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minimumLength(self, s: str) -> int:
        record = []
        n = len(s)
        cnt = 1
        for i in range(1, n):
            if s[i] == s[i-1]:
                cnt += 1
            else:
                record.append((s[i-1], cnt))
                cnt = 1
        record.append((s[n-1], cnt))
        while len(record) > 1 and record[0][0] == record[-1][0]:
            record.pop(0)
            record.pop(-1)
        if len(record) == 1:
            return 0 if record[0][1] > 1 else record[0][1]
        
        return sum([x[1] for x in record])

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

4. 题目四

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

  • 5660. 最多可以参加的会议数目 II

1. 解题思路

这道题比赛的时候我使用了深度优先遍历的方式进行了实现,当时运气好一次性过了,但是耗时8s+,然后第二天重新提交就发现过不了了……

然后看了一下别人的解法,发现整体的耗时都在1s附近,然后算法来说都是用的动态规划,因此,我们来好好研究一下如何使用动态规划来进行这道题的算法实现。


看了一下当前网上的解答,主体思路为:

  • 定义动态规划项dp(idx, k)为从包含第idx个会议开始,参加至多k个会议时所能够获得的最大最大会议价值。

此时,我们很快就能够得到递推公式如下:

dp(idx, k) = max(events[idx][2] + dp(nxt, k-1), dp(idx+1, k))

其中,前者表示参加该场会议的情况,后者表示不参加该场会议的情况。

由此,我们即可快速地给出代码实现。

2. 代码实现

给出python代码实现如下:


import bisect

class Solution:
    def maxValue(self, events: List[List[int]], k: int) -> int:
        events = sorted(events)
        st_list = [x[0] for x in events]
        n = len(events)
        
        @lru_cache(None)
        def dp(idx, k):
            if idx == n:
                return 0
            if k == 0:
                return 0
            ed = events[idx][1]
            nxt = bisect.bisect_left(st_list, ed+1)
            return max(events[idx][2]+dp(nxt, k-1), dp(idx+1, k))
        
        return dp(0, k)

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

你可能感兴趣的:(leetcode笔记,leetcode,算法,数据结构,动态规划)