LeetCode笔记:Biweekly Contest 38 比赛记录

0. 赛后总结

这一次的比赛结果整体上还是比较满意的,毕竟4道题都搞定了,就很开心。

排名来说国内129,世界394,差不多就是前6%前7%的样子,唯一可惜的是最后一题一开始题目看错了,浪费了不少时间,否则成绩也许还能再往上拉一下,可惜了。

1. 题目一

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

1. 解题思路

这一题归根结底就是一个排序问题,唯一的考察点在于比较函数的写作上需要按照题目要求定制,但是也不难,直接按照题目要求给出就行了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        counter = Counter(nums)
        nums = sorted(nums, key=lambda x: (counter[x], -x))
        return nums

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

不过当前似乎提交总量不够,看不到其他人的解法,暂时不知道有没有更好的解题思路,不过整体上估计是不会有什么太大的差异了。

2. 题目二

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

1. 解题思路

这一题事实上也非常的简单,其实就是将所有的点按照横坐标进行排序之后看两个相邻点之间的最大x坐标距离。

我们直接给出python代码实现即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maxWidthOfVerticalArea(self, points: List[List[int]]) -> int:
        x = sorted([p[0] for p in points])
        return max([x[i+1] - x[i] for i in range(len(x)-1)])

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

属于当前最优代码实现。

3. 题目三

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

1. 解题思路

这一题算是这一次的比赛里面最让我头疼的一题了,因为确实没啥好的思路,最后只能尝试这暴力求解,直接来了一个4层循环。

不过万幸的是,居然给过了。。。

2. 代码实现

给出暴力求解的代码实现如下:

class Solution:
    def countSubstrings(self, s: str, t: str) -> int:
        ans = 0
        n = len(s)
        m = len(t)
        
        @lru_cache(None)
        def dp(sub):
            l = len(sub)
            if l > m:
                return 0
            ans = 0
            for i in range(m-l+1):
                diff = 0
                for c1, c2 in zip(sub, t[i:i+l]):
                    if c1 != c2:
                        diff += 1
                if diff == 1:
                    ans += 1
            return ans
            
        for i in range(1, n+1):
            for j in range(n-i+1):
                sub = s[j:j+i]
                ans += dp(sub)
        return ans

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

当前的最优代码实现耗时1064ms,比我们有一倍以上的性能提升,不过看他的代码,也是n多层for循环,就很烦,不想看了,如果有读者感兴趣的话可以自行去看一下。

4. 题目四

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

1. 解题思路

这一题刚开始做的时候看错题目了,以为每一个单词都有一个k,结果发现k这个参数是所有单词共享的,那么题目整体就简单许多了,就变成了一道常规的动态规划的题目。

显然,当所有的单词都共享一个k时,在每一位上取用的字母来源自哪个单词就不太重要了,因此,我们首先使用一个counter来记录每一位上包含的字母个数。

而后,就是一个简单的动态规划的实现:

  • 如果单词中第k位上存在目标单词第i位上的字符c,则dp(i, k) = counter[i][c] * dp(i+1, k+1) + dp(i, k+1)
  • 反之,如果单词中第k位上不存在目标单词第i位上的字符c,则dp(i, k) = dp(i, k+1)
  • 如果i == len(target),说明已经一次匹配完成,返回最终结果为1即可;
  • 如果k == len(word),说明已经没有可能的候选字符给他选择了,匹配失败,返回结果为0即可。

2. 代码实现

按照上述的解题思路,我们就可以给出最终的python代码实现如下:

class Solution:
    def numWays(self, words: List[str], target: str) -> int:
        MOD = 1000000007
        
        n = len(target)
        m = len(words[0])
        counter = [Counter(word[i] for word in words) for i in range(m)]
        
        @lru_cache(None)
        def dp(idx, k):
            if idx >= n:
                return 1
            elif k >= m:
                return 0
            if counter[k][target[idx]] == 0:
                return dp(idx, k+1) % MOD
            else:
                return (counter[k][target[idx]] * dp(idx+1, k+1) + dp(idx, k+1)) % MOD
        
        return dp(0, 0)

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

当前最优的代码实现耗时904ms,但是实际提交之后评测发现耗时2364ms,并不比我们的代码实现要高效,因此,这里就不再多做展开了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值