题目:输入一个链表,输出该链表中倒数第k个节点
示例:一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
1、先明白一点:每个节点都会next指向下一个节点
- 头部节点为1,但是它
next指向了2,2又指向了3 . . . . ,所以头部节点的形式为:[1,2,3,4,5] - 第二个节点自然为:
[2,3,4,5] - 所以倒数第K个节点就是:
[4,5]
2、力扣上我们只需要写函数接口就可以,链表指针等都是封装好了
这道题有三种做法:
做法一:利用数组
- 将链表的每个节点包括其链接的节点存储到数组中
- 再利用数组索引取出来
/**
* 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 h = head
let arr = []
while(h) {
// 每次都将节点存储到数组的头部
arr.unshift(h)
h = h.next
}
return arr[k-1]
};
做法二:利用单指针
- 定义一个指针,统计链表的长度
n - 然后再返回链表的第
n-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 h = head
let n = 0
while (h) {
h = h.next
n++
}
// 此时指针指向最后一个节点的下一个节点 null,所以需要手动将指针指向头节点
let h = head
while (n - k > 0) {
h = h.next
n--
}
return h
};
效率一般般哈
3、快慢双指针
-
定义一个慢指针 和 一个快指针,都指向头部节点
-
让快指针先走
k步,然后慢指针再跟着快指针一起移动 -
当快指针走到
null时,慢指针就到了链表的 倒数第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 fast = head;
let slow = head;
// 快指针先走k步
while (k > 0) {
fast = fast.next;
k--
}
// 快慢指针一起走,直到快指针到了null
while (fast) {
fast = fast.next;
slow = slow.next
}
// 返回倒数第k个节点
return slow
};