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


    0、题目描述

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

         

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

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

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

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

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

       

    0.2、剑指offer解法理解

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

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

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

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

       

    根据书中的例子,有7个座位,编号{0123456

    当前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大于区间长度,那么这个重复数字可能 或者 一定在这个区间。

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

       

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

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

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

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

  • 相关阅读:
    在linux上通过docker运行容器,通过docker搭建jenkens环境
    linux jdk 安装报错
    UEditor 后台配置项返回格式出错,上传功能将不能正常使用!
    spring boot 项目 freemarker 无法加载static 中 js css 文件 原因(报错404)
    windows mongodb 添加用户
    window连接本地mongodb 报错 mongodb shell was not initiallized
    Zookeeper(四) 客户端shell命令
    Zookeeper(三) 集群搭建
    Zookeeper(二) 安装及配置
    Zookeeper(一) 入门
  • 原文地址:https://www.cnblogs.com/Justdocument/p/12383641.html
Copyright © 2020-2023  润新知