LeetCode每日一题3261---统计满足 K 约束的子字符串数量 II

一、题目描述

给你一个 二进制 字符串 s 和一个整数 k

另给你一个二维整数数组 queries ,其中 queries[i] = [li, ri]

如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束:

字符串中 0 的数量最多为 k

字符串中 1 的数量最多为 k

返回一个整数数组 answer ,其中 answer[i] 表示 s[li..ri] 中满足 k 约束 的 子字符串的数量。

示例 1:

输入:s = "0001111", k = 2, queries = [[0,6]]

输出:[26]

解释:

对于查询 [0, 6], s[0...6] = "0001111" 的所有子字符串中,除 s[0...5] = "000111" 和 s[0...6] = "0001111" 外,其余子字符串都满足 k 约束。

示例 2:

输入:s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]

输出:[15,9,3]

解释:

s 的所有子字符串中,长度大于 3 的子字符串都不满足 k 约束。

提示:

1 <= s.length <= 105

s[i] 是 '0' 或 '1'

1 <= k <= s.length

1 <= queries.length <= 105

queries[i] == [li, ri]

0 <= li <= ri < s.length

所有查询互不相同

二、解题思路

这道题目与统计满足 K 约束的子字符串数量 I相似,就是需要处理多个子串,完全可以利用上一次的函数进行求解,但是由于这次的字符串长度太大,会导致超出时间限制,因此需要特殊的方法处理,可以使用双指针 + 前缀和 + 二分

三、代码

1、普通方法(超出时间限制)

cpp 复制代码
class Solution {
public:
    // 计算符合条件的子串个数
    int countKConstraintSubstrings1(string& s, int k) {
        int l = 0, count = 0, one = 0, zero = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '1') one++;
            else zero++;

            // Shrink the window until both one and zero counts are <= k
            while (one > k && zero > k) {
                if (s[l++] == '1') one--;
                else zero--;
            }

            // Count all valid substrings ending at i
            count += i - l + 1;
        }
        return count;
    }

    vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {
        vector<long long> result(queries.size());
        
        // 针对每个查询直接计算符合条件的子串个数
        for (int i = 0; i < queries.size(); i++) {
            int left = queries[i][0], right = queries[i][1];
            
            // 直接截取查询区间的字符串
            string substring = s.substr(left, right - left + 1);
            result[i] = countKConstraintSubstrings1(substring, k); // 计算当前区间内符合条件的子串个数
        }

        return result;
    }
};

2、双指针 + 前缀和 + 二分

java 复制代码
class Solution {
    public long[] countKConstraintSubstrings(String s, int k, int[][] queries) {
        int n = s.length();
        char[] chars = s.toCharArray();
        int[] f = new int[n + 1];
        long[] sumF = new long[n + 1], sum = new long[n + 1];
        for (int i = 1, j = 1, sum1 = 0; i <= n; i++) {
            sum1 += chars[i - 1] - '0';
            while (sum1 > k && i - j + 1 - sum1 > k) {
                sum1 -= chars[j - 1] - '0';
                j++;
            }
            f[i] = j;
            sumF[i] = sumF[i - 1] + f[i];
            sum[i] = sum[i - 1] + i - j + 1;
        }

        int m = queries.length;
        long[] ans = new long[m];
        for (int i = 0; i < m; i++) {
            int l = queries[i][0] + 1, r = queries[i][1] + 1;
            ans[i] = sum[r] - sum[l - 1];

            int lo = l, hi = r, idx = -1;
            while (lo <= hi) {
                int mid = lo + hi >> 1;
                if (f[mid] < l) {
                    idx = mid;
                    lo = mid + 1;
                } else {
                    hi = mid - 1;
                }
            }

            if (idx != -1) {
                ans[i] -= (long) (idx - l + 1) * l - (sumF[idx] - sumF[l - 1]);
            }
        }

        return ans;
    }
}
相关推荐
VertexGeek32 分钟前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
石小石Orz33 分钟前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
jiao_mrswang1 小时前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca2 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱2 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子2 小时前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!2 小时前
【优选算法】二分查找
c++·算法
王燕龙(大卫)2 小时前
leetcode 数组中第k个最大元素
算法·leetcode
不去幼儿园3 小时前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh3 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法