前缀和+哈希表

前缀和+哈希表

我们处理很多求子数组,子串的时候对某种要求有限制,比如要求子串和为 k k k的倍数这种,实际上就是把所有前缀和 % k \%k %k,然后定义一个下标,然后找到相同的 s s s即可,这就是前缀和哈希表的思路

面试题 17.05. 字母与数字 - 力扣(LeetCode)

思路:

这道题要求我们求一个子串中数字和字母的个数相同,要让子串最大,我们可以假设字母为 − 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]

560. 和为 K 的子数组 - 力扣(LeetCode)

思路:

这道题思路也是一样的,我们记录一个总和每次对 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)

523. 连续的子数组和 - 力扣(LeetCode)

下面这几道题是结合状态压缩和位运算的题目

1915. 最美子字符串的数目 - 力扣(LeetCode)

思路:

这道题的解题关键在于只有 A − J A-J AJ总共就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 5abcd=5

由于异或运算满足交换律和结合律,可以重新排列次序:

5 ⊕ ( a ⊕ b ⊕ c ⊕ d ) = 5 5 \oplus (a \oplus b \oplus c \oplus d) = 5 5(abcd)=5

这等价于:

5 ⊕ 5 = a ⊕ b ⊕ c ⊕ d 5 \oplus 5 = a \oplus b \oplus c \oplus d 55=abcd

由于任何数与自身异或结果为0, 5 ⊕ 5 = 0 5 \oplus 5 = 0 55=0。所以:

0 = a ⊕ b ⊕ c ⊕ d 0 = a \oplus b \oplus c \oplus d 0=abcd
接下来要求只出现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

附上类似题目:

1371. 每个元音包含偶数次的最长子字符串 - 力扣(LeetCode)

1542. 找出最长的超赞子字符串 - 力扣(LeetCode)

  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值