给定一个数组,求其最长摇摆子数组的长度。
摇摆数组:数组的元素关系按照递增、递减、递增、递减...规律变化的数组,如[1,3,2,5,4]。
数组的摇摆子数组:删除某些元素后,剩下的元素按照原来的顺序组成摇摆数组。如数组[1,17,5,10,13,15,10,5,16,8],删除部分元素后得到的其中一个最长摇摆子数组为[1,17,10,13,10,16,8],其长度为7。
方法一:对每一个元素,找出把其当做较小的元素和较大的元素时,摇摆子数组的最长长度。这种方法需要两层遍历,时间复杂度为O(n^2)。
public int wiggleMaxLength(int[] nums) {
int[] l1 = new int[nums.length]; // as positive
int[] l2 = new int[nums.length]; //as negative
l1[0] = 1; l2[0] = 1;
int maxLength = 1;
for(int i = 1; i < nums.length; i++) {
int max = 0;
for(int j = i - 1; j >= 0; j--) {
if(nums[j] < nums[i] && l2[j] > max) { //i is positive
max = l2[j];
}
}
l1[i] = Math.max(1, max + 1);
max = 0;
for(int j = i - 1; j >= 0; j--) {
if(nums[j] > nums[i] && l1[j] > max) { //i is positive
max = l1[j];
}
}
l2[i] = Math.max(1, max + 1);
maxLength = Math.max(maxLength, Math.max(l1[i], l2[i]));
}
return maxLength;
}
方法二:对于每一个元素,如果下一步需要的是较小的元素,那么如果下一个元素比当前元素小,则考虑下一个元素,并开始寻找较大的元素;如果下一个元素比当前元素大,则把下一个元素替代当前元素(因为n[i+1] > n[i],寻找较小元素会比较容易)。该方法只需要一次遍历,时间复杂度为O(n)。
public int wiggleMaxLength(int[] nums) {
if (nums.length == 0 || nums.length == 1) {
return nums.length;
}
int k = 0;
while (k < nums.length - 1 && nums[k] == nums[k + 1]) { //Skips all the same numbers from series beginning eg 5, 5, 5, 1
k++;
}
if (k == nums.length - 1) {
return 1;
}
int result = 2; // This will track the result of result array
boolean smallReq = nums[k] < nums[k + 1]; //To check series starting pattern
for (int i = k + 1; i < nums.length - 1; i++) {
if (smallReq && nums[i + 1] < nums[i]) {
nums[result] = nums[i + 1];
result++;
smallReq = !smallReq; //Toggle the requirement from small to big number
} else {
if (!smallReq && nums[i + 1] > nums[i]) {
nums[result] = nums[i + 1];
result++;
smallReq = !smallReq; //Toggle the requirement from big to small number
}
}
}
return result;
}