題目描述:
在一個長度爲 n 的數組裏的所有數字都在 0 到 n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字是重複的,也不知道每個數字重複幾次。請找出數組中任意一個重複的數字。
要求:時間複雜度 O(N),空間複雜度 O(1)
Input:
{2, 3, 1, 0, 2, 5}
Output:
2
解題思路:
題目要求空間複雜度 O(1),因此不能使用排序的方法,不能使用HashSet,也不能使用額外的標記數組。
對於這種數組元素在 [0, n-1] 範圍內的問題,可以將值爲 i 的元素調整到第 i 個位置上進行求解,即哈希表的方式。具體過程如下圖(圖片來源於https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/%E5%89%91%E6%8C%87%20offer%20%E9%A2%98%E8%A7%A3.md該作者整理了java開發所需的筆記,強烈推薦,比看書快!):
由於比較簡單,直接貼代碼
public class Question3 {
private static int deduplicate(int a[]) {
if (a.length < 2 || a == null) {
return -1;
}
// 判斷不合格的數
for (int i = 0; i < a.length; i++) {
if (a[i] < 0 || a[i] > a.length - 1) {
return -2;
}
}
// 找重複的數
for (int i = 0; i < a.length; i++) {
while (a[i] != i) {
//如果這個位置上的數等於它hash位置上數,就重複
if (a[i]==a[a[i]]) {
return a[i];
}
swap(a, i, a[i]);
}
}
return -1;
}
public static void swap(int a[], int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int[] a = { 2, 3, 1, 0, 2, 5, 3 };
System.out.println(deduplicate(a));
}
}