6020. 将数组划分成相等数对
第一题很简单,不到一分钟就可以做出来了。思路就是统计每一个数字出现的次数,只有所有数字都出现过偶数次,才满足要求。
class Solution:
def divideArray(self, nums: List[int]) -> bool:
# 判断数组是否每一个数字都出现过偶数次
dic = collections.defaultdict(int)
for i, num in enumerate(nums):
dic[num] += 1
for k, v in dic.items():
if v % 2 == 1:
return False
return True
6021. 字符串中最多数目的子字符串
这一题没做出来。主要是因为对贪心法做得少。
贪心的思路是:
根据题意,设pattern中第一个字母为x,第二个字母为y,那么肯定是x越靠左越好,y越靠右越好(这一点当时都没想到)。于是可以直接把x放在最左侧或者y放在最右侧,每遇到一个y就统计左边x的个数。
需要注意的是,如果放x,那么相比于放之前,肯定多的子字符串个数是cy(cy为test中y出现的次数)。
如果放y,比之前做的子字符串个数为cx(cx为test中x出现的次数)。这样的话,我们就可以一次遍历解决两种情况了。
那么怎么计算text中本来有多少个pattern呢,其实在遍历的时候就可以直接计算y左边有多少个x,然后直接累加就行了。
class Solution:
def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
# 如果x==y,此时可以直接遍历text计算有多少个x,那么加上一个,之后用组合公式即可
if pattern[0] == pattern[1]:
cx = 0
for t in text:
if t == pattern[0]:
cx += 1
return cx * (cx + 1) // 2
res = 0
x, y = pattern[0], pattern[1]
cx = cy = 0
for i in range(len(text)):
if text[i] == x:
cx += 1
elif text[i] == y:
cy += 1
res += cx # 当前y左边有多少个x,那么以该y为第二个元素的子字符串就有多少个
return res + max(cx, cy)
6022. 将数组和减半的最少操作次数
这次双周赛,第三题并不难。其实也算贪心的方法,每次把最大的那个数减半,第二次再把当前最大的数减半,以此类推直到总和小于原来的一半,但是这样每次都要排序,很耗时。此时就可以想到有一种数据结构可以在拿出或者放入元素的时候自动维护有序,那就是堆。
不过python中是最小堆,所以我们需要把每个数字都转换成负数,最后求和也不是判断总和小于之前的一半,而是当总和小于之前一半的时候一致循环。
另外一点要注意的是,不需要每次都重新计算总和,这样的话会超时。我们每次都知道前一次的总和,而这次减小了多少我们也知道,所以可以直接计算,不需要对整个数组重新求和。
class Solution:
def halveArray(self, nums: List[int]) -> int:
# 每次从最大的数字开始减小,但是减小后还需要重新对数组排序,这很耗时
# 可以维护一个最大堆
q = []
for num in nums:
heapq.heappush(q, -num)
total = sum(q)
res = 0
new_sum = total
while new_sum < (total / 2):
res += 1
num = heapq.heappop(q)
num = num / 2
new_sum -= num # 新的数组和减少了num
heapq.heappush(q, num)
return res
6023. 用地毯覆盖后的最少白色砖块
pass