赞
踩
我们处理很多求子数组,子串的时候对某种要求有限制,比如要求子串和为 k k k的倍数这种,实际上就是把所有前缀和 % k \%k %k,然后定义一个下标,然后找到相同的 s s s即可,这就是前缀和哈希表的思路
这道题要求我们求一个子串中数字和字母的个数相同,要让子串最大,我们可以假设字母为 − 1 -1 −1,数字为 1 1 1,所以就是求前缀和相同的最大下标就行,哈希表我们可以记录最左边那个位置即可
class Solution:
def findLongestSubarray(self, array: List[str]) -> List[str]:
s = list(accumulate((-1 if c == 0 else 1 for c in nums), initial = 0))
begin = end = 0
first = {}
for i, v in enumerate(s):
j = first.get(v, -6)
if j < 0:
first[v] = i
elif i - j > end - begin:
begin, end = j, i
return array[begin:end]
这道题思路也是一样的,我们记录一个总和每次对 k k k取模,然后如果发现有一样的,就加上 c n t [ s ] cnt[s] cnt[s],没有就创建新的,然后 c n t [ s ] + = 1 cnt[s] += 1 cnt[s]+=1
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
mp = Counter()
mp[0] = 1
sum, cnt = 0, 0
for c in nums:
sum += c
if sum - k in mp:
cnt += mp[sum - k]
mp[sum] += 1
return cnt
下面对相同题目附上链接
974. 和可被 K 整除的子数组 - 力扣(LeetCode)
1590. 使数组和能被 P 整除 - 力扣(LeetCode)
下面这几道题是结合状态压缩和位运算的题目
这道题的解题关键在于只有
A
−
J
A-J
A−J总共就10
个字符,所以很有可能要出现状态压缩和位运算相关的,所以我们可以用一个10位的二进制位表示每个字符出现的奇偶次数,0表示出现了偶数次,为1表示出现了奇数次,然后我们可以通过异或运算来变化,因为异或可以实现2进制的模2加法,我们用
s
s
s表示当前异或得到的结果,如果
s
s
s之前出现过,可以说明这中间出现的字符全部为偶数次
5
⊕
a
⊕
b
⊕
c
⊕
d
=
5
5 \oplus a \oplus b \oplus c \oplus d = 5
5⊕a⊕b⊕c⊕d=5
由于异或运算满足交换律和结合律,可以重新排列次序:
5 ⊕ ( a ⊕ b ⊕ c ⊕ d ) = 5 5 \oplus (a \oplus b \oplus c \oplus d) = 5 5⊕(a⊕b⊕c⊕d)=5
这等价于:
5 ⊕ 5 = a ⊕ b ⊕ c ⊕ d 5 \oplus 5 = a \oplus b \oplus c \oplus d 5⊕5=a⊕b⊕c⊕d
由于任何数与自身异或结果为0, 5 ⊕ 5 = 0 5 \oplus 5 = 0 5⊕5=0。所以:
0
=
a
⊕
b
⊕
c
⊕
d
0 = a \oplus b \oplus c \oplus d
0=a⊕b⊕c⊕d
接下来要求只出现1次的结果,实际上就是要求一个二进制数是的s ^ y = 1 << i,然后y = 1 << i ^ s
class Solution:
def wonderfulSubstrings(self, word: str) -> int:
cnt = [0] * 1024
cnt[0] = 1
s = ans = 0
for c in word:
s ^= 1 << (ord(c) - ord('a'))
ans += cnt[s]
for i in range(10):
ans += cnt[s ^ (1 << i)]
cnt[s] += 1
return ans
附上类似题目:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。