Leecode刷题C语言之统计满足K约束的子字符串数量②
执行结果:通过
执行用时和内存消耗如下:
题目: 统计满足K约束的子字符串数量②
给你一个 二进制 字符串 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]
解题思路:
- 初始化变量:
cnt[2]
:一个数组,用于记录当前遍历到的子字符串中字符'0'
和字符'1'
的数量。n
:字符串s
的长度。returnSize
:用于返回结果数组的大小,设置为查询的数量queriesSize
。ans
:结果数组,用于存储每个查询的结果,初始化为全零。right
:一个数组,用于记录每个位置i
右侧第一个使得字符'0'
和字符'1'
的数量都大于k
的位置(如果不存在这样的位置,则设为n
)。temp
:一个辅助数组,用于快速计算满足条件的子字符串数量。
- 预处理:
- 初始化
right
数组,将所有值设为n
,表示默认没有位置使得字符'0'
和字符'1'
的数量都大于k
。 - 初始化
temp
数组,用于存储到当前位置为止,满足条件的子字符串数量。
- 初始化
- 第一次遍历(计算
right
和temp
数组):- 使用双指针
i
和p
,其中i
是当前遍历到的位置,p
是窗口的左边界。 - 遍历字符串
s
,更新cnt
数组以记录当前窗口内字符'0'
和字符'1'
的数量。 - 当窗口内字符
'0'
和字符'1'
的数量都大于k
时,移动左边界p
,并更新right[p]
为当前位置i
(表示p
右侧第一个不满足条件的位置是i
)。 - 计算
temp[i+1]
,表示到当前位置为止,以每个位置为结尾的满足条件的子字符串数量。这是通过累加(i - p + 1)
实现的,因为从p
到i
的每个位置都可以作为满足条件的子字符串的结尾。
- 使用双指针
- 处理查询:
- 对于每个查询
[l, r]
,计算满足条件的子字符串数量。 - 使用
right[l]
来确定从l
开始,第一个不满足条件的位置t
(如果right[l]
大于r
,则t
设为r + 1
)。 - 计算两部分子字符串的数量:
part1
:从l
到t-1
的子字符串中,满足条件的子字符串数量。这部分可以通过计算等差数列的和(t - l + 1) * (t - l) / 2
得到。part2
:从t
到r
的子字符串中,满足条件的子字符串数量。这部分可以直接从temp
数组中通过temp[r+1] - temp[t]
得到。
- 将
part1
和part2
相加,得到查询结果,并存储在ans
数组中。
- 对于每个查询
- 释放内存:
- 释放
right
和temp
数组占用的内存。
- 释放
- 返回结果:
- 返回结果数组
ans
。
- 返回结果数组
long long* countKConstraintSubstrings(char* s, int k, int** queries, int queriesSize, int* queriesColSize, int* returnSize) {
int cnt[2] = {0};
int n = strlen(s);
(*returnSize) = queriesSize;
long long* ans = calloc(queriesSize,sizeof(long long));
int *right = (int*)malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
right[i] = n;
}
long long* temp = calloc(n+1,sizeof(long long));
int p = 0;
for(int i = 0;i < n;i++){
cnt[s[i]-'0']++;
while(cnt[0] > k&&cnt[1] > k){
cnt[s[p]-'0']--;
right[p] = i;
p++;
}
temp[i+1] = temp[i] + i - p + 1;
}
for(int i = 0;i < queriesSize;i++){
int l = queries[i][0] , r = queries[i][1];
int t = right[l] <= r ? right[l] : r + 1;
long long part1 = (long long)(t - l + 1) * (t - l) / 2;
long long part2 = temp[r+1] - temp[t];
ans[i] = part1 + part2;
}
free(right);
free(temp);
return ans;
}
原文地址:https://blog.csdn.net/babyiu5201314/article/details/143738600
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!