剑指Offer-题3(Java版):找出数组中重复的数字

参考自:《剑指Offer——名企面试官精讲典型编程题》

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

主要思路: 数组中的数字范围为0~n-1,若没有重复数字,则排序后数字i出现在数组下标为i的位置。但是,因为有重复数字,所以数字和其下标不是一一对应的关系。重排该数组(numbers),从头到尾扫描,当扫描到下标为i时,判断其数值(m)是否等于i。

  1. 若相等,则继续扫描下一位置。
  2. 若不相等,则将该数值m与下标为m的数值(numbers[m])比较:
    2.1 若这两个数相等,则找到了第一个重复的数字(该数字在下标为i和m的位置都出现了);
    2.2 若不相等,则交换这两个数的位置,使得数值m 与其下标相等。接下来继续比较交换,直到找到重复的数字。

关键点: 找到数值与其索引的关系。

时间复杂度:O(n)

public class DuplicateNumber {
    public static void main(String[] args) {
        int[] numbers = {2, 3, 1, 0, 2, 5, 3};
        int[] duplications = new int[1];
        boolean isDuplicated = duplicate(numbers, numbers.length, duplications);
        if (isDuplicated) {
            // 2
            System.out.println(duplications[0]);
        }
    }

    private static 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) {
                int currentNumber = numbers[i];
                //该数字出现两次
                if (currentNumber == numbers[currentNumber]) {
                    duplication[0] = currentNumber;
                    return true;
                }
                //交换到正确位置
                int temp = numbers[currentNumber];
                numbers[currentNumber] = currentNumber;
                numbers[i] = temp;
            }
        }
        return false;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值