**陣列必須已排序**。此演算法利用有序特性,僅比較相鄰元素即可識別重複值,達到 O(n) 時間複雜度、O(1) 空間複雜度的原地去重。
public static void noDups(int[] arr) {
if (arr == null || arr.length <= 1) return;
int writeIndex = 0; // 寫入位置指標
for (int i = 0; i < arr.length - 1; i++) {
// 當前元素與下一個元素不同,保留當前元素
if (arr[i] != arr[i + 1]) {
arr[writeIndex++] = arr[i];
}
}
// 處理最後一個元素 (迴圈未比較到)
arr[writeIndex++] = arr[arr.length - 1];
// 截斷陣列 (Java 陣列長度固定,實際使用時需配合長度資訊)
// 實務上常回傳新長度,或轉為 List/新陣列
}
輸入陣列:[1, 1, 2, 2, 2, 3, 4, 4, 5]
| i | arr[i] | arr[i+1] | 比較結果 | 動作 | writeIndex | 陣列狀態 (前段) |
|---|---|---|---|---|---|---|
| 0 | 1 | 1 | 相等 | 略過 | 0 | [1, ...] |
| 1 | 1 | 2 | 不等 | 寫入 arr[0]=1 | 1 | [1, 1, ...] |
| 2 | 2 | 2 | 相等 | 略過 | 1 | [1, 1, ...] |
| 3 | 2 | 2 | 相等 | 略過 | 1 | [1, 1, ...] |
| 4 | 2 | 3 | 不等 | 寫入 arr[1]=2 | 2 | [1, 2, 2, ...] |
| 5 | 3 | 4 | 不等 | 寫入 arr[2]=3 | 3 | [1, 2, 3, 3, ...] |
| 6 | 4 | 4 | 相等 | 略過 | 3 | [1, 2, 3, 3, ...] |
| 7 | 4 | 5 | 不等 | 寫入 arr[3]=4 | 4 | [1, 2, 3, 4, 4, ...] |
| - | - | - | - | 寫入最後元素 5 | 5 | [1, 2, 3, 4, 5] |
public class ArrayDeduplication {
// 回傳去重後的有效長度
public static int noDups(int[] arr) {
if (arr == null || arr.length <= 1) return arr.length;
int writeIndex = 0;
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] != arr[i + 1]) {
arr[writeIndex++] = arr[i];
}
}
arr[writeIndex++] = arr[arr.length - 1];
return writeIndex;
}
public static void main(String[] args) {
int[] sortedArray = {1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 6};
int newLength = noDups(sortedArray);
System.out.print("去重結果: ");
for (int i = 0; i < newLength; i++) {
System.out.print(sortedArray[i] + " ");
}
// 輸出: 1 2 3 4 5 6
}
}
若陣列未排序,常見方案:
// 保持順序去重 (未排序陣列)
public static int[] deduplicateUnsorted(int[] arr) {
return Arrays.stream(arr)
.boxed()
.collect(Collectors.toCollection(LinkedHashSet::new))
.stream()
.mapToInt(Integer::intValue)
.toArray();
}
noDups 是**有序陣列去重的最優解**,體現「有序性」這一關鍵資訊的算法價值。面試常考察:辨識前提條件、雙指標技巧、邊界處理 (最後一個元素)。