判斷陣列中是否存在重複值是經典面試題。本文以 int[] 為例,先展示最直觀的雙重迴圈暴力解法,再引導至集合、排序、位圖等高效能替代方案。
int[] arr = {1,10,5,8,11,100,99,10};
boolean flag = false;
for (int i = 0; i < arr.length; i++) {
int count = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[i] == arr[j]) count++;
}
if (count >= 2) { flag = true; break; } // 含自我比較故 >=2
}
System.out.println(flag ? "有重複值" : "無重複值");
缺點:時間複雜度 O(n²),資料量大時極慢;且未標記重複值具體是哪個。
| 方法 | 時間複雜度 | 空間複雜度 | 適用場景 |
|---|---|---|---|
| HashSet 去重 | O(n) | O(n) | 通用、最推薦,set.size() != arr.length 即可判斷 |
| 先排序後相鄰比較 | O(n log n) | O(1) 或 O(log n) | 不可改動原陣列時拷貝排序,或記憶體極受限 |
| 位圖/布林陣列 | O(n) | O(k) | 數值範圍已知且較小(如 0~100萬),極省記憶體 |
| Stream API | O(n) | O(n) | Java 8+ 單行式:Arrays.stream(arr).distinct().count() != arr.length |
public static boolean hasDuplicate(int[] arr) {
if (arr == null || arr.length <= 1) return false;
Set<Integer> seen = new HashSet<>(arr.length * 2);
for (int v : arr) {
if (!seen.add(v)) return true; // add 回傳 false 表示已存在
}
return false;
}
// 取得所有重複值
public static Set<Integer> findDuplicates(int[] arr) {
Set<Integer> seen = new HashSet<>(), dup = new HashSet<>();
for (int v : arr) if (!seen.add(v)) dup.add(v);
return dup;
}
HashSet.add 回傳 boolean 可直接判重。Integer 快取範圍(-128~127)對自動裝箱效能的影響。