LeetCode笔记:Weekly Contest 238 比赛记录

0. 赛后总结

因为一些众所周知的原因,这周的比赛实际上是没有参加的,就是在赛后补做了以下题目,然后在这里整理了一下,与君共勉。

1. 题目一

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

1. 解题思路

这一题没啥难度,就是将原数用k进制表达出来然后计算一下每一位的数值之和而已。

2. 代码实现

给出python代码实现如下:

class Solution:
    def sumBase(self, n: int, k: int) -> int:
        res = 0
        while n != 0:
            res += n % k
            n = n // k
        return res

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

2. 题目二

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

1. 解题思路

这一题的关键点在于数据只能增不能减,因此,我们首先对所有的数字进行一个排序,然后从小到大依次考察每一个数,假设将目标数字定位这个数,那么最小的变换次数一定是将其之前的几个数变为这个数,直到耗尽所有的变换次数,而这可以通过维护一个滑动窗口进行实现。

当窗口向右滑动一位时,需要增加的操作数为(r-l) * (nums[r] - nums[l]),如果此时操作总数超过额定上限k,此时需要不断地将左窗口边缘向右滑动,直到所用的操作数不多于k为止。

这样,我们就可以在 O ( N ) O(N) O(N)的算法复杂度条件下完成求解。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maxFrequency(self, nums: List[int], k: int) -> int:
        nums = sorted(nums)
        l, r, n = 0, 1, len(nums)
        res = 1
        used = 0
        while r < n:
            delta = nums[r] - nums[r-1]
            used += delta * (r-l)
            while l < r and used > k:
                used -= nums[r] - nums[l]
                l += 1
            res = max(res, r-l+1)
            r += 1
        return res

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

3. 题目三

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

1. 解题思路

这一题的思路倒是没啥,由于要求元音字母顺序且必须包含所有的元音字符,因此,我们遇到并非是递增序列的字符就考察前面是否是满足条件的子串,如果是,那么更新最长子串长度。另一方面,如果新的子串以a开头,那么重新开始计算,否则一直等待直到下一个a出现。

2. 代码实现

给出python代码实现如下:

class Solution:
    def longestBeautifulSubstring(self, word: str) -> int:
        is_continuous = False
        left = -1
        res = 0
        seen = set()
        for i, c in enumerate(word):
            if i == 0:
                if c == 'a':
                    is_continuous = True
                    left = 0
                    seen.add(c)
                continue
            if c >= word[i-1]:
                if is_continuous:
                    seen.add(c)
                    if len(seen) == 5:
                        res = max(res, i - left + 1)
            else:
                is_continuous = False
                seen = set()
                if c == 'a':
                    is_continuous = True
                    left = i
                    seen.add(c)
        return res

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

不过代码实现不是很优雅就是了。

3. 算法优化

当前最优的算法实现耗时仅76ms,他是直接使用了正则表达式进行的代码实现,给出其代码实现如下:

class Solution:
    def longestBeautifulSubstring(self, word: str) -> int:
        import re
        a = re.findall('a*e*i*o*u*',word)
        ans=0
        for i in a:
            if len(set(i))==5:
                ans = max(len(i),ans)
        return ans

唉,这个代码比我们的实现实在是好了太多了,惭愧,惭愧……

4. 题目四

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

1. 解题思路

这道题算是半抄半做的吧,自己有点思路,和答案倒也是一致的,但是有一个细节点没想明白,然后看了答案之后修改了一下思路……

这道题的思路就是将所有的限制按照index进行排序,然后如果我们将每一个限制都给到上限,那么就可以求得两个限制位置之间可以达到的最高值为: ( w 2 − w 1 + ∣ h 2 − h 1 ∣ ) / 2 + m i n ( h 1 , h 2 ) (w_2 - w_1 + |h_2 - h_1|) / 2 + min(h_1, h_2) (w2w1+h2h1)/2+min(h1,h2)

但是这里存在一个前提假设就是所有的限制位置上都是可以达到上限位置的,但是这个实际是没法保证的,因此我们需要对上限的值先进行调整,不过如何调整之前我倒是没有想的很清楚。

答案中给的思路是按照前序和后序分别更新一次,从而确保每一个位置都可以达到,算是非常直接且简洁的一种思路了。

2. 代码实现

我们给出python代码实现如下:

class Solution:
    def maxBuilding(self, n: int, restrictions: List[List[int]]) -> int:
        restrictions = [[1, 0]] + sorted(restrictions)
        if restrictions[-1][0] != n:
            restrictions.append([n, n])
        m = len(restrictions)

        for i in range(1, m):
            restrictions[i][1] = min(restrictions[i][1], restrictions[i-1][1] + restrictions[i][0] - restrictions[i-1][0])

        for i in range(m-2, -1, -1):
            restrictions[i][1] = min(restrictions[i][1], restrictions[i+1][1] + restrictions[i+1][0] - restrictions[i][0])

        res = max([x[1] for x in restrictions[:-1]])
        for i in range(m-1):
            delta = restrictions[i+1][0] - restrictions[i][0] + abs(restrictions[i+1][1] - restrictions[i][1])
            res = max(res, delta // 2 + min(restrictions[i+1][1], restrictions[i][1]))
        return res    

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值