下雨天冷,大家注意保暖
正题
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
这是一道相对简单的算法题,求倒数第K个节点的问题。首先想到的就是将每一次链表的遍历存储在一个数组里面,然后取得倒数第K个元素即可,所以有了方法一。这也是最容易想到,最简单的解题思路,也只需要遍历一次即可。优势是只需要遍历一次,缺点是需要开辟新的数组空间,对内存有一点消耗。
方法一:数组缓存法
代码:
var getKthFromEnd = function(head, k) {
let list = []
while(head) {
list.push(head)
head = head.next
}
return list[list.length-k]
};
方法二: 二次遍历法
既然方法一种提到了优势是只遍历一次,那么说明我们还可以遍历多次(实际上是2次即可)取得正确结果。其实也很好理解,第一次遍历记录下链表的长度,然后第二次遍历只遍历到 长度 - k 个节点即可。优缺点和方法一互补。
代码:
var getKthFromEnd = function(head, k) {
let index = 0
let p = head
while(p) {
index++
p = p.next
}
while(head) {
if (k === index--) {
return head
}
head = head.next
}
}
方法三: 双指针遍历法
双指针遍历法是二次遍历法的延伸,我们可以定义两个指针去遍历链表,区别在于他们的出发时机不同,P1指针优先出发,P2指针在P1指针出发K个节点之后开始出发,划重点:那么我们可以得知P1和P2之间相隔了K个节点,那么当P1指针遍历结束时,P2指针指向的就是倒数第K个节点了!
代码:
var getKthFromEnd = function(head, k) {
let fast = head
let slow = head
while(fast) {
if (k <=0) {
slow = slow.next
}
fast = fast.next
k--
}
return slow
}