• 【剑指offer】 03 数组中重复的数字


    【剑指offer】 03 数组中重复的数字

    3-1 题目

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

    思考

    • 解法1:我直接一看就打算暴力了,开一个数组or字典记录每个出现过的数字,直接扫一边即可获得答案,时间复杂度为O(n),空间复杂度也是O(n)
    • 我没有考虑其他的解法,还有其他两种空间复杂度为O(1)的解法:
    • 解法2:排序,然后看这个数字和上一个数字是不是一样。时间复杂度为O(nlogn),空间复杂度为O(1)
    • 解法3:鸽巢原理(原地置换、原地哈希)。因为这个题目比较特殊,长度为n而且所有数字都在0~n-1里面,所以如果没有重复的数字的话,这个数组排序之后每个元素和其下标是一一对应的(元素值==下标值)。如果有重复的元素的话,有的元素无法再放在其值下标的位置的,因为那里面已经有了一个相同值的元素了。
      • 如果当前这个元素值不等于其下标
        • 如果其值对应下标不等于其值,则交换(则这个值可以放到相应下标的位置里了)
        • 如果其值对应下标等于其值,找到重复元素
      • 如果当前这个元素值等于其下标,则判断下一个下标的元素
    • 三种解法的效果,其中第一行为解法三,第二行为解法2,第三行为解法1的map实现,第四行为解法1的布尔数组实现。
      • image-20210113161446493

    代码

    解法1

    • 发现直接用一个O(n)的布尔数组(下),比用map(上)的效果更好,所以最好还是少用STL(盲猜?)
      • image-20210113160159137
    • 容器访问最好直接用下标访问,有些情况会明显下标更快
    class Solution {
        bool a[100005];
    public:
        int findRepeatNumber(vector<int>& nums) {
            memset(a,0,sizeof(a));
            int ret=0;
            // 最好是直接下标访问,一些情况会明显比用迭代器快
            // 我写这个代码的时候不知道hhh
            for(vector<int>::iterator it=nums.begin(); it!=nums.end(); it++){
                if(a[*it]){
                    printf("%d
    ",*it);
                    ret = *it;
                    break;
                }
                else{
                    a[*it]=true;
                }
            }
            return ret;
        }
    };
    

    解法2

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

    解法4

    class Solution {
    public:
        int findRepeatNumber(vector<int>& nums) {
            for(int i=0;i<nums.size();i++)
            {
                while(i!=nums[i]){
                    if(nums[nums[i]]==nums[i]){
                        return nums[i];
                    }
                    else{
                        swap(nums[i], nums[nums[i]]);
                    }
                } 
            }
            return 0;
        }
    };
    
  • 相关阅读:
    02-CSS基础与进阶-day8_2018-09-10-20-14-46
    02-CSS基础与进阶-day7_2018-09-07-21-42-30
    02-CSS基础与进阶-day7_2018-09-07-20-25-28
    02-CSS基础与进阶-day7_2018-09-07-20-15-37
    02-CSS基础与进阶-day6_2018-09-05-22-35-51
    linux(5)查看历史命令执行记录history
    linux(4)Linux 文件内容查看
    linux(3) 处理目录的常用命令
    linux(2)系统目录结构
    docker(12)使用Dockerfile创建jenkins+python3+pytest环境
  • 原文地址:https://www.cnblogs.com/xuwanwei/p/14272711.html
Copyright © 2020-2023  润新知