【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 = ...
随机推荐
- mysql创建数据库指定编码格式
CREATE DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
- 3d图像识别基础论文:pointNet阅读笔记
PointNet 论文阅读: 主要思路:输入独立的点云数据,进行变换不变性处理(T-net)后,通过pointNet网络训练后,最后通过最大池化和softMax分类器,输出评分结果. 摘要: 相较于之 ...
- Django开发笔记六
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...
- [转]数据对齐对CPU的影响
[转]http://www.cnblogs.com/wuzhenbo/archive/2012/06/05/2537465.html 1.前言 在IBM开发社区上发现一篇叫'Data alignmen ...
- 找到多个与名为“Home”的控制器匹配的类型的解决方案
主地址:http://localhost:3412/Home/Index 区域地址:http://localhost:3412/T200/Home/Index 解决方法: 注册路由添加命名空间(nam ...
- sum行列合计
select sum(decode(cplb,'3',hj,0)) from lr_scsjdqdw t group by zcxmdm
- python中对列表的所有操作方法
列表: names = ['a','b','c','d'] 1.追加:names.append() >>> names.append('e') >>> names ...
- 现代C++之理解decltype
现代C++之理解decltype decltype用于生成变量名或者表达式的类型,其生成的结果有的是显而易见的,可以预测的,容易理解,有些则不容易理解.大多数情况下,与使用模板和auto时进行的类型 ...
- mysql数据库报错:InnoDB: Operating system error number 13 in a file operation
环境:centos6.5 x86_64 启动mysql发现日志报错(日志路径可以查看/etc/my.cnf的配置) 160722 10:34:08 [Note] Found 42570716 of 4 ...
- vmware下centos克隆功能对网络的设置
centos完成克隆功能后需要对网络进行设置 # cd /etc/udev/rules.d/ vim 70-persistent-net.rules 删除eth0的配置,将eth1该为eth0 编辑网 ...