剑指offer——数组中重复的数字

/**
* 题目:在一个长度为n的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
* 请找出数组中任意一个重复的数字。
* 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
* 那么对应的输出是重复的数字 2 或者 3。
*
* 【法1】:一言不合先排序,排序之后双指针往后跑,直到找到相同的数字,return
* 时间复杂度:O(N*logN)+ O(N)
* 【法2】:用HashMap,遍历一下数组即可
* 时间复杂度:O(N)+ N*O(1)
* 空间复杂度:O(N)
* 【法3】:依照题意,数组中的数字都在[0,n-1]的范围内,
* 所以如果没有重复数字的话,每个数字就应该都在他对应的下标下面
* 但是有重复的数字,数字还不是有序的:
* 我们可以依次遍历整个数组,当遍历到第i个数字时,
* arr[i] == i, i++
* while(arr[i] != i){ //直到i这个位置插上了i,或者找到了一对重复的数字
* arr[arr[i]] == arr[i], 找到了重复的数字
* arr[arr[i]] != i, swap(arr[arr[i]], arr[i])
* }
*
* 时间复杂度:O(N),数组中的每个元素只需遍历或交换一遍,即可找到那个重复的数字
* 空间复杂度:O(1)
*
*/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class 数组中重复的数字 {
    public static int rep(int[] arr) {
        if(arr.length == 0 || arr == null) {
            return 0;
        }
        for(int i = 0;i < arr.length;i++) {
            while(arr[i] != i ) {
                if(arr[arr[i]] == arr[i]) {                
                    return arr[i];
                }else {
                    ch(arr,i,arr[i]);
                }
            }
        }
        return -1;     
    }

    private static void ch(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;     
    }

    public static void main(String[] args) {
        int[] arr = {2,3,1,0,2,5,3};
        System.out.println(rep(arr));

    }

}
0 条评论
发表一条评论