【Java】 剑指offer(2) 不修改数组找出重复的数字
本文参考自《剑指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)
【Java】 剑指offer(2) 不修改数组找出重复的数字的更多相关文章
- 一起来刷《剑指Offer》——不修改数组找出重复的数字(思路及Python实现)
数组中重复的数字 在上一篇博客中<剑指Offer>-- 题目一:找出数组中重复的数字(Python多种方法实现)中,其实能发现这类题目的关键就是一边遍历数组一边查满足条件的元素. 然后我们 ...
- 《剑指offer》第三_二题(不修改数组找出重复的数字)
// 面试题3(二):不修改数组找出重复的数字 // 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至 // 少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改 ...
- 【Offer】[3-2] 【不修改数组找出重复的数字】
题目描述 思路分析 Java代码 代码链接 题目描述 在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的. 请找出数组中任意一个重复的数字,但不能修改输入的数组. ...
- Acwing 14. 不修改数组找出重复的数字
题目地址 https://www.acwing.com/problem/content/description/15/ 来源:剑指Offer 给定一个长度为 n+1n+1 的数组nums,数组中所有 ...
- 【剑指 Offer】03.1.不修改数组找出重复的数字
找出数组中重复的数字. 在一个长度为 n + 1 的数组 nums 里的所有数字都在 1-n 的范围内.所以数组中至少有一个是重复的.请找出数组中任意一个重复的数字. 示例 1: 输入: [2, 3, ...
- 剑指offer笔记面试题3----数组中重复的数字
题目一:找出数组中重复的数字.在一个长度为n的数组里的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字.例如 ...
- 一起来刷《剑指Offer》-- 题目一:找出数组中重复的数字(Python多种方法实现)
数组中重复的数字 最近在复习算法和数据结构(基于Python实现),然后看了Python的各种"序列"--比如列表List.元组Tuple和字符串String,后期会写一篇博客介绍 ...
- JS 剑指Offer(一) 数组中的重复数字
题目:在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字. 分析: ...
- 讲两个int 数组找出重复的数字 用最少的循环
int a[] = {1,3}; int b[] = {1,3,5}; int size = a.length>b.length ?a.length:b.length; int valueA = ...
随机推荐
- The provider is not compatible with the version of Oracle client
保留下安装文件夹里的所有文件.然后把我那个很小应用软件(需要访问远程的oracle数据库)放在这个文件夹里.删除一下直接感觉无用的文件,先抽取可 能用不着的文件,保留放在另一个备用的文件夹里,然后运行 ...
- Linux - DDOS检测
netstat netstat -na #显示所有连接到服务器的活跃的网络连接 netstat -an | grep : | sort # 只显示连接到80段口的活跃的网络连接,80是http端口, ...
- java工程师之旅-一个月工作心得
不知不觉,在工作中已经度过一个月,距离上次写文章已经好几个月了,正好还有二十分钟下班,抽点时间来写一下博文,写一下心得. 首先说一下,在我工作之前,做了一个项目,和一个外校大四的学生做一个毕业设计,一 ...
- 发送http请求的方法
在http/1.1 协议中,定义了8种发送http请求的方法 get post options head put delete trace connect patch. 根据http协议的设计初衷,不 ...
- 线路板(PCB)制作流程中英文对照表
线路板(PCB)流程术语中英文对照流程简介:开料--钻孔--干膜制程--压合--减铜--电镀--塞孔--防焊(绿漆/绿油) --镀金--喷锡--成型--开短路测试--终检--雷射钻孔A. 开料( Cu ...
- Python中的元类
从前面"Python对象"文章中了解到,在Python中一切都是对象,类可以创建实例对象,但是类本身也是对象. class C(object): pass c = C() prin ...
- JS实现双击内容变为可编辑状态
在一些网站上我们经常看到交互性很强的功能.一些用户资料可以直接双击出现文本框,并在此输入新的资料即可修改,无需再按确定按钮等.. 我在网上查了很多资料,但都有一个小bug,就是当获取焦点后,光标的位置 ...
- nodejs的process模块如何获取其他进程的pid
var cmd=process.platform=='win32'?'tasklist':'ps aux'; var exec = require('child_process').exec; var ...
- HTML学习笔记01-HTML简介
主要是为了做接口测试,试着自己写爬虫,所以学习一下HTML一些基础的东西,方便用来解析网页.学习内容主要来自菜鸟教程的HTML教程,W3school的HTML 超文本标记语言(英语:HyperText ...
- IIS8.5 运行WCF
背景 这是一个项目给其它项目提供接口,其实现在哪有用WCF的了,都是restful.不过.net在这方面还是不错,比java强些,java竟然很多采用自己解析xml方式来做Web服务.难以理解. 但是 ...