算法演练一:数组中重复的数字

题目:在一个长度为n的数组里的全部数字都在0~n-1的范围内,找出对应重复的数字。例如输入长度为7的数组int[] m ={2,3,1,0,2,5,3},则重复的数字为2和3。java

解法一:使用快排,排序后再去作比较找重复的数字,这个方法的时间复杂度为O(nlogn),这是最多见的方法,可是不是最快的办法。数组

解法二:这里有个重点,就是n属于[0, n-1],也就是说若是没有重复的数字,那么下标i和m[i]是相等的,这个很好理解吧。那么让咱们重排数组,从头至尾扫描这个数组,过程以下:bash

  • 1.当扫描到下标i的数字m[i],把i和m[i]做比较,若是相等,则扫描下一个,不然进入第二步。
  • 2.将m[i]和第m[i]个数字进行比较,若是相等,这就是一个重复的数字,扫描下一个数字。不然进入第三步。
  • 3.将m[i]和第m[i]进行交换,继续仅从头开始新的一轮扫描,直到结束。

上面的过程实质上就是比较交换的过程。ui

这里给出java版本的代码,以下:spa

public class Main {

    static int[] a = {2, 3, 1, 0, 2, 5, 3};

    public static void main(String[] args){
        duplicate(a);
    }

    private static void duplicate(int[] numbers) {
        if (numbers == null || numbers.length == 0) return;
        for (int i = 0; i < numbers.length; i++){
            while (numbers[i] != i){//第一步
                if (numbers[i] == numbers[numbers[i]]){//第二步
                    System.out.println("重复的数字-----> " + numbers[i]);
                    break;
                }
                //第三步
                int tmp = numbers[i];
                numbers[i] = numbers[tmp];
                numbers[tmp] = tmp;
            }
        }
    }
}
复制代码

代码中尽管有两重循环,可是最多进行了2次交换就找到了它的位置,所以总的时间复杂度为O(n),全部的操做都在同一个数组上,没有额外的分配内存空间,空间复杂度为O(1);code

相关文章
相关标签/搜索