华为OD机考算法题:补种未成活胡杨

目录

题目部分

解读与分析

代码实现


题目部分

题目 补种未成活胡杨
难度
题目说明 近些年来,我国防沙治沙取得显著成果。某沙漠新种植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);
}

(完)

猜你喜欢

转载自blog.csdn.net/ZiJinShi/article/details/132876388