【名词解释】
第一行输入两个整数
——字符串长度与目标子序列数量。
第二行输入一个长度为
的 01 串
(下标从
开始)。
若不存在满足要求的区间,输出单独一行-1;否则输出两个整数
表示区间端点(输出任意一组均可)。
4 2 0011
1 3
子串内的
子序列共有
个:
、
。
4 2 1110
-1
接收控制台传过来的字符串长度和目标子序列数量,注意子序列数量可能超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);
}
}
}