LeetCode笔记:Biweekly Contest 74

本文详细记录了LeetCode双周赛第74场的四道题目解题思路与Python代码实现。第一题通过统计数组元素个数判断能否均分为偶数对;第二题讨论字符串中子序列的最大数量,涉及排列组合与字符串处理;第三题通过排序与动态调整找到使数组元素和减半所需的最少操作次数;第四题采用动态规划解决最小白色瓷砖数量问题。文章探讨了算法优化与复杂度控制。
摘要由CSDN通过智能技术生成

1. 题目一

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

1. 解题思路

这一题的思路还是很直接的,只需要对数组中的每一个元素的个数进行一下统计,要能够成功分组,当且仅当所有元素的个数均为偶数。

2. 代码实现

给出python代码实现如下:

class Solution:
    def divideArray(self, nums: List[int]) -> bool:
        cnt = Counter(nums)
        return all(v % 2 == 0 for v in cnt.values())

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

2. 题目二

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

1. 解题思路

这一题的思路其实也比较直接,显然,pattern中没有出现的字符对于结果是无用的,因此,我们首先可以对字符串进行简化,只保留pattern当中出现过的字符,然后,我们来考察如何获得最多的pattern。

在此之前,我们首先考察一种特殊情况,即pattern为两个相同字符的情况,此时根据排列组合,答案事实上是显见的,且字符增加方法也是无所谓的,只要随意增加一个字符即可。

如果pattern的字符不同,那么,增加字符的方式就一定是以下两者之一:

  1. 在字符串开头加上pattern[0]
  2. 在字符串尾部加上pattern[1]

对于前者,增加的pattern数目为pattern[1]的数目,而对于后者,增加的pattern数目为pattern[0]的数目。

因此,剩下的我们只需要考察原始序列当中包含的pattern数目即可,这个问题只要对每一个pattern[0]字符后面的pattern[1]的数目进行一下求和即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
        s = [ch for ch in text if ch in pattern]
        n = len(s)
        if pattern[0] == pattern[1]:
            return n * (n+1) // 2
        cnt = 0
        res = 0
        for ch in s[::-1]:
            if ch == pattern[1]:
                cnt += 1
            else:
                res += cnt
        return res + max(cnt, n-cnt)

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

3. 题目三

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

1. 解题思路

这一题我的思路其实挺简单的,不过相对的效率就不是很高……

我的思路就是不断地取最大的元素进行减半处理。

因此,我们就是直接对原数组进行一次排序,然后不断地pop,然后取半,最后二分插入即可。

不过直接这样的解法遇到了超时,因此我们稍微做了一点优化,即:

  • 显然的,如果最大的元素减半之后不大于最小的元素,那么最优的解法必然是所有的元素减半,因此,我们返回数组长度即可。

另一方面,对于元素减半之后如果长度小于了最小的元素,那么我们事实上也不再需要将这个元素放回到数组当中了。

通过上述优化,代码不再遇到超时问题,不过还是感觉不太优雅……

anyway,先将就将就吧……

2. 代码实现

给出python代码实现如下:

class Solution:
    def halveArray(self, nums: List[int]) -> int:
        nums = sorted(nums)
        if nums[-1] / 2 <= nums[0]:
            return len(nums)
        s = sum(nums) / 2
        rm = 0
        cnt = 0
        while rm < s:
            x = nums.pop() / 2
            rm += x
            cnt += 1
            if rm < s and x > nums[0]:
                bisect.insort(nums, x)
        return cnt

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

看了一下当前的最优解法,感觉也就是把二叉排序换成了堆排,没啥本质的区别……

4. 题目四

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

1. 解题思路

这一题感觉就是一个简单地动态规划的题目。

对每一个位置,如果该位置本来就是黑色的话,那么我们无需进行额外的操作,否则,我们可以有两种操作,要不就是铺上地毯,要不然就是不铺,然后继续考虑下一个位置,此时白色格子总数就会+1。

特殊的,如果剩下的地毯可以铺满所有的位置时,那么直接返回0即可;反之,如果地毯已经铺完了,那么只要返回剩下的所有的白色的格子数目即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minimumWhiteTiles(self, floor: str, numCarpets: int, carpetLen: int) -> int:
        n = len(floor)
        cnt = [0 for _ in range(n+1)]
        for i in range(n-1, -1, -1):
            if floor[i] == "0":
                cnt[i] = cnt[i+1]
            else:
                cnt[i] = cnt[i+1] + 1
        
        @lru_cache(None)
        def dp(idx, k):
            if idx >= n:
                return 0
            elif k == 0:
                return cnt[idx]
            elif k * carpetLen >= n - idx:
                return 0
            elif floor[idx] == "0":
                return dp(idx+1, k)
            
            return min(1 + dp(idx+1, k), dp(idx+carpetLen, k-1))
        
        return dp(0, numCarpets)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值