题目:牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
简述:在长度为n的数组中找到一个连续子序列,该连续子序列满足最多只改变一个数,就可以使其成为一个严格上升的连续子序列,返回该连续子序列的最长长度
思路:可以分别计算数组中每个元素在该位置的正序和逆序的连续子序列长度,然后遍历数组,当前位置的 ans_1 = 正序子序列长度+逆序子序列长度-1(当前位置重复计算),为当前位置到断点的最大子序列长度,若当前位置的后一个元素与前一个元素的差值大于2,则当前位置有成为断点的“潜力”,则计算前一个元素的 ans_2 = 正序子序列长度+后一个元素的逆序子序列长度+1(当前位置加入计算)。最后,比较ans, ans_1和ans_2的大小,返回最终值。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums = new int[n+2]; // n+2设置数组两头的边界,idx=0为最小值,idx=n+1为最大值
nums[0] = Integer.MIN_VALUE; // 设置左边界
for(int i = 1; i <= n; i++){
nums[i] = in.nextInt();
}
nums[n+1] = Integer.MAX_VALUE; //设置右边界
int[][] dp = new int[n+2][2];
int key = 1;
while(key <= n){
// 正序当前位置连续序列长度,遇到断点重置长度为1
dp[key][0] = nums[key] > nums[key-1] ? 1+dp[key-1][0] : 1;
// 逆序当前位置连续序列长度
dp[n-key+1][1] = nums[n-key+1] < nums[n-key+2] ? 1+dp[n-key+2][1] : 1;
key++;
}
int ans = -1;
for(int i = 1; i <= n; i++){
// 若当前位置不是断点,则有最大子序列长度,-1是由于当前位置重复计算
ans = Math.max(ans, dp[i][0] + dp[i][1] - 1);
if(nums[i+1] - nums[i-1] > 1){
// 当前位置可以成为断点,计算最大子序列长度,+1是由于当前位置没被计算,只计算了当前位置的前后元素的子序列长度的总和,所以需要加上当前位置(断点)。
ans = Math.max(ans, dp[i-1][0] + dp[i+1][1] + 1);
}
}
System.out.println(ans);
}
}
标签:动态规划
代码参考:运行ID:62159990