本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集

题目 

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

思路

  数组长度为n+1,而数字只从1到n,说明必定有重复数字。可以由二分查找法拓展:把1~n的数字从中间数字m分成两部分,若前一半1~m的数字数目超过m个,说明重复数字在前一半区间,否则,在后半区间m+1~n。每次在区间中都一分为二,知道找到重复数字。

  更简单的思路:把该数组看作一个链表,下标代表当前结点,值代表next指针,具体参考Find the Duplicate Number,时间复杂度仅为O(n)

测试用例

  1.数组中带一个或多个重复数字

  2.数组中不包含重复的数字

  3.无效输入测试用例(空数组,数组数字越界等)

完整Java代码

(含测试代码)

/**
*
* @Description 不修改数组找出重复的数字
*
* @author yongh
* @date 2018年7月16日 上午11:47:44
*/ /*
* 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至
* 少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的
* 数组。例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的
* 输出是重复的数字2或者3。
*/
public class FindDuplication2 { /**
* 找到数组中一个重复的数字
* 返回-1代表无重复数字或者输入无效
*/
public int getDuplicate(int[] arr) {
if (arr == null || arr.length <= 0) {
System.out.println("数组输入无效!");
return -1;
}
for (int a : arr) {
if (a < 1 || a > arr.length - 1) {
System.out.println("数字大小超出范围!");
return -1;
}
}
int low = 1;
int high = arr.length - 1; // high即为题目的n
int mid, count;
while (low <= high) {
mid = ((high - low) >> 2) + low;
count = countRange(arr, low, mid);
if (low == high) {
if (count > 1)
return low;
else
break; // 必有重复,应该不会出现这种情况吧?
}
if (count > mid - low + 1) {
high = mid;
} else {
low = mid + 1;
}
}
return -1;
} /**
* 返回在[low,high]范围中数字的个数
*/
public int countRange(int[] arr, int low, int high) {
if (arr == null)
return 0; int count = 0;
for (int a : arr) {
if (a >= low && a <= high)
count++;
}
return count;
} // ==================================测试代码==================================
/**
*数组为null
*/
public void test1() {
System.out.print("test1:");
int[] a = null;
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重复数字为:" + dup);
} /**
*数组数字越界
*/
public void test2() {
System.out.print("test2:");
int[] a = { 1, 2, 3, 4 };
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重复数字为:" + dup);
} /**
*数组带重复数字
*/
public void test3() {
System.out.print("test3:");
int[] a = { 1, 2, 3, 2, 4 };
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重复数字为:" + dup);
} public static void main(String[] args) {
FindDuplication2 f2 = new FindDuplication2();
f2.test1();
f2.test2();
f2.test3();
}
}

  

test1:数组输入无效!
test2:数字大小超出范围!
test3:重复数字为:2

FindDuplication2

复杂度

时间复杂度说明:函数countRange()将被调用O(logn)次,每次需要O(n)的时间。

时间复杂度:O(nlogn)  (while循环为O(logn),coutRange()函数为O(n))

空间复杂度:O(1)

更多:《剑指Offer》Java实现合集

【Java】 剑指offer(2) 不修改数组找出重复的数字的更多相关文章

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

    数组中重复的数字 在上一篇博客中<剑指Offer>-- 题目一:找出数组中重复的数字(Python多种方法实现)中,其实能发现这类题目的关键就是一边遍历数组一边查满足条件的元素. 然后我们 ...

  2. 《剑指offer》第三_二题(不修改数组找出重复的数字)

    // 面试题3(二):不修改数组找出重复的数字 // 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至 // 少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改 ...

  3. 【Offer】[3-2] 【不修改数组找出重复的数字】

    题目描述 思路分析 Java代码 代码链接 题目描述 在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的. 请找出数组中任意一个重复的数字,但不能修改输入的数组. ...

  4. Acwing 14. 不修改数组找出重复的数字

    题目地址  https://www.acwing.com/problem/content/description/15/ 来源:剑指Offer 给定一个长度为 n+1n+1 的数组nums,数组中所有 ...

  5. 【剑指 Offer】03.1.不修改数组找出重复的数字

    找出数组中重复的数字. 在一个长度为 n + 1 的数组 nums 里的所有数字都在 1-n 的范围内.所以数组中至少有一个是重复的.请找出数组中任意一个重复的数字. 示例 1: 输入: [2, 3, ...

  6. 剑指offer笔记面试题3----数组中重复的数字

    题目一:找出数组中重复的数字.在一个长度为n的数组里的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字.例如 ...

  7. 一起来刷《剑指Offer》-- 题目一:找出数组中重复的数字(Python多种方法实现)

    数组中重复的数字 最近在复习算法和数据结构(基于Python实现),然后看了Python的各种"序列"--比如列表List.元组Tuple和字符串String,后期会写一篇博客介绍 ...

  8. JS 剑指Offer(一) 数组中的重复数字

    题目:在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字. 分析: ...

  9. 讲两个int 数组找出重复的数字 用最少的循环

    int a[] = {1,3}; int b[] = {1,3,5}; int size = a.length>b.length ?a.length:b.length; int valueA = ...

随机推荐

  1. Jsp (Java Server Pages)相关知识九大内置对象和四大作用域

    一.初识JSP Jsp页面的组成:静态内容.指令.表达式.小脚本.声明.标准动作.注释等元素构成 Url:统一资源定位符 Url组成:协议.主机名(包括端口号).路径 1.注释的方式: 1.HTML注 ...

  2. IDA Pro使用(静态分析+动态调试)

    链接:http://skysider.com/?p=458 IDA Pro使用(静态分析+动态调试) 1.静态分析 IDA FLIRT Signature Database —— 用于识别静态编译的可 ...

  3. 【BZOJ4827】【HNOI2017】礼物

    强省HN弱省HA……(读作强省湖南弱省蛤 原题: 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个 ...

  4. POJ1251 Jungle Roads【最小生成树】

    题意: 首先给你一个图,需要你求出最小生成树,首先输入n个节点,用大写字母表示各节点,接着说有几个点和它相连,然后给出节点与节点之间的权值.拿第二个样例举例:比如有3个节点,然后接下来有3-1行表示了 ...

  5. python中argparse

    python中argparse 在很多编程语言中,运行程序可以直接使用function(a,b,……)运行程序,但是在python中就无法实现,那么我们如何在命令行中传递参数呢?在python的中,有 ...

  6. Faster rcnn代码理解(2)

    接着上篇的博客,咱们继续看一下Faster RCNN的代码- 上次大致讲完了Faster rcnn在训练时是如何获取imdb和roidb文件的,主要都在train_rpn()的get_roidb()函 ...

  7. 【Shell】带颜色输出(白底x色)

    echo -e "\033[31mHello World.\033[0m" 红色31m 绿色32m 黄色33m 蓝色34m 黑色30m 白色37m 紫色35m 深绿色36m

  8. linux 下camera调试笔记【转】

    转自:https://blog.csdn.net/kevinx_xu/article/details/8801931 linux camera调试 2011-10-23 10:43:37|  分类:  ...

  9. Android主题切换

    一.APK文件方式:(CM9方案) 我们知道Android给每个APK进程分配一个单独的用户空间,其manifest中的userid就是对应一个Linux用户的(Android 系统是基于Linux) ...

  10. vw 解决方案

    vw 解决方案 1. 安装并配置PostCss插件 复制代码代码如下: npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-w ...