【剑指Offer】【数组】3_数组中重复的数字

题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

 

A1:因为数字有范围,所以可以把数字m放入下标为m的位置,若查找过程中发现num[m] == num[num[m]] 则存在重复数字    ====>  虽然有两重循环,但是每个数字最多只要交换两次即可,时间复杂度约等于O(n),但是要改变数组的结构

A2:创建长度为n+1的辅助数组,逐一把原数组的数字m复制到辅助数组的下标m处,当下标m处已有数字时,存在重复数字  ====>  时间复杂度O(n),空间复杂度O(n)

A3:从1~n的范围里只有n个数字,把1~n的数字从中间m数二分,若1~m的数字数目超过m,那么这一半的区间里一定包含重复数字  ====> 二分查找的思路,O(nlogn),不保证能找出所有重复的数字

 

//原数组上交换位置

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        if((numbers == nullptr) || (length <= 0))
        {
            return false;
        }
        for(int i = 0; i < length; i++)
        {
            if((numbers[i] < 0) || (numbers[i] > length - 1))
            {
                return false;
            }
        }
        for(int i = 0; i < length ;i++)
        {
            while(numbers[i] != i)
            {
                if(numbers[i] == numbers[numbers[i]])
                {
                    *duplication = numbers[i];
                    return true;
                }
                int tmp = numbers[i];
                numbers[i] = numbers[tmp];
                numbers[tmp] = tmp;
            }
        }
        return false;
    }
};

 

//辅助数组 

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        if((numbers == nullptr) || (length <= 0))
        {
            return false;
        }
        for(int i = 0; i < length; i++)
        {
            if((numbers[i] < 0) || (numbers[i] > length - 1))
            {
                return false;
            }
        }
        int tmp[100] = {-1};
        for(int i = 0; i < length; i++)
        {
            if(tmp[numbers[i]] == numbers[i])
            {
                *duplication = numbers[i];
                return true;
            }
            tmp[numbers[i]] = numbers[i];
        }
        return false;
    }
};

  

 

//二分思想

 太难了还不会写

 

 

 

相关题目:

  中位数(小M给你一个长度为n的数组,我们定义median数为该数组从小到大排序后,下标为(n-1)/2的数字。下标从0开始,(n-1)/2表示整数除法,即向下取整。现在我们已经得到了一个初始的数组,我们希望这个数组的median数是一个给定数字x。所以我们需要加入一些数到数组中从而完成我们的目标。数组中的元素可以重复,请问,最少需要加入多少个数字才能达成这个目标。)

  序列最小化(有一个长度为N的序列。一开始,这个序列是1, 2, 3,... n - 1, n的一个排列。对这个序列,可以进行如下的操作:每次选择序列中k个连续的数字,然后用这k个数字中最小的数字替换这k个数字中的每个数字。我们希望进行了若干次操作后,序列中的每个数字都相等。请你找出需要操作的最少次数。)

  奇数位丢弃(对于一个由0..n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。)

posted @ 2019-08-25 20:43  XieXinBei0318  阅读(163)  评论(0编辑  收藏  举报