个人评价:链表中指针的基础操作,加入合理的双指针操作

题目难度:🌟 (参考 LeeCode 简单🌟 、中等🌟 🌟 、困难🌟 🌟 🌟 )

另,通常算法题会考察分析时间复杂度和空间复杂度,可参考笔者之前的文章

「数据结构&算法」必知必会系列:3. 时间 & 空间复杂度(下)

链表中倒数第k个节点

题目描述

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

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

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

示例:

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

返回链表 4->5.

解题思路

需要到达倒数 k 个数,显然需要遍历到达链表尾部,可想到使用双指针:快指针到达 null,慢指针比快指针少走 k 次。

  1. 快、慢指针初始为 head
  2. 快指针先走 k 次
  3. 快、慢指针一起走,直至快指针指向 null 停止;慢指针即为所需

Go 代码如下:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getKthFromEnd(head *ListNode, k int) *ListNode {
	slow, fast := head, head
	for ; k > 0; k-- {
		fast = fast.Next
	}
	for fast != nil {
		slow, fast = slow.Next, fast.Next
	}
	return slow
}

总结

相比数组,由于链表不存在下标,寻址通常会使用指针,且通常我们不希望增加额外的空间复杂度。因此,使用快慢指针在链表相关算法题中就比较常见了。

相对其他的数据结构,链表笔者认为是相当具有实用性的(很多源码实现基于链表),而且面试链表题,一定程度上可以看出面试者的基本功,尤其是指针的使用及操作。

链表的边界判断、空指针引用等也是需要注意的!

继续刷链表题鸭~ 就决定是你了=》下一篇 19.删除链表的倒数第 N 个结点

更多基础链表题:「数据结构&算法」必知必会系列:7. 常见数据结构——链表(下)