Leetcode每日刷题(day3)

简介: Leetcode每日刷题(day3)

数组中重复的数字


来源:leetcode:剑指offer 03.数组中重复的数字


1、题目描述


找出数组中重复的数字。



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


2、示例

1669255774422.jpg

3、排序暴力求解


经历了四数之和的折磨,看到这道题目,我的内心是狂喜的,这算个题?四数之和截取的一部分就能解出来,快排一下,然后去重,so easy!😅

int cmp(const void* x,const void* y)
{
    return *(int*)x-*(int*)y;
}
int findRepeatNumber(int* nums, int numsSize)
{
    //排序后去枝叶
    int ret=0;
    qsort(nums,numsSize,sizeof(int),cmp);
    for(int i=0;i<numsSize;++i)
    {
        if(i>0&&nums[i]==nums[i-1])
        {
            ret=nums[i];
            break;
        }
    }
    return ret;
}

不得不说快排真的爽,我们来分析一下复杂度:


时间复杂度:大O一下就是O(N*logN);


空间复杂度:O(1)


然后呢?跑是跑过去了,但是面试官问:不许用排序,有没有时间复杂度是O(N),空间复杂度是O(1)的解法?果然,没那么简单。


4、交换比较解法


要求是O(N),给我们的是数组,那么只有一种可能,最多遍历一遍数组就能找出重复的数。


我们再来看题目能不能给我们点有利的线索,我们注意到:

1669255803856.jpg

这句话很重要!为什么呢?他告诉我们一个信息:如果数组内是有序的,且没有重复的数字,那么每个数的下标都应该和这个数相等!


大佬已经悟了,像我和各位老铁一样的普通码农可能还不太理解,我们进一步分析:


1669255820616.jpg


对于这一组数,如何操作呢?


1669255830541.jpg


图有点糙...


基本逻辑:


设i为下标遍历,数组为nums。


i=0为下标遍历数组,如果i不等于以nums[i],那么就把以nums[i]为下标的nums[nums[i]]和nums[i]比较,如果相等,就找到了重复的数字,如果不相等就交换,交换过后,继续比较i和nums[i],如果相等,i就++,去查看下一个数,直到找到重复的数!


void Swap(int* x,int*y)
{
    int tmp=*x;
    *x=*y;
    *y=tmp;
}
int findRepeatNumber(int* nums, int numsSize)
{
    //注意数组长度为n,且所有数字都在0~n-1的范围内,所以如果没有重复的数,那么
    //如果排好序,必定每个数的下标都与这个数相等
    int ret=0;
    for(int i=0;i<numsSize;++i)
    {
        int flag=1;
        while(i!=nums[i])
        {
            //nums[nums[i]]和nums[i]比较
            if(nums[nums[i]]==nums[i])
            {
                ret=nums[i];
                flag=0;
                break;
            }
            else//如果不等于
            {
                Swap(&nums[nums[i]],&nums[i]);
            }
        }
        if(flag==0)
            break;
    }


复杂度分析:


代码中尽管有一个双重循环,但是每次交换都为一个数找到了它在有序数组里的正确位置可以减少我们后序循环。


时间复杂度:O(N)


空间复杂度:O(1)

相关文章
|
4天前
|
算法 C++
【刷题】Leetcode 1609.奇偶树
这道题是我目前做过最难的题,虽然没有一遍做出来,但是参考大佬的代码,慢慢啃的感觉的真的很好。刷题继续!!!!!!
8 0
|
4天前
|
算法 索引
【刷题】滑动窗口精通 — Leetcode 30. 串联所有单词的子串 | Leetcode 76. 最小覆盖子串
经过这两道题目的书写,相信大家一定深刻认识到了滑动窗口的使用方法!!! 下面请大家继续刷题吧!!!
9 0
|
4天前
|
算法
【刷题】 leetcode 面试题 08.05.递归乘法
递归算法是一种在计算机科学和数学中广泛应用的解决问题的方法,其基本思想是利用问题的自我相似性,即将一个大问题分解为一个或多个相同或相似的小问题来解决。递归算法的核心在于函数(或过程)能够直接或间接地调用自身来求解问题的不同部分,直到达到基本情况(也称为基础案例或终止条件),这时可以直接得出答案而不必再进行递归调用。
21 4
【刷题】 leetcode 面试题 08.05.递归乘法
|
4天前
|
存储 算法 安全
【刷题】 leetcode 面试题 01.06 字符串压缩
来看效果: 非常好!!!过啦!!!
25 5
【刷题】 leetcode 面试题 01.06 字符串压缩
|
4天前
|
存储 算法 测试技术
|
4天前
|
算法 C语言 C++
|
存储 算法 C语言
C语言刷题~Leetcode与牛客网简单题
C语言刷题~Leetcode与牛客网简单题
|
20天前
刷题之Leetcode160题(超级详细)
刷题之Leetcode160题(超级详细)
13 0
|
20天前
|
Java
刷题之Leetcode19题(超级详细)
刷题之Leetcode19题(超级详细)
14 0