寻找重复数(LeetCode287)-快慢指针法寻找圈入口的数学证明

文章目录

关于题目

没问题,一切都没问题,这个方法也很好理解,(但是不好想)。but,but如何证明?
我看了一圈评论席,要么是二分,要么是抄的快慢指针,没一个说数学证明的(甚至还有好多人都不看题目要求的,使用了o(n)的空间复杂度)。。。
本题最好的解法是利用快慢指针来寻找圈的入口,快慢指针的概念这里我就不多说了。

先讲一下题目:
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

	示例 1:
	输入: [1,3,4,2,2]
	输出: 2

	示例 2:
	输入: [3,1,3,4,2]
	输出: 3

针对这个问题,很多人的做法是这样,利用快慢指针。

	[1,3,4,2,2]
	(0,1,2,3,4)

上述中[]中是nums,而()中是对应的索引,我们把其当成是链表,索引代表当前值,而索引所在的nums的值是next。
即0的next是1,1的next是3,2的next是4,3的next是2,4的next是2。
如此,我们便有了一个链表,我们利用快慢指针从0节点出发(从数组的0号索引位出发),0的下一个是1,1的下一个是3,3的下一个是2,2的下一个是4,4的下一个是2。很明显,这样快慢指针就找到了一个圈。当快慢指针重合时,便是停在了2,便是找到了重复的值。

那么下面我们就来搞一下数学证明吧,即证明为什么从0号节点出发,一定能找到重复点?或者说为什么从0号节点出发,就一定能找到圈的入口?

数学证明

在走整个证明思路之前,我们先讲三个引理:

  1. 对于该题,假设有n个点,每个的点的出度为1,而入度是{0,1…}。针对该题,我们是这样定义节点之间的边(有向边)的,索引值为当前节点,而索引值对应的nums值是next。于是,我们很容易发现,每个节点都有且只有一个next,即每个节点都有且只有一条出边;但并不是每个节点都有被其他节点指向(因为重复点可能不只重复出现一次)。

  2. 该图一定有无向圈。我们除去0号节点,和0号节点所连的边,那么剩下的节点便是1-n号节点了。同时,我们可以发现,这1-n号节点的next都是在1-n号范围内的(由题意可得)。那么,也就是说,我们有n个节点,同时有n个边,则此时我们可以轻松的想到,这n个节点必有圈(无向圈,不考虑方向)。因为树的特点是n个点n-1条边嘛,但凡加一条边,就会成圈。

  3. 该图的圈一定是强连通圈。强连通圈是什么意思呢?看下图左图。 在这里插入图片描述

    即首尾相接,从一个点可以到圈里任意一个点(强连通),每条边的方向一定一致。
    那这里可能有人会问,那为什么一定是这样每条边都方向一致的圈呢?为什么不可能圈中的某条边和其余边的方向不同呢?比如上图右图这种?
    这种当然是不可能的,很明显,假设圈不是强连通的,那么必然有节点入度是2,对应的必然有节点出度是2。你看节点3,它的出度就是2了,这和我们的引理1相矛盾,所以我们的圈一定只能是上图左图那种强连通的圈。

有了上面3个引理,我们下面就好证明多了。

无论用例是什么数组(或者说给的什么图,或者说给的什么链表)。我们每次都是从0号节点进入。0号节点的特点是只有它指向别人,并没有人指向它(好孤单5555,所以这也是0号节点也是为什么我们选择称为起始点的原因)。
我们从0号节点出发,进入到包含1-n这n个节点的图中。
我们这里假设0号节点的next是M。很显然,M节点的值是属于[1,n]的。
那么我们的问题是,证明从M点出发,一定能重复遍历[1,n]中某个点。
即我们要证明,从M点出发,一定能经过一个圈(圈的入口便是重复点)。

好,有了证明的题目,我们可以开始证明了。

我们分类讨论:

  • 情况(1):M点就在圈中。那么显然,从M点闭能够到一个圈,且整个圈的入口就是M,M便是我们要找的重复点(M点在圈内被指向一次,又被0号节点指向一次)。
  • 情况(2):M点不在圈中,那我们顺着M的next,M的next的next一直往下走,则必然能够无限制的走下去。(这里为啥能无限制走下去?可能走到某个点就戛然而止无法继续往下走吗?不可能,因为上面我们已经说了,每个节点都有next,所以必然能够一直走下去)。当我一直走n步,因为总共的节点只有n个节点,则必然会在这n步中遍历到两个重复的节点,也就是我必然会走过一个圈。

于是证明完毕。

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/109636287