一. 问题描述
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例 1:
输入: [1,3,4,2,2]
输出: 2
示例 2:
输入: [3,1,3,4,2]
输出: 3
说明:
不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。
二. 解题思路
本题思路:弗洛伊德循环解法求解。
第一种:弗洛伊德循环解法,通过题目首先,我们可以很容易地证明问题的约束意味着必须存在一个循环。因为 nums 中的每个数字都在 1 和 n 之间,所以它必须指向存在的索引。
对于环的问题,我们可以采用弗洛伊德循环检测方法进行求解。
步骤一:通过数学了解环的入口就是重复数,例如对于数组[2,5,9,6,9,3,8,9,7,1],所得到的环根据第一个数组下标得到某一个数,然后在将这个数当成下标另一个数,如果存在重复数,则肯定有指向那个重复数的多个下标,造成环。
步骤二:证明从开头走到环入口点与相遇后走到环入口点的距离相等,证明在这个网址https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-/
步骤三:开始设计程序,首先建立快慢指针,fast走两步,low走一步,注意,是根据将数组的值当成下标来进行走,找到相遇点fast==low。
步骤四:然后将fast指向头部,与low接着每次走一步,当相遇时,相遇点就是所求的重复数。
三. 执行结果
执行用时 :0 ms, 在所有 java 提交中击败了100.00%的用户
内存消耗 :37.9 MB, 在所有 java 提交中击败了84.49%的用户
四. Java代码
public int findDuplicate(int[] nums) { int first=nums[0]; int second=nums[0]; do{ second=nums[second]; second=nums[second]; first=nums[first]; }while(second!=first); second=nums[0]; while(second!=first) { first=nums[first]; second=nums[second]; } return first; }