对于一个长度为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 (寻找重复数字)的更多相关文章

  1. [LeetCode] Find the Duplicate Number 寻找重复数

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...

  2. [LeetCode] 287. Find the Duplicate Number 寻找重复数

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...

  3. [LeetCode] Find Duplicate Subtrees 寻找重复树

    Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only ne ...

  4. 287 Find the Duplicate Number 寻找重复数

    一个长度为 n + 1 的整形数组,其中的数字都在 1 到 n 之间,包括 1 和 n ,可知至少有一个重复的数字存在.假设只有一个数字重复,找出这个重复的数字.注意:    不能更改数组内容(假设数 ...

  5. LeetCode Find the Duplicate Number 找重复出现的数(技巧)

    题意: 有一个含有n+1个元素的数组,元素值是在1-n之间的整数,请找出其中出现超过1次的数.(保证仅有1个出现次数是超过1的数) 思路: 方法一:O(nlogn).根据鸽笼原理及题意,每次如果< ...

  6. LeetCode 287. Find the Duplicate Number (找到重复的数字)

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...

  7. 287. Find the Duplicate Number 找出数组中的重复数字

    [抄题]: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive ...

  8. 64.Find the Duplicate Number(发现重复数字)

    Level:   Medium 题目描述: Given an array nums containing n + 1 integers where each integer is between 1 ...

  9. Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)

    Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和  ...

随机推荐

  1. Connection to linux server with ORACLE SQL DEVELOPER

    1.Link name is random 2.username and password is database account 3.host name  is ip address  ifconf ...

  2. 数据链路层 点对点协议 PPP

    点对点协议 PPP 一. PPP 协议应满足的需求 简单.提供不可靠的数据报服务,比IP协议简单,不需要纠错,不需要序号,不需要流量控制. 工作方式:接收方每收到一个帧就进行CRC校验,如正确就接受该 ...

  3. System.Buffer 以字节数组(Byte[])操作基元类型数据

    1. Buffer.ByteLength:计算基元类型数组累计有多少字节组成. 该方法结果等于"基元类型字节长度 * 数组长度" , , }; , , }; , , }; Cons ...

  4. Production-Ready Beanstalkd with Laravel 4 Queues

    原文地址:http://fideloper.com/ubuntu-beanstalkd-and-laravel4 Note: TL;DR version at the bottom! Queues a ...

  5. Discuz3.3注册程序修改添加记录推荐人账号

    Discuz3.3注册入口地址为:member.php?mod=register 一.member.php: 打开之后,代码非常简单. 其中有一句: $mod = !in_array($discuz- ...

  6. jq实现拖拽

    $("body").delegate( ".msg-layer",{ mousedown: function (e) { var el = $(".m ...

  7. Guava包学习--Table

    Table,顾名思义,就好像HTML中的Table元素一样,其实就是行+列去确定的值,更准确的比喻其实就是一个二维矩阵. 其实它就是通过行+列两个key去找到一个value,然后它又containsv ...

  8. [USACO11JAN]Roads and Planes

    嘟嘟嘟 这道题他会卡spfa,不过据说加SLF优化后能过,但还是讲讲正解吧. 题中有很关键的一句,就是无向边都是正的,只有单向边可能会有负的.当把整个图缩点后,有向边只会连接在每一个联通块之间(因为图 ...

  9. Python常用库之三:Matplotlib

    导入模块 import matplotlib.pyplot as plt import seaborn as sb 绘制条形图 countplot(data:数据集, x:x坐标轴, color:条形 ...

  10. 9、RabbitMQ-集成Spring

    spring封装RabbitMQ看官网:https://spring.io/projects/spring-amqp#learn 开发时根据官网的介绍进行开发,具体的说明都有具体的声明 1.导入依赖 ...