「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例 1:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
利用数组存储节点
思路
返回第倒数第k个节点,我们知道,链表只能next访问下一位节点,并不能倒数访问上一个节点
所以我们只能遍历过每一个节点,并记录位置信息
方法很多,这里我们通过遍历链表,并且把链表的没一个节点都按顺序保存在数组stack中,这样我们就可以直接通过访问数组下标来直接获取对应的节点了stack[stack.length-k]
var getKthFromEnd = function(head, k) {
var stack = []
while(head){
stack.push(head)
head = head.next
}
return stack[stack.length-k]
};
双指针
思路
另外我们可以通过双指针的方式来获取,如何使用双指针呢?
其实双指针就是通过快慢指针之间的间距为k来标记长度为k的一段链表,
- 指定双指针的位置,slow从头开始,fast要提前走k步,这样他们之间相差k个节点
- 只要fast有值,则不断向后移动
- 当fast链表末尾null的时候,因为间距为k,slow正好是倒数第k个节点
此时直接返回k节点
var getKthFromEnd = function(head, k) {
if(!head) return head
var slow = fast = head
var n = 0
while(n<k){
fast = fast.next
n++
}
while(fast){
fast = fast.next
slow = slow.next
}
return slow
};
迭代
思路
迭代是通过遍历链表获取链表的长度n,那么倒数第k个元素就是,n-k
所以第二次遍历链表 到n-k的位置,就是倒是第k各节点了
var getKthFromEnd = function(head, k) {
if(!head) return head
var node = head
var n = 0
//第一次遍历获取链表程度n
while(node){
node = node.next
n++
}
var m = 0;
var res = head
//第二次遍历获取链表倒数第k个节点,正数第n-k+1
while(m<n-k){
res = res.next
m++
}
return res
};