PHP K 个一组翻转链表(递归相关)- LeetCode 25

365 阅读4分钟

「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

上一篇文章我们说了PHP 两两交换链表中的节点(递归相关)- LeetCode 24

今天说一下两两交换链表节点的进阶版,在一个链表中,K 个节点一组翻转链表的实现。

image.png

实现思路

在讲K个节点一组翻转链表之前,我们先说一下两两交换链表的节点,它的思路对于我们实现今天的题目很有帮助。

两两交换链表节点时,原链表的第1个节点变成了新链表的第2个节点,由于原链表的第2个节点之后的节点还没有完成交换,所以新链表的第2个节点的指向,需要等待原链表后面的节点交换完成之后才能被赋值。以此类推就实现了两两交换链表中的节点。

那么实现k个节点一组翻转链表呢?

不管k的值是多少,原链表的第1个节点,就会变成新链表中的最后1个节点。那么由于原链表中的第k个节点之后节点由于没有没完成翻转,所以新链表中最后1个节点的指向,需要等待原链表后面的节点完成翻转之后才能被赋值。以此类推就实现了k个节点一组翻转链表。

刚才我们只是把翻转之后的链表连接在一起,但是我们还没有实现在k个节点中如何翻转。

由于实现两个节点翻转,只需要根据当前节点的next,就可以获取第2个节点,然后把第2个节点当作头节点。

由于k的不确定,我们无法直接获取最后一个节点,把它当作新链表的头节点。我们需要实现的是k个节点翻转,实际上就是k个节点的倒叙。

我们在遍历这k个节点时,由于我们不能直接获取新链表中的头节点,但我们可以确定当前节点的上一个节点。

由于第一个节点没有上一个节点,我们假设第一个节点的上一个节点为 NULL,每遍历一个节点,由于我们知道上一个节点,那么我们把上一个节点的next指向当前节点,就实现了和上一个节点的交换。遍历完成后,就完成了k个节点的翻转。

完成代码

image.png

第474-476行代码,如果当前节点为空,说明链表已没有节点;如果当前节点的下一个节点为空,说明链表中只有一个节点;如果k为1,则说明不用翻转。这三种情况直接返回当前节点。

第478-484行代码,由于需要K个节点翻转,如果链表剩余的节点不足,则直接返回剩余节点。

第486-494行代码,这段代码实现了k个节点翻转。定义一个虚拟的节点$prev, $num变量表示遍历到第几个节点,通过控制$num实现k个节点翻转。

第489-490行代码,我们先把当前节点$current的下一个节点赋值给一个变量,因为我们需要给当前节点的指向重新赋值,需要重新指向原链表中,当前节点的上一个节点$prev

第491行代码,当遍历下一个节点时,下一个节点的上一个节点就是当前节点,所以我们需要给表示当前节点上一个节点的$prev赋值为当前节点。

第492行代码,由于需要不断移动链表,所以给当前节点赋值为下一个节点,用于下次遍历需要。

第496行代码,上面我们已经实现了k个节点的翻转,但是原链表的第一个节点变成新链表的最后一个节点后,它的指向需要等待后面的节点完成翻转后才能确定,所以我们把第k+1个节点当作新链表重复上面的操作。

第498行代码,$prev就是翻转完成后的新链表,把分段完成翻转的链表返回,全部连接起来就是翻转完成后的链表。