剑指 Offer 03. 数组中重复的数字

本文介绍了一种在0~n-1范围内寻找数组中重复数字的最优算法,通过巧妙利用数组特性和原地交换,实现了O(n)时间复杂度和O(1)空间复杂度的解决方案。

题目描述:

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

解题思路:

1、利用排序:
     这道题很容易想到的思路是使用排序算法得到一个排序的数组,然后顺序判断每一个数字,如果存在重复的数字,则该数字一定是连续的,这样就可以找出重复的数字,但是由于排序算法的时间复杂度是O(nlogn),因此这个算法不是最优的。

2、哈希表:
      同时也可以利用哈希表来解决这个问题,也就是从头顺序扫描数组,每扫描一个数字时都可以使用O(1)的时间复杂度判断哈希表中是否已经包含了该数字,如果没有的话则保存该数字到哈希表中,否则该数字就是重复数字。这种算法的时间复杂度为O(n),但是空间复杂度是O(n),因为需要一个空间大小为O(n)的哈希表。

3、最优算法:
     由于题目描述中该数组nums是一个大小为n,同时数字范围为0~n,因此可以利用这个特性来进行扫描,扫描的方法是:从头开始扫描数组,判断每个数字nums[i]nums[nums[i]]中是否一样,如果一样,则num[i]是重复数字;否则交换这两个数字,即swap(nums[i],nums[nums[i]]),然后继续判断下一个数字,即nums[i]nums[i]已经是交换后的数字了,也就是下一个数字),使用这种方法可以遍历整个数组,同时空间复杂度为O(1),由于每个数字最多交换两次,因此时间复杂度为O(n)

实现代码:

	//返回数组中任意一个重复的数字
    public int findRepeatNumber(int[] nums) {
        if(nums == null || nums.length == 0)
            return -1;
        for(int i = 0; i < nums.length; i++){
            while(nums[i] != i){//只要下标不对应才判断
                if(nums[i] == nums[nums[i]])//判断是否重复
                    return nums[i];
                else
                    swap(nums, i, nums[i]);//交换nums[i]和nums[nums[i]]
            }
        }
        return -1;
    }

    public void swap(int a[],int i, int j){
        int t = a[j];
        a[j] = a[i];
        a[i] = t;
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值