最长震荡子数组:
给定一个数组,如果连续两次递增(或递减)后再两次递减(或递增),允许最开始的时候只有一次递增(或递减),允许最后的时候只有一次递增(或递减)**
解答:
通过设置状态来记录之前的情况。可以分为一下几种情况是合理的:
前前状态 前状态 当前状态
1 NULL NULL INCR/DECR
2 NULL INCR/DECR INCR/DECR
3 INCR INCR DECR
4 INCR DECR DECR
5 DECR DECR INCR
6 DECR INCR INCR
定义枚举用于表示这几种状态:
private static enum Trend {
INCR(1),
DECR(-1),
EQUAL(0),
NULL(0),
;
public final int score;
Trend(int score){
this.score = score;
}
}定义一个函数用于计算当前下标对应的状态:
private static Trend calculateTrend(int[] input, int i) {
if(i == 0){
return Trend.NULL;
}
int pre = input[i - 1];
int current = input[i];
if(current == pre) {
return Trend.EQUAL;
}
if(current > pre) {
return Trend.INCR;
} else {
return Trend.DECR;
}
}判断当前状态是否合理:
private static boolean canContinue(Trend[] history, Trend current){
if(current == Trend.EQUAL){
// 不能与后面连起来了,需要中断计数
return false;
}
if(history[0] == Trend.NULL){
if(history[1] == Trend.NULL){
return true;
}
// 必須連續
return history[1] == current;
}
if(history[0] == history[1]){
return current != history[1];
}
return current == history[1];
}生成历史状态,即把状态逐一推进:
private static void regenHistoryTrend(Trend[] historyTrend, Trend currentTrend) {
// 已经连续两个了,只按照时间,推进
historyTrend[0] = historyTrend[1];
historyTrend[1] = currentTrend;
}主函数:
public class T2 {
public static void main(String[] args) {
int[] input = new int[]{1, 2, 3, 2, 1};
int maxLength = 0;
for (int i = 0; i < input.length; i++) {
//以下标i为子数组起点,起始的前两个状态为NULL,NULL
Trend[] historyTrend = new Trend[]{Trend.NULL, Trend.NULL};
int score = 0;
int j = i;
//从下标i开始遍历数组,用下标j来表示当前的位置
for (; j < input.length; j++) {
//计算出下标j所在的状态
Trend currentTrend = calculateTrend(input, j);
if(j == i){
currentTrend = Trend.NULL;
}
score += currentTrend.score;
// 如果当前状态不符合或者score>2或者score<-2,就退出循环
if(!canContinue(historyTrend, currentTrend) || score > 2 || score < -2){
// 不算本次
j --;
break;
}
regenHistoryTrend(historyTrend, currentTrend);
}
int currentLength = j - i;
if(currentLength >= 5 && currentLength > maxLength){
maxLength = currentLength;
}
}
System.out.println(maxLength);
}
}
京公网安备 11010502036488号