题目详情
【问题描述】
给定一个长度为 N 的整数序列:A1, A2, · · · , AN。现在你有一次机会,
将其 中连续的 K 个数修改成任意一个相同值。请你计算如何修改可以
使修改后的数 列的最长不下降子序列最长,请输出这个最长的长度。
最长不下降子序列是指序列中的一个子序列,子序列中的每个数不小于在它之前的数。
【输入格式】
输入第一行包含两个整数 N 和 K。
第二行包含 N 个整数 A1, A2, · · · , AN。
【样例输入】
5 1
1 4 2 8 5
【样例输出】
4
解题思路
因本人比较菜,动态规划有点玩不明白,所以在此出了一种不需要动态规划,也不要需要找状态转移方程的方法
首先我们要定义两个int类型的变量,用来存放N和K
static int n,k;
接下来定义两个数组,一个为int型,一个为Boolean型,作用介绍在代码里:
static int[] arr;//用来存放所输入的数字
static boolean[] c;//用来判断所输入的数组两个值之间的递增关系;是了为true;否之为false
我们变量命名好之后,接着就该给变量赋值,这里我要引用到java.until.Scanner包(及从键盘获取输入的一个包)复制代码如下:
Scanner scan = new Scanner(System.in);
n=scan.nextInt();//获取样例输入的第一行
k=scan.nextInt();//n,k分别为数组的长度和我们所需要调整的数字个数
for (int i = 0; i < n; i++) {
arr[i]= scan.nextInt();
}//从键盘获取输入样例的第二行
我们引入数值后,就可以给我们的Boolean数组赋值,代码如下
for (int i = 1; i < n; i++) {
if (arr[i]<arr[i-1]){//数组不为递增时
c[i]=false;
}else {
c[i]=true;//数组为递增时
}
}
这样我们Boolean类型的数组复制完毕了,接下来我们定义一个max变量用来计算我们的最大下降序列,代码如下:
int max = 0;
for (int i = 0; i < n; i++) {
if(k>0){//因为我们可以调整k个值,所以分为k>0和K=0两种情况
if (c[i]){//当c[i]为true的时候,说明序列为增,即max+1
max++;
}else{
k--;//当从c[i]为false的时候,说明序列为递减,既要调正这个数字,所以要k--是为了记录我们可调数字的个数
max++;//当我们调整过后,数列又为递增序列,所以max的值又要+1
}
}else if (k==0){//当k=0时;及我们没有办法再去调整递减的值
if (c[i]){//所以当c[i]为true的时候,我们把max的值+1即可
max++;
}else{//当c[i]为false的时候我们无法改变值,所以遍历结束
System.out.println(max);//输出所获得的不递减子序列
break;//结束循环
}
}
}
完整代码如下:
import java.util.Scanner;
public class Main {
static int N=1000000;//因为题目的最大测例为1000000;所以我们设置数组的大小为1000000
static int[] arr = new int[N];//存放初始值
static boolean[] c = new boolean[N];//用来判断序列是否上升
static long n,k;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
k = scan.nextInt();
c[0]=true;
for (int i = 0; i < n; i++) {
arr[i]= scan.nextInt();
}
for (int i = 1; i < n; i++) {
if (arr[i]<arr[i-1]){
c[i]=false;
}else {
c[i]=true;
}
}
int max = 0;
for (int i = 0; i < n; i++) {
if(k>0){
if (c[i]){
max++;
}else{
k--;
max++;
}
}else if (k==0){
if (c[i]){
max++;
}else{
System.out.println(max);
break;
}
}
}
}
}