找出数组中的重复元素

出自剑指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 }

我比较了三种方法的程序运行时间,如下图所示。显然第三种解法更好点,但是限制于题目的要求,对数组元素的范围有要求。先排序再查找的方法适合任意数组。

 

顺便一提,在写快排的时候得格外小心,我没有一次写对,还调试了一会,需要注意快排的细节,下图是快排的算法逻辑。

posted @ 2019-06-26 15:50  jeavenwong  阅读(5834)  评论(0编辑  收藏  举报