最長的可整合子陣列的長度
阿新 • • 發佈:2019-12-31
題目描述
先給出可整合陣列的定義:如果一個陣列在排序之後,每相鄰兩個數的絕對值都為1,或者該陣列長度為1,則該陣列為可整合陣列。例如[5,3,4,6,2]排序後為[2,5,6],符合每相鄰兩個數差的絕對值都為1,所以這個陣列為可整合陣列。給定一個陣列arr,請返回其中最大可整合子陣列的長度。例如[5,2,3]的最大可整合子陣列為[5,4],所以請返回5
[要求]時間複雜度為O(n^2),空間複雜度為O(n)
輸入示例
7
5 5 3 2 6 4 3
輸出
5
複製程式碼
解題思路分析
- 首先本題題意描述可整合陣列的定義得清晰,而且題目也給了提示了,其實得先給陣列進行排序
- 使用快排排完序之後呢,我們就要考慮如何在排序陣列中給找出最長的可整合子陣列的長度,這裡可以使用雙指標法進行查詢(程式碼中有了詳細介紹了)
程式碼實現
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.valueOf(scanner.nextLine());
int[] nums = new int[n];
String[] lines = scanner.nextLine().split(" ");
for (int i = 0; i < n; i++) {
nums[i] = Integer.valueOf(lines[i]);
}
quickSort(nums,0 ,n - 1);
System.out.println(getAns(nums,n));
}
//快排
private static void quickSort(int[] nums,int left,int right) {
int base = nums[left],i = left,j = right;
while (i < j) {
while (nums[j] >= base && i < j) {
j--;
}
if (i < j) {
nums[i] = nums[j];
i++;
while (nums[i] <= base && i < j) {
i++;
}
if (i < j) {
nums[j] = nums[i];
j--;
}
}
}
nums[i] = base;
if (left < (i - 1)) {
quickSort(nums,left,i - 1);
}
if ((j + 1) < right) {
quickSort(nums,j + 1,right);
}
}
private static int getAns(int[] nums,int n) {
/**
* 初始長度肯定為 1 ,因為最長子整合陣列中至少會有一個元素,然後定義兩個下標 i 為前面這個下標,j 為後面這個下標
*/
int length = 1,i = 0,j = 1;
while (i < n && j < n) {//停止條件為 i 和 j 都不越界
if (j < n - 1) {//首先得判斷 j 是否到了陣列的最後一個位置,在這裡判斷是為了後面不會丟擲越界異常
if (nums[j] == nums[j + 1]) {//如果 j 與 j 後面這個數字相等時,就可以直接將 j 定位到後面這個數字,此時 i 不變
j++;
} else if (nums[i] == (nums[j] - 1)) {// 當前 i 和 j 指向的數字符合題目要求
length++;//長度 +1
j++;// j 後移一位
i = j - 1;//注意這裡需要始終保證 i 和 j 相鄰
} else {// 當前 j 和 i 指向的數字不符合題目要求
j++;// j 後移一位
i = j - 1;//注意這裡需要始終保證 i 和 j 相鄰
}
} else {// j 指向了最後一個數字
if (nums[i] == (nums[j] - 1)) {//如果此時符合要求
length++;//長度 +1
j++;// j 後移一位
i = j - 1;//注意這裡需要始終保證 i 和 j 相鄰
} else {//不符合要求
j++;// j 後移一位
i = j - 1;//注意這裡需要始終保證 i 和 j 相鄰
}
}
}
return length;
}
複製程式碼