剑指 Offer 22. 链表中倒数第k个节点

94 阅读2分钟

前言:剑指offer刷题系列

问题:

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.

思路:

这段代码定义了一个名为 getKthFromEnd 的函数,它接受两个参数:head 和k。head 是一个链表的头节点,k 是一个整数。

首先,代码创建了两个变量 a 和 b,并将它们都初始化为头节点。

接着,代码进入一个循环,循环次数为 k-1。在循环中,将 a 设置为 a.next。

然后,代码进入另一个循环,循环条件是 a 和 a.next 都不为 null。在循环中,将 b 设置为 b.next,将 a 设置为 a.next。

最后,返回 b。

这段代码的作用是找到链表中倒数第 k 个节点。它使用了双指针的方法,先让指针a 向前移动 k-1 步,然后同时移动指针a 和指针b,直到指针 a 到达链表尾部。此时指针 b 指向的就是倒数第 k 个节点。

基于上述思考,代码如下:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var getKthFromEnd = function(head, k) {
    let a=head,b = head
    for(let i = 0;i < k-1;i++){
        a = a.next
    }
    while(a && a.next){
        b = b.next
        a = a.next
    }
    return b
};

执行结果如下图:

image-20230713155224439.png

修改后的代码,看起来更舒适:

var getKthFromEnd = function(head, k) {
    let fast = head,slow = fast
    while(k--){
        fast = fast.next
    }
    while(fast){
        fast = fast.next
        slow = slow.next
    }
    return slow
};

python 版本

思路

就是使用快慢指针思想,让快指针先走k个节点,然后两个指针一起走,当快指针到链尾时,慢指针就是倒数第k个节点

代码如下

class Solution:
    def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
        first = head
        last = head
        while k:
            first = first.next
            k -= 1
        while first:
            first = first.next
            last = last.next
        return last

执行结果如下:

image.png

学到的知识点:

  • 快慢指针是一种常用的算法技巧,它使用两个指针,一个快指针和一个慢指针,以不同的速度遍历数据结构(如链表或数组)。快慢指针常用于解决一些特定的问题,例如判断链表是否有环,寻找链表的中间节点,寻找链表的倒数第 k 个节点等。
  • 快慢指针可以用来判断链表是否有环。具体方法是,使用两个指针,一个快指针和一个慢指针,同时从链表头节点开始遍历链表。快指针每次移动两步,慢指针每次移动一步。如果链表中存在环,那么快指针和慢指针最终会在环内相遇;如果链表中不存在环,那么快指针会先到达链表尾部。