目录
题目部分
题目 | 补种未成活胡杨 |
难度 | 易 |
题目说明 | 近些年来,我国防沙治沙取得显著成果。某沙漠新种植N棵胡杨(编号1-N),排成一排。一个月后,有M棵胡杨未能成活(会给出未成活胡杨的编号)。现可补种胡杨K棵,可能有1到多种补种方式。请求出在这些补种方式中,能够得到的最多连续胡杨棵树。 |
输入描述 | N 总种植数量 M 未成活胡杨数量 M 个空格分隔的数,按编号从小到大排列 K 最多可以补种的数量 其中: 1<=N<=100000 1<=M<=N 0<=K<=M |
输出描述 | 最多的连续胡杨棵树。 |
补充说明 | 无 |
------------------------------------------------------ | |
示例 | |
示例1 | |
输入 | 5 2 2 4 1 |
输出 | 3 |
说明 | 补种到 2 或 4 结果一样,最多的连续胡杨棵树都是 3。 |
示例2 | |
输入 | 10 3 2 4 7 1 |
输出 | 6 |
说明 | 补种第7棵树,最多的连续胡杨棵树为6,即(5,6,7,8,9,10)。 |
解读与分析
题目解读:
N 棵胡杨排成一排,编号分别为 1 到 N。其中,有 M 棵坏死,需要补种 K 棵 ( 0 <= K <= N )。
当补种后,且有最多的胡杨树是连续的时候,必定要保证补种的这 K 棵树包含在连续的序列中,否则,不连续的补种就会造成浪费。为什么有这个结论呢?
用反证法,假设补种的至少有 1 棵胡杨没有包含在最大的连续序列中,那么把这棵胡杨换到最大的连续序列比邻的位置,最大的连续序列就会变得更大,那么原先所谓的“最大的连续序列”就不是最大的。所以,当补种后,连续的胡杨树最大时,补种的这 K 棵一定包含在连续的序列中。
那么,这就意味着,在坏掉的 M 棵树对应的编号数组中,补种的 K 棵树编号一定是 M 棵树数组中相邻的 K 个元素。
分析与思路:
刚才提到,在坏掉的 M 棵树对应的编号数组中,补种的 K 棵树编号一定是 M 棵树数组中相邻的 K 个元素。
假设坏掉的 M 棵树的编号放在数组 badTree 中,那么,补种的 K 棵树的编号可能为 badTree 的第 0 到 ( K - 1 ),或 1 到 K …… 或 ( M - K + 1 ) 到 M。
在实现算法时,我们可以先尝试 K 棵树是 badTree[0] 到 badTree[ K - 1],计算连续的棵树;然后往右移动一个,计算补种 badTree[ 1 ] 到 badTree[ K ] 时,连续的棵树,直到遍历完 badTree。
最终,找出连续最大的那一组,即为最终结果。
此算法只需要遍历 1 次数组,更具体一点,计算 (M - K + 1)次。时间复杂度为 O(n),空间复杂度为 O(n)。
代码实现
Java代码
import java.util.Scanner;
public class PlantTree {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String input = sc.nextLine();
int count = Integer.parseInt( input );
// badCount可以忽略,它等于badTreeStr.length
input = sc.nextLine();
int badCount = Integer.parseInt( input );
input = sc.nextLine();
String[] badTreeStr = input.split( " " );
input = sc.nextLine();
int k = Integer.parseInt( input );
processPlantTree( count, badTreeStr, k );
}
}
private static void processPlantTree( int count, String[] badTreeStr, int k )
{
int[] badTree = new int[badTreeStr.length];
for( int i = 0; i < badTree.length; i ++ )
{
badTree[i] = Integer.parseInt( badTreeStr[i] );
}
int maxLength = 0;
for( int i = 0; i < badTree.length - k + 1; i ++ )
{
int leftIncluded = 1; // i = 0;
if( i != 0 )
{
leftIncluded = badTree[ i - 1 ] + 1;
}
int rightExcluded = count + 1; // i = badTree.length
if( i + k != badTree.length )
{
rightExcluded = badTree[ i + k ];
}
int length = rightExcluded - leftIncluded;
if( length > maxLength )
{
maxLength = length;
}
}
System.out.println( maxLength );
}
}
JavaScript代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
while (line = await readline()) {
var count = parseInt(line);
// count 可以忽略
line = await readline();
var badCount = parseInt(line);
line = await readline();
var badTreeStr = line.split(" ");
line = await readline();
var k = parseInt(line);
processPlantTree(count, badTreeStr, k);
}
}();
function processPlantTree(count, badTreeStr, k) {
var badTree = new Array();
for (var i = 0; i < badTreeStr.length; i++) {
badTree[i] = parseInt(badTreeStr[i]);
}
var maxLength = 0;
for (var i = 0; i < badTree.length - k + 1; i++) {
var leftIncluded = 1; // i = 0;
if (i != 0) {
leftIncluded = badTree[i - 1] + 1;
}
var rightExcluded = count + 1; // i = badTree.length
if (i + k != badTree.length) {
rightExcluded = badTree[i + k];
}
var length = rightExcluded - leftIncluded;
if (length > maxLength) {
maxLength = length;
}
}
console.log(maxLength);
}
(完)