zoukankan      html  css  js  c++  java
  • 不修改数组找出重复的数字

    在一个长度为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次,此时我们用该算法不能确定是每个数字个
    各出现一次还是某一个数字出现了两次

  • 相关阅读:
    git基本
    openwrt 固件的uci系统
    openwrt刷固件恢复原厂固件
    openwrt 登录管理页面openwrt管理页面密码
    openwrt固件升级方法
    OpenWrt简要介绍openwrt开发
    X86 openWRT 虚拟机编译教程 在ubuntu10中X86 OpenWRT的源码编译
    无线热点认证解决方案 WifiDog
    怎么把wifidog直接编译进openwrt
    portal为什么选择开源路由器第三方固件 OpenWrt
  • 原文地址:https://www.cnblogs.com/aiguozou/p/11438001.html
Copyright © 2011-2022 走看看