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

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

题目链接

数组中重复的数字

题目描述

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

Input:
{2, 3, 1, 0, 2, 5, 3}

Output:
2或3

解题思路

1. 计数法

一看这个题要求重复的数字,首先想到的就是用计数法,找到一个个数大于1的就可以返回结果了。

class Solution {
    public int findRepeatNumber(int[] nums) {
        if(nums == null || nums.length == 0) return -1;
        int[] count = new int[nums.length];
        for(int i = 0; i < nums.length; i ++){
            count[nums[i]] ++;
            if(count[nums[i]] > 1) return nums[i];
            
        }
        return -1;
    }
}

这样做时间复杂度和空间复杂度都是O(N),一旦要求空间复杂度是O(1)这样就行不通了、、、

2. 抽屉原理

抽屉原理指的是n个元素,n-1个抽屉,编号为i的抽屉放一个对应的元素i,一定有其中一个抽屉x需要放两个元素x,所以我们要找的这个重复元素就是x。

所以这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。本题要求找出重复的数字,因此在调整过程中,如果第 i 位置上已经有一个值为 i 的元素,就可以知道 i 值重复。

以 (2, 3, 1, 0, 2, 5, 3) 为例,遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复:

class Solution {
    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[nums[i]] == nums[i]) return nums[i];//如果当前数字应该放的位置上已经有了对的数字,就返回结果
                else{ //否则就交换
                    int tmp = nums[i];
                    nums[i] = nums[tmp];
                    nums[tmp] = tmp;
               }
            }            
        }
        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值