尋找陣列中重複的數字
阿新 • • 發佈:2018-11-21
引言
原題來自劍指offer第二版面試題三
題目:
在一個長度為n的數組裡的所有數字都在0~n-1範圍內。陣列中某些數字是重複的。但是不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應輸出的是重複的數字2或者3。
java程式碼實現如下:
/** * @author FengTianHao * @version 1.0 * @since 2018/11/20 9:08 */ import com.sun.istack.internal.localization.NullLocalizable; /** 找出陣列中重複的數字--最優演算法 * 思路: * 從頭到尾依次掃描這個陣列中的每個數字當掃描到下標為i的數字時(比如a[i]),首先比較這個數字(用a[i]表示) * 等不等於i,如果(a[i]==i)接著掃描下一個數字;如果當前的數字(a[i])和下標i的值不相等,則再比較a[i]和陣列中的下標 * 等於a[i]的數字,如果二者相等則找到重複值;如果不相等則對這兩個數進行互動。接下來重複這個比較 * 、交換的過程,直到我們發現一個重複的數字 */ public class Test{ private int a; public void setA(int a) { this.a=a; } public int getA() { return a; } public static boolean duplicate(int[] numbers,Test duplication) { /** * 判斷陣列是否為空 */ if(numbers.length==0) { return false; } /** * 判斷陣列內的資料是否符合題目要求 */ for(int i=0;i<numbers.length;i++) { if(numbers[i]<0||numbers[i]>numbers.length-1) { return false; } } /** * 核心演算法 */ for(int i=0;i<numbers.length;i++) while (numbers[i] != i) { if (numbers[i] == numbers[numbers[i]]) { duplication.setA(numbers[i]); return true; } int temp; temp = numbers[i]; numbers[i] = numbers[temp]; numbers[temp] = temp; } return false; } public static void main(String[] args) { Test dup=new Test(); int[] a=new int[]{2,3,1,0,2,5,3}; if(duplicate(a,dup)) { System.out.println("重複值為:"+dup.getA()); } else { System.out.println("該陣列無重複值"); } } } 演算法執行過程: 以{2,3,1,0,2,5,3}為例 陣列的第0個數字(從0開始計數,和陣列的下標保持一致)是2,與它的下標值不相等,於是它 和下標為2的1進行比較,不相等,因此將2和下標為2的1進行交換。交換後的陣列是{1,3,2,0,2,5,3}, 此時第0個數字1依舊和下標值不相等,於是將1和下標為1的3進行比較,不相等,因此將1和下標 為1的3進行交換,交換後的陣列為{3,1,2,0,2,5,3}。重複上述步驟繼續進行交換,交換後陣列 為{0,1,2,3,2,5,3},接下來掃描的是下標為4 的2,2和下標值不同,因此將2和下標為2的2進行 比較發現相同,則將2儲存,此時已經發現重複值,程式結束。
小結
程式碼中儘管有兩重迴圈,但是每個數字最多交換兩次就能找到屬於它的位置,因此總的時間複雜度為0(n).另外,所有的操作步驟都是在輸入陣列上進行的,不需要額外分配記憶體,因此空間複雜度為O(1);