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 和 ...
随机推荐
- August 12th 2017 Week 32nd Saturday
That which does not kill us makes us stronger. 但凡不能杀死你的,最终都会使你更强大. Seemingly I have heard this from ...
- vs项目同步到gitee方法
前提:vs配置过登录后 进入命令行后执行: git push --set-upstream origin master
- extern “C”
http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html 问题:extern “C” 在C++环境下使用C函数的时候,常常 ...
- ajax上传表单的俩种方式
1.用h5对象上传表单(图片) var formData = new FormData(); formData.append("authenticity_token", '1212 ...
- 7、Web Service-IDEA-jaxws规范下的 服务端/客户端 开发
前提简介:这里之后即使基于IDEA进行开发的,风格与之前有些不同之处! 1.服务端的开发 1.创建新的项目 2.pom.xml 添加开发时所需要的依赖 <?xml version="1 ...
- PHP延迟静态绑定(本文属于转发)
这段时间看项目后台的PHP代码,看到了类似于以下的一段代码,我把它抽出来: <?php class DBHandler { function get() {} } class MySQLHand ...
- Kali-linux使用NVIDIA计算机统一设备架构(CUDA)
CUDA(Compute Unified Device Architecture)是一种由NVIDIA推出的通用并行计算架构,该架构使用GPU能够解决复杂的计算问题.它包含了CUDA指令集架构(ISA ...
- python多线程练习
import threading from time import sleep,ctime def print1(): for i in range(10): print(i,end='') prin ...
- C#回调实现的一般过程
C#回调实现的一般过程 C#的方法回调机制,是建立在委托基础之上的,下面给出它的典型实现过程. (一) 定义.声明回调 Delegate void DoSomeCallBack(type para); ...
- 如何导出SHP文件中的点坐标?(ArcGIS10)
行政区域坐标,网上流传较广的版本是包括海域的,假如你仅仅想要把陆地边界绘出,那么怎么办呢? 现在讲一下用arcgis 10从shp线.面文件中获取对应区域的坐标呢?(点图层忽略第一步) 首先用在arc ...