【名词解释】
第一行输入两个整数
——字符串长度与目标子序列数量。
第二行输入一个长度为
的 01 串
(下标从
开始)。
若不存在满足要求的区间,输出单独一行-1;否则输出两个整数
表示区间端点(输出任意一组均可)。
4 2 0011
1 3
子串内的
子序列共有
个:
、
。
4 2 1110
-1
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
long long k;
cin >> n >> k;
string s;
cin >> s;
int l = 0;
int r = 0;
int num0 = 0;
int num1 = 0;
long long num = 0;
for (int i = 0; i < n; i++) {
if (num == k) {
cout << l + 1 << ' ' << r + 1 << endl;
return 0;
}
// 扩展
if (num < k) {
r = i;
if (s[r] == '0') {
num0++;
} else {
num1++;
num += num0;
}
}
// 收缩
if (num > k) {
while (num > k) {
if (s[l] == '0') {
num0--;
num -= num1;
} else {
num1--;
}
l++;
}
}
}
cout << -1 << endl;
return 0;
} 接收控制台传过来的字符串长度和目标子序列数量,注意子序列数量可能超int值,所以需用long来接收。
保存控制台过来的字符串,用大小为2的数组分别存储0、1的数量。
定义左右指针left和right开始滑动窗口寻找符合题意的区间,
我们只需要找一个区间,当找到符合条件的区间时,用resultleft、resultright保存区间左右边界,直接返回即可。
用right滑动窗口,只有在右边界字符为1时,才有可能得到结果,当遍历到1时,res += (left, right)区间中0的个数,
当res大于目标值时,需要持续滑动窗口left,left == ‘0’时,res -= 1的数量,直到res <= target,退出循环。
此时判断res 是否等于target,若等于,说明找到了满足题意的区间,记录区间左右边界并返回、输出。
若遍历完集合还未找到,返回-1。
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();
Long k = in.nextLong();
char[] chars = in.next().toCharArray();
int[] zeroAndOne = new int[2];
int left = 0, right = 0;
long res = 0;
int resultleft = 0, resultright = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '1') {
res += zeroAndOne[0];
zeroAndOne[1]++;
while (res > k) {
if (chars[left] == '0') {
res -= zeroAndOne[1];
zeroAndOne[0]--;
} else if (chars[left] == '1') {
zeroAndOne[1]--;
}
left++;
}
if (res == k) {
resultleft = left + 1;
resultright = i + 1;
break;
}
} else {
zeroAndOne[0]++;
}
}
if (resultleft != 0 && resultright != 0) {
System.out.println(resultleft + " " + resultright);
} else System.out.println(-1);
}
}
}
#参考双指针思路 n, k = map(int, input().split()) s = input().strip() if n == 0: print(-1) exit() cnt0 = 0 cnt1 = 0 l = 0 r = 0 # 初始化第一个字符 if s[0] == '0': cnt0 += 1 elif s[0] == '1': cnt1 += 1 num = 0 result = None while l < n and r < n: if num == k: result = (l + 1, r + 1) break if num < k: # 移动右指针 if r + 1 < n: r += 1 current_char = s[r] if current_char == '0': cnt0 += 1 else: num += cnt0 cnt1 += 1 else: # 无法移动右指针时,尝试移动左指针 current_char = s[l] if current_char == '0': num -= cnt1 cnt0 -= 1 else: cnt1 -= 1 l += 1 else: # 移动左指针 current_char = s[l] if current_char == '0': num -= cnt1 cnt0 -= 1 else: cnt1 -= 1 l += 1 # 检查退出循环后是否满足条件 if result is None and num == k and l <= r < n: result = (l + 1, r + 1) if result: print(result[0], result[1]) else: print(-1)