LeetCode 287 Find the Duplicate Number

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a247027417/article/details/83541073

之前写了一篇Duplicate Number的博客了,和学长讨论的时候发现,原来的解是一个错误解。虽然可以提交而且时间复杂度很小,但是不满足不修改原数组的条件。那一篇博客详见Duplicate Number 错误blog

【解析】

将找重复值变成寻找环形链表的入口节点问题

一个n+1长的数组中放置1到n,一定会出现相同的数字。因为数组中的变量和数组下标的关系,可以联想到,将数组看成一个链表。数组中的值是链表中节点存储的值,同时也代表了next的位置。

比如  : nums=[1, 3, 5, 5, 4, 2]  ,首先是1,所以节点数据为1,next的下标为1,第二个节点为nums[1]=3,next的下标为3,第三个节点为nums[3]=5,next的下标为5,第四个节点的数据为nums[5]=2,next的下标为2,第五个节点为nums[2]=5,下一个next的下标为5,形成了环。可以看成链表, 1->3->5->2->5,而成环的这个节点,就是重复出现的值,因此,这道题变成寻找环的入口。(注意:之所以可以看成环,是因为不存在0,如果0出现在数组下标为0的位置,就不能这么做)

寻找环形列表入口

整体步骤

1. 设置快慢指针,快指针每次步进2个,慢指针每次步进1个。

2. 当快慢指针第一次相遇时,到达图中红点,此时将快指针至回原点,同时设置其步长为1个

3. 当快慢指针再次相遇时,输出环形入口值,即为重复值

代码

public class Solution4 {
	public int findDuplicate(int[] nums) {
		if(nums.length <= 1)
			return -1;
		// Ptr_slow 和Ptr_fast设置的值为其走了一步之后的值,不然需要在while中判断两者为0的情况
		int Ptr_slow = nums[0];
		int Ptr_fast = nums[nums[0]];
		// 找到红点
		while(Ptr_slow!=Ptr_fast)
		{
			Ptr_slow = nums[Ptr_slow];
			Ptr_fast = nums[nums[Ptr_fast]];
		}
		// 将快指针至回原点,步长变1
		Ptr_fast = 0;
		while(Ptr_slow != Ptr_fast)
		{
			Ptr_slow = nums[Ptr_slow];
			Ptr_fast = nums[Ptr_fast];
		}
		
		return Ptr_fast;
	}
}

猜你喜欢

转载自blog.csdn.net/a247027417/article/details/83541073