不修改数组找出重复的数字

在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至少有一个数字是重复的。
请找出数组中任意一个重复的数字,但不能修改输入的数组。
例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的输出是重复的数字2或者3。

思路

按照二分查找的思路
数组长度为n+1,而数字只从1到n,说明必定有重复数字。
可以用二分查找扩展{2, 3, 5, 4, 3, 2, 6, 7} 取中间数4
统计1-4,5-7 在数组出现的次数
1-4 出现了5次,如果大于4则在1-4一定有重复
接下来缩小范围1-2,3-4
3-4出现了3次
再分别统计 3,4
3出现了两次 则3为重复元素

实现

public int getDuplicate(int[] arr) {
    int start = 1, end = arr.length - 1;
    while (start <= end) {
        int mid = (end - start) / 2 + start;
        int count = getCount(arr, start, mid);
        if (start == end) {
            if (count > 1) {
                return start;
            } else {
                break;
            }
        }
        if (count > (mid - start + 1)) {
            //说明有重复元素
            end = mid;
        } else {
            //相反
            //因为 数组中肯定有重复的元素,不上一半就在这
            start = mid + 1;
        }
    }
    return -1;
}
//计算数组中start-end 中出现的次数
private int getCount(int[] arr, int start, int end) {
    if (arr == null) {
        return 0;
    }
    int count = 0;
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] >= start && arr[i] <= end) {
            count++;
        }
    }
    return count;
}

测试用例

public void test() {
    int[] a = { 1, 2, 3, 2, 4 };
    int dup = getDuplicate(a);
    System.out.println("重复数字为:" + dup);
}

输出

重复数字为:2

注意
这种算法不能保证找到所有的重复数字。
例如:{2,3,5,4,3,2,6,7} 中1-2范围有1和2两个数字,
但这里这个范围的数字也出现了2次,此时我们用该算法不能确定是每个数字个
各出现一次还是某一个数字出现了两次

转载于:https://www.cnblogs.com/aiguozou/p/11438001.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值