Find the Duplicate Number (寻找重复数字)
对于一个长度为n+1的数组,其中每一个值的取值范围是[1,n],可以证明的是必然存在一个重复数字(抽屉原理),假设仅存在一个重复数字,找到他。
举例:输入:[1,3,4,2,1],输出:1
自己做的时候,要么时间复杂度到o(n2),要么需要额外的存储空间利用hashset,下面来分析一下leetcode上别人的算法吧。
方法一:通过图论中环的有关知识解决
public int findDuplicate(int[] nums) {
// Find the intersection point of the two runners.
int tortoise = nums[0];
int hare = nums[0];
do {
tortoise = nums[tortoise];
hare = nums[nums[hare]];
} while (tortoise != hare);
// Find the "entrance" to the cycle.
int ptr1 = nums[0];
int ptr2 = tortoise;
while (ptr1 != ptr2) {
ptr1 = nums[ptr1];
ptr2 = nums[ptr2];
}
return ptr1;
}
如果数组的每一个数的取值都是不重复的,那么可以选取特定的数值来使,不断通过索引值得到数值,再将新的数值作为索引值,循环下去可以得到一个链路。假定数组为[1,2,3,4,5],设定f(x),x是索引值,f(x)是值,并将得到的f(x)作为下一个输入,这样形成了一个链路,1->2->3->4->5;但是如果稍微做一下改变原数组为[1,2,3,4,1],那么链路将变为,1->2->3->4->1…,形成一个环路,这里的重复数字1就是构成环路的关键。
本题中就包含这样一个重复数字,所以数组nums一定会存在一个环路,问题变为如何查找环路起点问题,对于这种问题有这样一个算法,叫做弗洛伊德的循环寻找算法。在算法中会有两个指针一个快速指针每次移动两个步骤,一个慢速指针每次移动一个步骤,其中快速指针会提前进入循环并且在慢速指针进入循环后会与其相交。类似于操场跑圈,快速指针和慢速指针同时同宿舍出发,快速指针先到操场开始跑圈,慢速指针后到操场开始跑圈,但是快速指针一定会在某个时刻与慢速指针到达同一位置。

如何求取圆环起点位置(即重复的数字):
设定慢速指针与快速指针相交点距离环起点的距离为k,环周长为n,指针起点到环起点的距离为m,则慢速指针走过的距离为a = m+k+xn ;快速指针走过的距离为2a = m+k+yn,两者做差可以得到a = (y-x)n,是环长度的整数倍,如果将快速指针重置到起点,且将快速指针的移动距离改为1,那么当快速指针移动到圆环起点时,慢速指针移动距离为a+m,因为a是圆环长度的整数倍,所以慢速指针的位置也是在圆环起点,这样两者的相遇点即为圆环起点。
方法二:
public int findDuplicate_leetcode3(int[] nums) {
if (nums.length == 0 || nums == null)
return 0;
int low = 1, high = nums.length - 1, mid;
while (low < high) { //这个题不好用low+1<high,因为最后结果的两个值无从比较,是基于count的
mid = low + (high - low) / 2;
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] <= mid)
count++;
}
if (count > mid)
high = mid;
else
low = mid + 1;
}
return low;
}
根据题目中的条件,可以知道的是一定会有重复数字且只有一个重复数字,那么必然导致数组数值的不均匀分布(指的不是位置的不均匀,而是数值的取值不均匀),那么可以通过二分法来判别重复取值的数字在哪个部分,取数组的中值,计算大于和小于中值的数量,取数量较多的那份为新的数组,重复进行,最后到不可分时,得到的即为重复数字。
Find the Duplicate Number (寻找重复数字)的更多相关文章
- [LeetCode] Find the Duplicate Number 寻找重复数
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- [LeetCode] 287. Find the Duplicate Number 寻找重复数
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- [LeetCode] Find Duplicate Subtrees 寻找重复树
Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only ne ...
- 287 Find the Duplicate Number 寻找重复数
一个长度为 n + 1 的整形数组,其中的数字都在 1 到 n 之间,包括 1 和 n ,可知至少有一个重复的数字存在.假设只有一个数字重复,找出这个重复的数字.注意: 不能更改数组内容(假设数 ...
- LeetCode Find the Duplicate Number 找重复出现的数(技巧)
题意: 有一个含有n+1个元素的数组,元素值是在1-n之间的整数,请找出其中出现超过1次的数.(保证仅有1个出现次数是超过1的数) 思路: 方法一:O(nlogn).根据鸽笼原理及题意,每次如果< ...
- LeetCode 287. Find the Duplicate Number (找到重复的数字)
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- 287. Find the Duplicate Number 找出数组中的重复数字
[抄题]: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive ...
- 64.Find the Duplicate Number(发现重复数字)
Level: Medium 题目描述: Given an array nums containing n + 1 integers where each integer is between 1 ...
- Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)
Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 ...
随机推荐
- 3 Dockerfile指令详解-FROM&MAINTAINER&RUN
1.FROM指令 FROM centos #指定centos为基础镜像 2.MAINTAINER 指令 MAINTAINER @QQ.COM #指定维护人等信息,方便维护 3.RUN 命令 #新建 ...
- MYSQL数据库、用户、表等基础构建
MYSQL数据库.用户.表等基础构建: 1.->:创建数据库: 1.1. create schema [数据库名称] default character set utf8 collate utf ...
- Java 字符流与基本IO
字符流基类 java.io包中专门用于字符流处理的类,是以 Reader 和 Writer 为基础派生的一系列类.字符流以字符为单位,根据码表映射字符,一次可能读多个字节,只能处理字符类型的数据.Re ...
- win环境下使用sqlmap写shell + MYSQL提权(默认就是system权限)
今天在来一个mysql提权 (也可以说是默认system权限提的) 在被黑站点找到一个站 先教拿shell是有注入漏洞的 有可能是root权限的注入点 可以确定是有注入漏洞的 也得到了 物理路径 ...
- python BaseManager中register()的描述
register(typeid[, callable[, proxytype[, exposed[, method_to_typeid[, create_method]]]]]) A classmet ...
- 基于session和cookie的登录验证(CBV模式)
基于session和cookie的登录验证(CBV模式) urls.py """cookie_session URL Configuration The `urlpatt ...
- php filesize() 方法返回的文件大小异常
问题描述:需要生成一个 700k 大小左右的文件,相关代码如下: <?php $handle = fopen('./split.log', 'a+'); $result = 0; while( ...
- Sublime Text 3中文乱码问题解决
Sublime Text 3是我MacBook Pro最喜欢的代码编辑器,没有之一,因为她的性感高亮代码配色,更因为它的小巧,但是它默认不支持GBK的编码格式,因此打开GBK的代码文件,如果里面有中文 ...
- 1、Spring Cloud - 微服务简介
前言: 业界大牛马丁.福勒(Martin Fowler) 这样描述微服务: 论文网址:https://martinfowler.com/articles/microservices.html 就目前而 ...
- 俄罗斯方块 UWP 版
UWP跟 WPF编程模型一致,不过UWP做了精简,而且不同的系统的API还略有不同.不同的地方有以下几点: 1.动画.动画除了故事版,还有其它的实现方式. 2.异步方法.UWP中的方法调用,大部分都是 ...