LeetCode 2489. 固定比率的子字符串数

2489. 固定比率的子字符串数

给定一个二进制字符串 s 和两个整数 num1 和 num2num1 和 num2 为互质。

比率子串 是 s 的子串,其中子串中 0 的数量与 1 的数量之比正好是 num1 : num2

  • 例如,如果 num1 = 2 和 num2 = 3,那么 "01011" 和 "1110000111" 是比率子串,而 "11000" 不是。

返回 s 的 非空 比率子串的个数。

注意:

  • 子串 是字符串中连续的字符序列。
  • 如果 gcd(x, y) == 1,则 x 和 y 为 互质,其中 gcd(x, y) 为 x 和 y 的最大公约数。

示例 1:

输入: s = "0110011", num1 = 1, num2 = 2
输出: 4
解释: 有 4 个非空的比率子串。
- 子字符串 s[0..2]: "0110011"。它包含一个 0 和两个 1。比例是 1:2。
- 子字符串 s[1..4]: "0110011"。它包含一个 0 和两个 1。比例是 1:2。
- 子字符串 s[4..6]: "0110011"。它包含一个 0 和两个 1。比例是 1:2。
- 子字符串 s[1..6]: "0110011"。它包含两个 0 和四个 1。比例是 2:4 == 1:2。
它可以显示没有更多的比率子串。

示例 2:

输入: s = "10101", num1 = 3, num2 = 1
输出: 0
解释: s 没有比率子串,返回 0。

提示:

  • 1 <= s.length <= 10^5
  • 1 <= num1, num2 <= s.length
  • num1 和 num2 互质。

提示 1

Let Func(i) denote the number of 0’s in the prefix [0…i]. We want to find the number of pairs of indices L and R such that Func(R) - Func(L) : R - L - Func(R) + Func(L) = num1 : num2.


提示 2

It is better to simplify the formula.


提示 3

Func(R) * (num1 + num2) - R * num1 = Func(L) * (num1 + num2) - L * num1.


提示 4

Iterate from left to right and use a hash map to count the number of indices having the same value for the above formula.

解法1:前缀和 + 哈希表

presum[ i ] = sum (nums[0..i]), presum[i] 表示 nums[0..i] 中1的个数。

i < j

presum[ j ] - presum[ i ] 表示 nums[i + 1...j] 中 1 的个数,j - i 表示 nums[i + 1...j] 的元素个数,

j - i - (presum[j] - presum[i]) , 即 j - presum[j] - i - presum[i] 表示 nums[i + 1...j] 中 0 的个数。

j - i - (presum[j] - presum[i]) : presum[j] - presum[i] == num1: num2,  转换成

( j - i - presum[j] + presum[i] ) * num2 == (presum[j] - presum[i]) * num1 , 即

presum[j] * (num1 + num2) - j * num2 == presum[i] * (num1 + num2) - i * num2

我们枚举 j ,在哈希表中 找到符合要求的 i 的个数,累加答案。

Java版:

class Solution {
    public long fixedRatio(String s, int num1, int num2) {
        long presum = 0;
        long ans = 0;
        Map<Long, Integer> map = new HashMap<>();
        map.put((long) num2, 1);
        for (int i = 0; i < s.length(); i++) {
            presum += s.charAt(i) == '0' ? 0 : 1;
            long key = presum * (num1 + num2) - i * num2;
            if (map.containsKey(key)) {
                ans += map.get(key);
            }
            map.merge(key, 1, Integer::sum);
        }
        return ans;
    }
}

Python3版:

class Solution:
    def fixedRatio(self, s: str, num1: int, num2: int) -> int:
        ans = 0
        presum = 0
        dic = {num2: 1}
        for i, c in enumerate(s):
            presum += 1 if c == '1' else 0 
            key = presum * (num1 + num2) - i * num2
            ans += dic[key] if key in dic else 0 
            dic[key] = 1 if key not in dic else dic[key] + 1
        return ans

复杂度分析

  • 时间复杂度:O(n),其中 n 是 字符串 s ​ 的长度。需要遍历 s 一次计算前缀和,对于每个元素,更新前缀和、更新答案与操作哈希表的时间都是 O(1)。
  • 空间复杂度:O(n),其中 n 是 字符串 s ​ 的长度。哈希表的空间是 O(n)。 
  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值