【題3陣列中重複的數字】
【題3陣列中重複的數字】
【題目1】
在一個長度為n的數組裡的所有數字都在0-n-1的範圍內,陣列中某些數字是重複的,但不知道每個數字重複了幾次,請找出陣列中任意一個重複的數字,例如,如果輸入長度為7的陣列,{2,3,1,0,2,5,3},那麼對應的輸出是2或者3
【方法】
1.
(1)先把輸入陣列排序
(2)從頭到尾掃描排序後的陣列
(3)排一個長度為n的陣列需要O(nlogn)
2雜湊表
(1) 從頭到尾按順序掃描陣列的每個數字
(2) 每掃描一個用O(1)時間判斷雜湊表裡是否已經包含該數字
(3) 若包含則一個重複數字,若不包含則插入到雜湊表
3數字都在0~n-1範圍內排序之後,i將對應下標i的位置
重排陣列
(1)掃描到下標i的數字時,比較這個數字(m)是否=i
(2)若等於,掃描下一個。不等則與第m個數字比較
(3)如果與第m個數字相等,則 有一個重複數字
(4)把第i個數字與第m個數字交換,把m放到屬於他的位置
實現
package ti3; /** * * 題目:在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。陣列中某些數字是重複的,但不知道有幾個數字重複了, * 也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。例如,如果輸入長度為7的陣列{2, 3, 1, 0, 2, 5, 3}, * 那麼對應的輸出是重複的數字2或者3。 * test1:陣列輸入無效! test2:陣列中無重複數字! test3:數字大小超出範圍! test4:重複數字為:2 */ public class FindDuplication { /** * 找到陣列中一個重複的數字 * 返回-1代表無重複數字或者輸入無效 */ public int getDuplicate(int[] arr){ if(arr == null || arr.length <= 0){ System.out.println("陣列輸入無效"); return -1; } for(int a:arr){ if(a < 0 || a > arr.length - 1){ System.out.println("數字大小超出範圍"); return -1; } } for(int i = 0;i < arr.length;i++){ int temp; while(arr[i] != i){ if(arr[arr[i]] == arr[i]){ return arr[i]; } //交換arr[arr[i]]和arr[i] temp = arr[i]; arr[i] = arr[temp]; arr[temp] = temp; } } System.out.println("陣列中無重複的數字"); return -1; } //測試程式碼 //陣列為null public void test1() { System.out.println("test1"); int[] a = null; int dup = getDuplicate(a); if(dup >= 0){ System.out.println("重複數字為"+dup); } } //陣列無重複數字 public void test2() { System.out.println("test2"); int[] a = {0,1,2,3}; int dup = getDuplicate(a); if(dup >= 0){ System.out.println("重複數字為"+dup); } } //陣列數字越界 public void test3() { System.out.println("test3"); int[] a = {1,2,3,4}; int dup = getDuplicate(a); if(dup >= 0){ System.out.println("重複數字為"+dup); } } //重複數字為2 public void test4() { System.out.println("test4"); int[] a = {1,2,3,2,4}; int dup = getDuplicate(a); if(dup >= 0){ System.out.println("重複數字為"+dup); } } public static void main(String[] args) { FindDuplication f = new FindDuplication(); f.test1(); f.test2(); f.test3(); f.test4(); } }
【題目2不修改陣列找出重複的數字】
在一個長度尾n+1的數組裡的所有數字都在1~n的範圍內,所有陣列中至少有一個數字時重複的。請找出陣列中任意一個重複的數字,但不能修改輸入的陣列。例如,輸入長度為8的陣列{2,3,5,4,3,2,6},那麼對應 的輸出是重複的數字2或3
注意:不能修改原陣列
方法:
1.
(1)建立一個長度為n+1的輔助陣列,逐一把原陣列的每個數字複製到輔助陣列
(2)若原陣列中被複制的數字為m,則複製到輔助陣列下標為m的位置
2.
(1)把從1~n數字從 中間的數字m分為2部分,1-m,m+1~n
(2)如果1~m數字的數目超過了m則這個一半包含重複的數字
否則,另一半m+1~n區間裡一定包含重複的數字
(3)繼續一分為二
實現
package ti3;
public class DuplicationInArrayNotEdit {
private int countRange(int[] array,int length,int start,int end){
if(start < 0 ||end > length-1)throw new IllegalArgumentException("Wrong Arguments");
int count = 0;
for(int i = 0;i<length;++i){
if(array[i]<=end && array[i]>= start)++count;
}
return count;
}
public int returnOneDuplication(int[] array){
if(array == null) throw new IllegalArgumentException("Wrong Arguments");
int length = array.length;
int start = 1;
int end = length - 1;
while(start <= end){
int middle = ((end-start)>>1)+start;
int count = countRange(array,length,start,middle);
if(start == end){
if(count >1)return start;
else break;
}
if(count>middle - start+1)end = middle;
else start = middle +1;//注意這個+1
}
return -1;
}
public static void main(String[] args) {
DuplicationInArrayNotEdit duplicationInArrayNotEdit = new DuplicationInArrayNotEdit();
int[] Array = new int[] {2,3,5,4,3,2,6,7};
System.out.println(duplicationInArrayNotEdit.returnOneDuplication(Array));
}
}
參考:
1.《劍指offer》
2.https://www.cnblogs.com/yongh/p/9318604.html
3.https://blog.csdn.net/w13261711130/article/details/79973502