剑指offer-数组中重复的数字

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

思路和实现

way1(参考剑指offer)

在这里插入图片描述

数组中的数字都是在0~n-1的范围内,如果数组中没有重复的数字,当数组排序后数字 i 出现在下标为 i 的位置。 因为数组中有重复的数字,所有有些位置可能存在多个数字,有些位置可能没有数字。

思路: 重新排列数组,从头到尾扫描,
扫描到下标为i的数字m,比较数字m是不是等于 下标i:
   如果是,扫描下一个数字
   如果不是,将下标为i的数字m 和下标为m的数字比较:
     如果相等,则找到了一个重复的数字(下标为i和下标m的位置都出现数字m)
     如果不相等,则将下标为i的数字m 和下标为m的数字交换,将m放到属于它的位置。
重复此过程,直到发现重复的数字。

举例:
在这里插入图片描述

实现:

public class Solution {
    public boolean duplicate(int numbers[], int length, int[] duplication) {
        if (numbers == null || length == 0)
            return false;
        for (int i = 0; i < length; i++) {
            if (numbers[i] < 0 || numbers[i] > length - 1)
                return false;
        }

        for (int i = 0; i < length; i++) {
            while (numbers[i] != i) {
                if (numbers[i] == numbers[numbers[i]]) {
                    duplication[0] = numbers[i];
                    return true;
                }
                //交换numbers[i]和numbers[numbers[i]]
                int temp = numbers[i];
                numbers[i] = numbers[temp];
                numbers[temp] = temp;
            }
        }

        return false;
    }
}

way2

思路: 不需要额外的数组或者hash table来保存,题目里写了数组里数字的范围保证在0 ~ n-1 之间,所以可以利用现有数组设置标志,当一个数字m被访问过后,可以设置索引位置为m对应的值 + n,之后再遇到相同的数时,会发现对应索引位置上的数已经大于等于n了,那么直接返回这个数即可。

实现:

public class Solution { 
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        duplication[0]=-1;
        if(numbers==null || length==0 )
            return false;
        for (int i = 0; i <length ; i++) {
            int index=numbers[i];
            if(index>=length)
                index-=length;
            if(numbers[index]>=length){
                duplication[0]=index;
                return true;
            }
            numbers[index]+=length;
        }
        return false;
    }
}

例如:

  • n=7 {2,3,1,0,2,5,3}
    int i = 0; i <length ;
    int index=numbers[0]=2;
    if(index>=length)
    index-=length;
    if(numbers[index]>=length){
    duplication[0]=index;
    return true;
    }
    numbers[2]+=length numbers[2]=1+7=8;
    i++ ; i=1

  • n=7 {2,3,8,0,2,5,3}
    int i = 1; i <length ;
    int index=numbers[1]=3;
    if(index>=length)
    index-=length;
    if(numbers[index]>=length){
    duplication[0]=index;
    return true;
    }
    numbers[3]+=length ; numbers[3]=0+7=7
    i++ ; i=2

  • n=7 {2,3,8,7,2,5,3}
    int i = 2; i <length ;
    int index=numbers[2]=8;
    if(index>=length)
    index-=length; index=1
    if(numbers[index]>=length){
    duplication[0]=index;
    return true;
    }
    numbers[1]+=length ; numbers[1]=3+7=10
    i++ ; i=3

  • n=7 {2,10,8,7,2,5,3}
    int i = 3; i <length ;
    int index=numbers[3]=7;
    if(index>=length)
    index-=length; index=7-7=0
    if(numbers[index]>=length){
    duplication[0]=index;
    return true;
    }
    numbers[0]+=length ; numbers[0]=2+7=9
    i++ ; i=4

  • n=7 {9,10,8,7,2,5,3}
    int i =4; i <length ;
    int index=numbers[4]=2;
    if(index>=length)
    index-=length;
    if(numbers[index]>=length){
    duplication[0]=index =2;
    return true;
    }

参考

https://www.nowcoder.com/profile/456591/codeBookDetail?submissionId=1512271

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值