将一个数组中不重复_你不知道的解法:数组中重复的数字

点击关注上方“五分钟学算法”,

设为“置顶或星标”,一起成长

5e9084a23946cf04c8f96692262ad636.png

今天分享的题目来源于 LeetCode 上的剑指 Offer 系列 面试题03. 数组中重复的数字

题目链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

一、题目描述

找出数组中重复的数字。

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

示例 1:

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

限制:

2 <= n <= 100000

二、题目解析

注意题目描述:一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的 范围内,这个 范围 恰好与数组的下标可以一一对应。

所以我们可以执行某种操作,使索引与值一一对应即索引 0 的值为 0,索引 1 的值为 1。而一旦某个索引的值不只一个,则找到了重复的数字,也即发生了 哈希冲突

三、动画描述

四、图片描述

3b751b50464fbcb98aa86f4a4feb47b7.png

d02bbb492a642227d09540472eda33b5.png

aca207d21fedd407c4c6dcf05e9074cd.png

35cdfa6ad8c20c288827573fc396715a.png

b23d69c05fc253d857cb90e7f8c3da67.png

77db72bdd5449590f39517d37ae9393c.png

52f35ac41ea113ac6d538cf617c0263d.png

2109a68e505ea8d5350259f34cc581a7.png

d80de5bd3d3883ac09b0435a1175cd2d.png

a371e51bdf7fc84caed06a1df4f5de71.png

18457511e6b89073fcc5c208acba5e5c.png

02fc461032da4286c19945d22d5fd176.png

8c3e2ee617fd0b966500e0cd2e8df27c.png

c7c387859b2753a2a983de2c6b115abd.png

69094f039ba284e6d6e9cfb4269d4985.png

53238559a3dda055ad32abcc31800f12.png

34b112922957402260985492f46289ee.png

a51e6b7d617b930c2e8f23ebce1b3f7c.png

e5e6c30c7e987f6d204523fc0844b311.png

5b257f21a2b68cd546be042e90b0f74e.png

954bd9bc368de446f5089a23a8be0f9c.png

ac04df2dbcc1d18d4adb8a396284e782.png

1db8580cb13aa8f48c2c112ab0092732.png

5061a95438b6c38143a4fb639699ef68.png

4e7a4ea66cd94eb324429dd9323be624.png

8c8953175d955b89c1ffa7db7da12c3a.png

122813f07060dfeb20d89f4759e308b4.png

e0de599bb656ffdec2189c33d7661c5e.png

730ef5098d634cb239f3ac06ad563f0c.png

a44be02eb202cb7ae85d5717f6010e76.png

五、参考代码

class Solution {
    public int findRepeatNumber(int[] nums) {
        //设索引初始值为 i = 0
        int i = 0;
        //遍历整个数组 nums 
        while(i             //索引 i 的值为 i,无需执行交换操作,查看下一位
            if(nums[i] == i) {
                i++;
                continue;
            }
            //索引 nums[i] 处的值也为 nums[i],即找到一组相同值,返回 nums[i] 即可
            if(nums[nums[i]] == nums[i]) return nums[i];
            //执行交换操作,目的是为了使索引与值一一对应,即索引 0 的值为 0,索引 1 的值为 1
            int tmp = nums[i];
            nums[i] = nums[tmp];
            nums[tmp] = tmp;
        }
        //如果遍历整个数组都没有找到相同的值,返回 -1
        return -1;
    }
}

六、复杂度分析

时间复杂度

遍历数组需要 O(N) 时间。

注意参考代码里面的关键字 continue,这表示在 while 的一次循环里面,只有这次循环将 索引(i)索引值(num[i]) 匹配到了,才会执行下一次循环。

在每一次的循环过程中,索引(i)索引值(num[i]) 匹配到后,在后续的循环过程中不会操作它们,所以虽然一开始的循环过程中,执行的交换操作较多,但在后续的循环过程中根本不需要再执行操作了。

根据均摊复杂度分析 ,总的时间复杂度为  O(N) ,N 为数组的长度。

空间复杂度

使用常数复杂度的额外空间,为  O(1)

七、相关标签

  • 数组

  • 哈希

  • 原地哈希

今天是 『 365 刷题计划 』 第 41 天。每晚八点,一起图解一道算法题,不见不散!


欢迎关注我的公众号“图解面试算法”,如果喜欢,麻烦点一下“在看”,转发+在看相当于打赏!

216e68391396bbeba06b576eaaa58e6f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值