找出数组中任意重复的数字(不修改数组)

题目

在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。

思路

借鉴二分查找的思想,将数字1~n拆分成1~m和m+1~n两部分,如果数字范围1~m中数字个数大于m,则重复数字在1~m中间,否则重复数字一定在数字范围m+1~n中。基于二分查找法不能找到全部的重复数字,例如{2,2,3,3,4,5,6,7}中数字区间为1~2的范围内2出现两次,但1没有出现,不能确定是每个数字出现一个还是某个数字出现两次。

高明解法:
首先将数组一分为二,假设数组有8个元素。那么元素大小都在 0 ~ 7 之间。一分为二,如果没有重复,四个元素在 0 ~ 3 之间,四个在 4 ~ 7 之间。假设数组为arr[8] = {1, 0, 2, 3, 3, 4, 5, 6},统计0 ~ 3 之间的元素有5个, 统计 4 ~ 7 之间的元素有3个。说明,在 0 ~ 3 之间肯定有重复元素。接下来划分 0 ~ 3的5个元素{1, 0, 2, 3, 3}。 0 ~ 1 之间有两个元素, 2~3之间有三个元素。再划分2 ~ 3之间的元素,2有一个,3有两个,所以重复的是元素3。

#include <iostream>
    #include <vector>
    using namespace std;
    class Solution{
    public:
        int duplication(vector<int> vec)
        {
            // 空数组
            int length = vec.size();
            if(vec.size() == 0)
                return -1;

            // 数字超界
            for(int i =0;i<length;++i)
            {
                if(vec[i]<1 || vec[i]>length-1)
                    return -1;
            }
            // 定义数字范围
            int begin = 1;
            int end = length-1;

            // 指定数字范围内的数字个数
            while(begin<=end)
            {
                // 计算数字范围的中点
                int mid = (begin + end)>>1;

                // 统计指定数字范围内的数字个数
                int count = countrange(vec,begin,mid,length);

                if(end > begin)
                {
                    // 更新数字范围
                    if(count>(mid - begin + 1))
                        end = mid;
                    else
                        begin = mid + 1;
                }
                else
                {
                    if(count > 1)
                        return begin;
                    else
                        break;
                }
            }

            return -1;
        }
int countrange(vector<int> vec,int begin,int end,int length)
    {
        int count=0;
        for(int i=0;i<length;++i)
        {
            if(vec[i]>=begin && vec[i]<=end)
                ++count;
        }

        return count;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_35433716/article/details/82118025