此题为2017年今日头条春招研发岗笔试题。(思路为“今日头条校园”公众号提供的解法)
题目要求:求给定数列A中先升后降(必须是先升后降,只升不降或者只降不升都不符合条件;输入的数组不存在相邻两个数相等的情况)的最长连续子序列,要求O(n)
思路:预处理使得up[i]表示以A[i]为结尾的连续最长上升序列的长度、down[i]表示A[i]为起始的连续最长下降子序列的长度,那么答案实际上就是max { up[i] + down[i] - 1},更新答案时顺便记录最优区间即可。唯一的trick是up[i] > 1和down[i] > 1必须同时满足。
代码实现如下:
public class Solution {
public static void main(String[] args) {
int[] datas = {23,4324,21,34,14,3,2,2345,32};
int length = datas.length;
if(length <= 0){
return ;
}
int[] up = new int[length];
int[] down = new int[length];
up[0] = 1;
// 从前向后遍历datas,填充up数组
for(int i=1; i<length; i++){
if(datas[i] > datas[i-1]){
up[i] = up[i-1] + 1;
} else{
up[i] = 1;
}
}
// 从后向前遍历datas,填充down数组
down[length-1] = 1;
for(int i=length-2; i>=0; i--){
if(datas[i] > datas[i+1]){
down[i] = down[i+1] + 1;
} else {
down[i] = 1;
}
}
System.out.print("Up数组如下:");
for(int i=0; i<length; i++){
System.out.print(up[i] + " ");
}
System.out.println();
System.out.print("Down数组如下:");
for(int i=0; i<length; i++){
System.out.print(down[i] + " ");
}
System.out.println();
int begin = 0;
int end = 0;
int maxWidth = 0;
int tempWidth = 0;
for(int i=0; i<length; i++){
if(up[i] > 1 && down[i] > 1){
tempWidth = (up[i] + down[i] - 1);
if(tempWidth > maxWidth){
// 更新最宽尖峰的宽度
maxWidth = tempWidth;
// 同时更新起始位置
begin = i - up[i] + 1;
end = i + down[i] - 1;
}
}
}
System.out.println("最大宽度为:" + maxWidth + " 起始位置:" + begin + " 结束位置:" + end);
}
}