bat从数组中找出相同数字并删除_001 数组中重复的数字

做题过程中,发现自己把问题解决了,但是自己头脑还是好乱,所以打算把解题思路给写出来。如何发现问题,优化问题的。题目全当实在面试

01

题目


找出数组中重复的数字。


在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:[2, 3, 1, 0, 2, 5, 3]输出:2 或 3

限制:

2 <= n <= 100000

来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof

02

解题思路


需求阶段

拿到这道后, 我首先思考几个问题。

问题1:这道让我实现什么功能。  数据源以什么逻辑形式存放在内存中。

找到数组中重复的任何一个数字即可。数据源存放在数组中。

和面试官沟通:

数组的数据是否可以修改    

        假设面试官告诉我, 数据为传入参数。

时间复杂度和空间复杂度的要求

        假如面试官告诉我,时间复杂度O(NlogN)

构思阶段

一、小白思路:

    使用双重 for 循环。第一个元素和当前元素后面的比较 ,第二个和当前元素后面的比较,当发现有相等的情况下,满足条件。  这个思路比较简单。

    但是思考一番时间复杂度和要求相差太大了。当前的时间复杂度为O(N^2)

二、进一步思考,时间复杂度可以从O(N^2)优化到 O(NlogN)吗?

  •   时间浪费在什么地方  ---  小白思路主要时间浪费在 一个元素需要和N个元素比较。

  •   那么可以实现一个元素仅仅和当前元素相邻的元素比较即可呢? ---  数组排序。然后依次比较相邻的元素。。其实有经验的,通过面试官告诉时间复杂可以知道本题最差使用什么算法可以通过,既NlogN时间复杂度类的算法,排序什么的。

1 数组排序

2 依次比较相邻的元素

把 2 的过程通过图来表示

ca090df3f5817a16cd3cea674a949565.png

08cb11c21ca2d424f0161e5fedae3b53.png

16d2780dd56abede07e380e18479995a.png

代码实现

int findRepeatNumber(vector<int>& nums) {    //1 排序    sort(nums.begin(), nums.end());    //2 依次查找相邻的是否相等。    // i 表示左区间 j 表示右区间      int i, j;    i = 0; j = 0;    for ( j =0 ; j < nums.size(); j++)    {      if (i == j) continue;      if (i != j && nums[i] == nums[j])      {        return nums[i];      }      if (i != j && nums[i] != nums[j])        i = j;    }    return -1;  }};

1f19dc6410571ef5f3a6f41ac52b8491.png

小伙子不错哦, 通过提交看来,你的时间复杂度还是太高了,那你在思考下,能不能在优化下,实现时间复杂度为O(N)呢!

876ca255929dff31fe5312a53fecf4cc.png

陷入了沉思ing。。。

三、从O(NlogN)优化到O(N)

如何做到O(N)的时间复杂度呢?,实现这种级别的话只能循环一遍数组。

题目表示数组里面的值都在 0~n-1 范围内,那么能不能使用它来做点文章呢?

可以把里面的相同的数据放到一个地方, 那么数据存放的地方可以在去申请一块内存。这块内存是多大呢,根据里面的数值范围,取边界值。

总结一下: 

    其实就是使用简单 hash 算法。  hash 地址为一维数组的下标,hash 函数为f(x) = x   

    注:x 为 关键码因变量   f(x)为存储的地址

    相同的数据放在同一个存储单元内存,你可能会问,如何同时存放,其实来一个数,相应存储单元加一。

    最后遍历 hash 表。>2 表示 重复数据。

图解时间到了

eff7c538168ec0073cd59f0fdf04460f.png

d881bb9693bf255eb221f1f037d4556f.png

936bd4e53e40b474e4dab3e01a58e187.png

f4fdc26e3d5b74ec7c8c315623b5ba8b.png

558ba1bec47761447dd430d19ff961b6.png

由于hash[2]>2所以没有必要往下走了。

代码实现

class Solution {public:  int findRepeatNumber(vector<int>& nums) {    vector<int> hash(nums.size(),0);        for(int i = 0;i        {            if(hash[nums[i]] == 1 )                return nums[i];            hash[nums[i]]++;        }        return -1;  }};

性能

45cd4649cbd41d919eec90a15679653b.png

时间复杂度提高了接近一半 。但是搞不清楚为什么内存消耗为什么不变和上次比较。理论上是 辅助内存 消耗了O(N)才对啊。

四、面试官有要问了,能不能实现辅助内存为O(1)嫩

好吧!那我想一下、

主要使用 hash 表占用了,那不用 hash 表, 把数据放到数组 nums 中,

当前数组 当 hash 表,

流程:

//伪代码for( i = begin ; i/依次遍历{  while( arr[i]  != i)  {      if(arr[i] != arr[arr[i]])         swap(arr[i] , arr[arr[i]])      else          return arr[i];  }}

图解时间到了

16cfed2f3d0ec069483b829752dc721f.png

27ebdf216b9d3ce2cb49f794d746471f.png

a6c0bb0d69fa44af7c42aff41003fe33.png

fae1668be8221c2794435520c3c1e86e.png

代码实现

class Solution {public:  int findRepeatNumber(vector<int>& nums) {    //遍历整个数组    for (int i = 0; i < nums.size(); i++)    {      //把 nums[i] 放到 对应的下标中。5 > nums[5]      while (i != nums[i])      {        if (nums[i] == nums[nums[i]])          return nums[i];        swap(nums[i], nums[nums[i]]);      }    }    return -1;  }};

性能;

02a8cc28f29d96b6e1c040dd510fb8a6.png

提高了10ms左右。

还不错。

03

总结

  • hash 函数

  • 双指针

今天发现对  vector 不是很熟悉, 在这留个 tag , 找下相关资料在去总结。

留给自己的作业。

能不能再不改变数组情况下,且辅助内存为O(1)的情况下实现呢???

这个问题留着明天再来吧!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值