找出數組中的重復元素


出自劍指offer,題目如下。

我給出了兩個解法以及官方解法,如下所示。

  1 package com.jeaven;
  2 
  3 /*
  4 * 劍指offer_problem3: 找到數組中的重復元素
  5 * */
  6 public class Problem3 {
  7     /*
  8     * 測試
  9     * */
 10     public static void main(String[] args) {
 11         //測試數組
 12         int[] testArray = {4,3,5,2,5,3};
 13         //解法一
 14         Solution1 s1 = new Solution1();
 15         long startTime = System.nanoTime();
 16         s1.solve(testArray);
 17         long endTime = System.nanoTime();
 18         long spendTime1 = endTime - startTime;
 19         //解法二
 20         Solution2 s2 = new Solution2();
 21         startTime = System.nanoTime();
 22         s2.solve(testArray);
 23         endTime = System.nanoTime();
 24         long spendTime2 = endTime - startTime;
 25         //解法三
 26         int[] testArray1 = {4,3,5,2,5,3};
 27         Solution3 s3 = new Solution3();
 28         startTime = System.nanoTime();
 29         s3.solve(testArray1);
 30         endTime = System.nanoTime();
 31         long spendTime3 = endTime - startTime;
 32         //比較程序運行效率
 33         System.out.println("solution1 spends time: " + spendTime1 + " ns");
 34         System.out.println("solution2 spends time: " + spendTime2 + " ns");
 35         System.out.println("solution3 spends time: " + spendTime3 + " ns");
 36     }
 37 }
 38 
 39 
 40 /*
 41  * 解法一:選定某個元素,查找數組中剩下元素有沒有重復的元素
 42  * 時間復雜度為O(n^2)
 43  * */
 44 class Solution1 {
 45     public boolean solve(int[] arr) {
 46         for(int i = 0; i < arr.length; i++) {
 47             int curr = i;
 48             for(int j = 0; j < arr.length; j++) {
 49                 if(arr[j] == arr[i] && i != j) {
 50                     System.out.println("solution1: " + arr[i]);
 51                     return true;
 52                 }
 53             }
 54 
 55         }
 56         return false;
 57     }
 58 }
 59 
 60 
 61 /*
 62  * 那么優化一下
 63  * 解法二:先排序,遍歷數組,查看相鄰元素是否重復
 64  * 使用O(n)的快速排序,總的時間復雜度則為O(nlgn)
 65  * */
 66 class Solution2 {
 67     public boolean solve(int[] arr) {
 68         //使用快速排序
 69         quickSort(arr, 0, arr.length - 1);
 70         int temp = 0;
 71         for(int i = 1; i < arr.length; i++) {
 72             if(arr[temp] == arr[i]) {
 73                 System.out.println("solution2: " + arr[i]);
 74                 return true;
 75             } else {
 76                 temp = i;
 77             }
 78         }
 79         return false;
 80     }
 81 
 82     //快速排序partition函數
 83     private int partition(int[] arr, int start, int end) {
 84         //選數組第一個元素為排序基准
 85         int k = start;
 86         int p = start;
 87         for(int q = p + 1; q <= end; q++) {
 88             if(arr[q] < arr[k]) {
 89                 p = p + 1;
 90                 int temp = arr[p];
 91                 arr[p] = arr[q];
 92                 arr[q] = temp;
 93             }
 94         }
 95 
 96         int temp = arr[p];
 97         arr[p] = arr[start];
 98         arr[start] = temp;
 99         return p+1;
100     }
101 
102     //快速排序
103     private void quickSort(int[] arr, int start, int end) {
104         if(start < end) {
105             int k = partition(arr, start, end);
106             quickSort(arr, start, k-1);
107             quickSort(arr, k+1, end);
108         }
109     }
110 
111 }
112 
113 
114 /*官方解法: 遍歷數組,比較數組的下標和對應元素是否相等,如果不相等交換arr[i]和arr[arr[i]],相等則找到重復數字*/
115 class Solution3 {
116     public boolean solve(int[] arr) {
117         for(int i = 0; i < arr.length; i++) {
118             while(arr[i] != i) {
119                 if(arr[i] != arr[arr[i]]) {
120                     int temp = arr[i];
121                     arr[i] = arr[temp];
122                     arr[temp] = temp;
123                 } else {
124                     System.out.println("solution3: " + arr[i]);
125                     return true;
126                 }
127             }
128         }
129         return false;
130     }
131 }

我比較了三種方法的程序運行時間,如下圖所示。顯然第三種解法更好點,但是限制於題目的要求,對數組元素的范圍有要求。先排序再查找的方法適合任意數組。

 

順便一提,在寫快排的時候得格外小心,我沒有一次寫對,還調試了一會,需要注意快排的細節,下圖是快排的算法邏輯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM