浅谈双指针技巧(三)利用快慢指针,查找链表中指定位置节点

前面两篇文章主要介绍了,快慢指针在链表环中的应用。除此之外,我们还常常利用快慢指针来查找单向链表中指定位置的节点。
常见的经典题目有:
1、查找倒数i位置的的节点
2、查找中间节点
我们依次来看
一、查找快慢指针查找单链表中位于倒数第i个位置的元素
力扣 剑指 Offer 22. 链表中倒数第k个节点 (https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/)
如果没有提前做过准备,想要解决类似问题,只能通过缓存等方式来解决。但是通过快慢指针,可以很巧妙的解决该问题。
思路是这样的:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
快慢指针同时指向head节点。接着慢指针不动,快指针向前移动i步。之后快慢指针同速前移动。直至快指针先到终点,此时慢指针,所处的位置就是倒数第i个节点的位置。
就像下图,假设右侧小人先跑40m,随后两者同速前进,则左侧小人距离右侧小人始终为40m。这样当右侧小人到达终点时,左侧小人的位置恰好为倒数40m处:

 代码也很简单:

 1     public ListNode getKthFromEnd(ListNode head, int k) {
 2         ListNode fast = head;
 3         ListNode tail = head;
 4         for (int i = 0; i < k-1; i++) {
 5             fast = fast.next;
 6         }
 7         while (fast.next != null) {
 8             fast = fast.next;
 9             tail = tail.next;
10         }
11         return tail;
12     }

 这个场景其实除了双指针的解法,还可以通过递归出栈的方式解决,感兴趣的同学可以自己想想

二、查找链表中间位置的节点
力扣 876. 链表的中间结点 (https://leetcode.cn/problems/middle-of-the-linked-list/)
此题与上题类似,仍然可以采用快慢指针的形式。
区别是不再同速保持固定距离,而是快指针每次走两步,慢指针走一步。
这样假设快指针遍历了2N个节点,慢指针就是便宜了N个节点。
如果你自己考虑这个问题,你会发现事情没有这么简单:
这里会涉及到两个问题:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
1、链表长度是不是偶数。
2、链表如果是偶数,那么中间节点应该是中间位置左侧节点 还是右侧节点。
如果链表长度奇数的话,那么要注意快指针最后一次移动是不能走两步的。
如果链表长度是偶数的话,我们取中间位置的右侧节点。代码如下:

 1     public ListNode middleNode(ListNode head) {
 2         ListNode fast = head;
 3         ListNode low = head;
 4         while (true) {
 5             if (fast.next == null) {
 6                 return low;
 7             }
 8             low = low.next;
 9             fast = fast.next;
10             if (fast.next != null) {
11                 fast = fast.next;
12             }
13         }
14     }

 细想一下,这种思路其实除了可以找到中间节点位置,还可以找到1/3处节点位置,1/5处节点位置。

posted @ 2022-09-09 10:49  王若伊_恩赐解脱  阅读(229)  评论(0编辑  收藏  举报