当前位置:   article > 正文

前缀和+哈希表_前缀和哈希表设置1

前缀和哈希表设置1

前缀和+哈希表

我们处理很多求子数组,子串的时候对某种要求有限制,比如要求子串和为 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]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

下面对相同题目附上链接

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

附上类似题目:

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/558068
推荐阅读
相关标签
  

闽ICP备14008679号