目录
题目地址:
今天刷链表中倒数第k个节点,大家有兴趣可以点上看看题目要求,试着做一下。
剑指offer原题:
输入一个链表,输出该链表中倒数第k个节点。
为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
我们直接看题解吧:
解题方法:
方法1、顺序查找(需两次遍历,先求出链表长度)
方法2、双指针(只需一次遍历,不需要求出链表长度)
两个方法的时间复杂度与时间复杂度均为(n),(1)
难度分析:
属于基础性题目,链表基础,以及双指针使用。
审题目+事例+提示:
注意,单链表的长度不包括头结点,头节点看作位序0,头结点指向的下一个节点为位序1。
解题思路(双指针(快慢指针)):
创建两个指针,for,lat,它们均指向头结点
for指针先走cnt步,此时,两个节点相差cnt个节点
for,lat指针同步往后移动,最后直至for==null
for 指针指向cnt+1(实际为null),lat此时与for相差cnt
说白了,就是不需要知道链表长度,指针1先走k步,然后指针2和指针1(相差k)同时前进,当指针1指向链表最后一个元素的下一位(即null)时,指针2即为所求。
代码实现:
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode former = head, latter = head; //创建双指针,初始化指向头结点
for(int i = 0; i < cnt; i++) { //for先走cnt步
if(former == null) return null; //防止cnt大于链表长度,直接返回null
//(因为此时没求解的意义了)
former = former.next;
}
while(former != null) { //同时往后移动,直至for指针指向尾节点的下一位即null
former = former.next;
latter = latter.next;
}
return latter;
}
}
代码优化:
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode slow=head,fast=head;
int t = 0; //加个变量t判断,代替第一个for循环
while(fast!=null){
if(t>=k) slow=slow.next;
fast = fast.next;
t++;
}
return slow;
}
}
代码实现(方法1):
class Solution {
public ListNode trainningPlan(ListNode head, int cnt) {
int n = 0;
ListNode node = null;
for (node = head; node != null; node = node.next) {
n++;
}
for (node = head; n > cnt; n--) {
node = node.next;
}
return node;
}
}