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

在一个长度为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

时间: 2024-10-10 09:10:24

不修改数组找出重复的数字的相关文章

面试题3(二):不修改数组找出重复的数字

// 面试题3(二):不修改数组找出重复的数字// 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至// 少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改输入的// 数组.例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的// 输出是重复的数字2或者3. 解题思路: 不能修改数组,可以创建一个长度为n+1的辅助数组,空间复杂度为O(n). 如果用时间换空间的话,可以使用二分查找的思想. 元素范围为1~n,但是有n+1

[题目2]不修改数组找出重复的数字

代码实现: package j2; /** * 不修改数组找出重复的数字 * Created by admin on 2019/5/14. */ public class FindDuplicate3 { public static void main(String[] args) { int arr[] = {2,3,5,4,3,2,6,7}; System.out.println(duplicate(arr,arr.length)); } public static int duplicat

一起来刷《剑指Offer》——不修改数组找出重复的数字(思路及Python实现)

数组中重复的数字 在上一篇博客中<剑指Offer>-- 题目一:找出数组中重复的数字(Python多种方法实现)中,其实能发现这类题目的关键就是一边遍历数组一边查满足条件的元素. 然后我们在博客用最复杂的方式学会数组(Python实现动态数组)这篇博客中介绍了数组这一结构的本质,并自己动手实现了一个动态数组. 今天我们介绍一下另一道来自<剑指Offer>的关于数组的面试题--不修改数组找出重复的数字. 不修改数组找出重复的数字 题目二:不修改数组找出重复的数字 给定一个长度为 n+

不修改数组找出重复的数字(c语言)

让人瑟瑟发抖的面试题... 来我们看一下题目在一个 长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改输入的数组.注意:时间复杂度O(n),空间复杂度O(1) 找出数组中重复的数字(c语言)怎么解决勒???分析:利用题目中元素处于1~n的范围,把元素分为两组,判断两组元素个数,如果大于范围,则重复的数字就在这个范围内.例如:1~3范围中有4个数,说明其中至少有一个重复的数字.按此二分下去,将会剩下一个数字有两个,最后输出

2015年 【华为c++技术面试题】找出重复的数字

面试题目: 1-100共100个数,外加一个重复的数字,共101个:这101个数是乱序的,让你找出这个重复的数字: 解题思路: 这个重复的数=这101个数的和-5050(1-100的和): C++代码: 结果展示:

数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数

问题描述: 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数. 算法一: 对数组a[n]进行冒泡排序,如果冒泡所得的最值和前一个最值相等,则该最值为重复的数. 分析: 该算法时间复杂度最坏的情况为O(n的2次方),在空间开销上只需要一个额外的交换空间. 如何将时间开销减小呢?下面给出另外一种算法 算法二: 给定另外一个数组b[n],将a[n]中的数作为数组b的索引,然后遍历b[n],如果未访问过,则标记:如果已经访问过,则该索引就为重复的数. 分析: 该算法时间复杂度能够达到最

从一千万条短信中找出重复次数最多的前10条

题目:      有1千万条短信,有重复,以文本文件的形式保存,一行一条.请用5分钟时间,找出重复出现最多的前10条. struct TNode { BYTE* pText; //直接指向文件映射的内存地址 DWORD dwCount; //计算器,记录此节点的相同短信数 TNode* ChildNodes[256]; //子节点数据,由于一个字母的ASCII值不可能超过256,所以子节点也不可能超过256 TNode() { //初始化成员 } ~TNode() { //释放资源 } }; /

sql从某不连续的数字中将其分段并找出缺失的数字并分段

首先做准备数据 1 CREATE TABLE #tempsource(col NVARCHAR(100)) 2 3 INSERT INTO #tempsource (col) VALUES('20140100001') 4 INSERT INTO #tempsource (col) VALUES('20140100002') 5 INSERT INTO #tempsource (col) VALUES('20140100003') 6 INSERT INTO #tempsource (col)

两个有序数组找出相同数据

两个有序数组找出相同数据,要求最简单的算法复杂度. class Program { static void Main(string[] args) { int Low = 0; int[] m = new int[] { 2, 4, 6, 9, 12, 13, 15, 16 }; int[] n = new int[] { 3, 5, 9, 12, 15 }; foreach (int item in m) { Search(n, ref Low, n.Length - 1, item); }