找数组中重复数字(修改数组和不修改数组)

给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内。

数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。

请找出数组中任意一个重复的数字。

一:修改数组

代码:

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int n = nums.size();
        for (auto x : nums)
            if (x < 0 || x >= n)
                return -1;
        for (int i = 0; i < n; i ++ ) {
          while(nums[nums[i]] != nums[i]) swap(nums[i], nums[nums[i]]);
            if (nums[i] != i) return nums[i];
        }
        return -1;
    }
};

核心思想: 

1.因为所有数字的范围都在0 - n-1,先遍历整个数组把数值  i 分配到第  i  个数组,这样的话,如果有重复的数的话,等循环完毕后肯定会有一个   数值与数组的位置不对应

一个重要的问题:如何把数值  i 分配到下标  i  的数组,

循环:while(num[num[i]] != nums[i]) swap(num[i],num[num[i]])

要理解为什么是    mun[i]    and     num[num[i]] 

像一个问题:如果num [ i ]  ==   num[num[i]]     是不是说明数值  i 分配到下标  i  的数组

二:不修改数组 

与第一种方法截然不同

中心思想:

因为数组中有n个数,但是数的取值范围为  1   -      n

所以肯定有重复的数

所以我们只需要把这个数的取值范围分成两半

以n = 9为例

1 2 3 4 5 6 7 8 9

然后遍历一遍数组如果数组的值在1-4范围内

count++

遍历完成后:

如果count  >   4说明数组中一定有在1-4范围内的数存在不止一次

所以缩小范围

1 2 3 4        (同理)

如果 count  <= 4,说明重复出现的数字在另外半块

代码:

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int left = 1,right = nums.size()-1;//因为这里right指的是有序数123456789的最右
                                            //而不是数组的最右
        int mid = 0;
        while(left < right)
        {
             mid = (left + right)/2;
            int cout = 0;//计算数组里的数和前半段数目是否符合
            for(int x:nums)//遍历
            {
                if(x>=left&&x<=mid)
                cout++;
            }
            if(cout > mid-left+1) right = mid;
            else left = mid +1;
           
        }
        return right;
    }
};

以下代码还有一种写法: 

for(int x:nums)//遍历
            {
                if(x>=left&&x<=mid)
                cout++;
            }



for(int x:nums)//遍历
            {
                cout+=x>=left&&x<=mid
            }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小布丁729

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值