活动地址:CSDN21天学习挑战赛
题目描述
假设种了一排胡杨总数N,一段时间后发现其中死了M棵,现在给你提供K棵补种的胡杨树,请问怎么补种可以得到连贯的胡杨树最多。
输入
20(总胡杨棵数)
5(死亡胡杨数)
3 7 11 14 18(死亡胡杨编号)
3(补种胡杨数量)
输出
14(补种后最多14棵胡杨连贯)
思考
其实在这个题目中,为了保证连贯的数量最多,那么在死亡胡杨编号数组中补种必定是连贯相邻的,所以这里可以视为一个长度为K的滑动窗口,在死亡胡杨编号数组中滑动,框出的K个编号便是补种的位置,从左向右滑动一遍计算出所有最多连贯胡杨数量,在其中得到最大的数字即可。
代码
public class TreeReplant {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//胡杨总数
int n = scanner.nextInt();
//死亡胡杨数目
int m = scanner.nextInt();
//死亡胡杨编号数组
List<Integer> array = new ArrayList<>();
for (int i=0;i<m;i++) {
array.add(scanner.nextInt());
}
//补种数量
int k = scanner.nextInt();
//记录最大值
int max = 0;
//从左向右移动滑动窗口,这里的i标记的是窗口的左边界
for (int i=0;i<=m-k;i++) {
if (i == 0) {
//滑动窗口在数组最左边
max = Math.max(max, array.get(i+k) - 1);
}else if (i == m-k) {
//滑动窗口在数组最右边
max = Math.max(max, n - array.get(i-1));
}else {
//滑动窗口在数组中间某个位置
max = Math.max(max, array.get(i+k) - array.get(i-1) - 1);
}
}
System.out.println(max);
}
}
总结
这题的关键就是隐藏默认条件–为了保证连续胡杨数量最大,补种的位置肯定在死亡胡杨编号中是相邻连续的。当意识到这点后,问题就很容易解决了,在算法题中还有很多这种滑动窗口的问题,比如寻找长字符串中短字符串的最小覆盖子串的问题,与此题不同的是,窗口的大小是变化的。