剑指offer 面试题3.数组中重复的数字

目录

0、题目描述

0.1、朴素想法--排序OR桶排

0.2、剑指offer解法理解

1、进阶题目描述

1.1、朴素想法--桶排OR使用STL

2.2、剑指offer解法理解


0、题目描述

  • 一个长度为n的数组中所有数字都在0~n-1之间
  • 数组中有些数字是重复的,有些是不重复的
  • 不知道每个数字重复几次
  • 请找任意一个重复的数字
  • 例:长度为7的数组{2、3、1、0、2、5、3}输出2或3

       

0.1、朴素想法--排序OR桶排

①很容易想到的是先排序,然后判断相邻两个数字之间是否相等。如果相等直接返回true即可。

此时好处是空间复杂度是o1,时间复杂度取决于排序的时间复杂度。

(发散一下复习高级排序算法:堆排序、快速排序)

②可以通过桶排,缺点是空间换时间。

   

0.2、剑指offer解法理解

这里想写一下自己较为通俗的去理解剑指offer中的解法。

多读几遍题目找一找隐含条件,长度为n且数字必须在0~n-1之间。

逆向的去想一下就可以发现不重复的情况只有一种即:0~n-1的数字都存在且只有一次。

根据这种唯一性可以这样去理解:n个人,n个座位。都有自己的编号,编号对应一个唯一属于自己的座位。

   

根据书中的例子,有7个座位,编号{0、1、2、3、4、5、6}

当前0号位置上坐的是2;

一号位置上坐的是3;

   

从左向右遍历这个座位,我们可以根据座位号和号码是否相同来区分这个"人"是否"失位"?

0号位置上坐的是2,则2称为失位,我们需要把2送回到2号位上。

当然,如果2号位已经坐了2那么可以直接退出说明2重复了。

换完之后,继续判断0号位是否依然失位。

1、进阶题目描述

进阶题目增加不允许修改原数组为条件。且数字范围1~n之间,不再是0~n-1。

1.1、朴素想法--桶排OR使用STL

与上述相同。桶排空间换时间。

在数据量比较大的时候,用STL中set或者map可以以较小的空间代价完成任务。

2.2、剑指offer解法理解

在这个例子中,数字范围在1~8之间,那么如果有重复的数字必须也是在1~7之间。

思路是通过二分法将区间不断分割。

比如说,第一次分割区间是1~4和5~8两个区间

遍历一次整个数组,如果小于等于4就count++,那么一趟之后我们就可以知道1~4区间中有多少个数字,反之用8(数组的总长度)减去这个count就可知5~8之间有多少个数字。

如果count正好等于区间长度 或者 count大于区间长度,那么这个重复数字可能 或者 一定在这个区间。

继续对这个区间二分。。以此推类。

   

但很明显,这个算法的弊端是只能找出一个重复数字。

如果有两个重复数字,那么一定会在某个分割阶段,两个区间会割离。

比如{4,4,4,4,8,8,8,8}那么在第一次分割区间的时候只能选择1~4的区间,或者5~8的区间。

而无论你的算法选择哪个区间你都会失去一种情况。

猜你喜欢

转载自blog.csdn.net/qq_32963855/article/details/105782070