持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
题目
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
解题思路
已知给到k值,此值是链表尾部向前数的值来求得对应节点。单向链表只能正向遍历查询,无法直接从链表尾部查询到某个节点。
遍历解法
链表结构特殊性无法只知道链表总长度,因此先遍历链表获取链表长度。
- 知道链表长度后,已知k值是反向的,其次知道了链表总长度。
- 从而通过k值和链表总长度得到正向遍历时的下标位置。
- while(count - k)再次遍历链表所求获取节点。
public ListNode getKthFromEnd(ListNode head, int k) {
// 1.巧解 反向思考 -
// 先知道链表长度
// 根据下标正向遍历知道
ListNode first = head;
int count = 1;
while(first.next != null){
first = first.next;
count ++;
}
while((count - k) >0){
head = head.next;
count--;
}
return head;
}
双指针解法
双指针和遍历解法有点相像,但双指针不需要遍历整个链表获取长度。
- 首先move指针先移动k-1次。
- 然后再同时移动move指针和left指针,直到move移动到链表结束为止。
- 返回slow当前节点就是k值倒数链表所指的节点了。
第二次循环移动和遍历解法是一样,slow正向移动(count - k)到达指定节点。
思考一下:move先移动就是为了减去k-1个节点数,再移动时就是去移动剩下正向移动所指想节点的位置了。
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode move = head;
ListNode slow = head;
while(k > 1){
move = move.next;
k --;
}
while(move.next != null){
move = move.next;
slow = slow.next;
}
return slow;
}
参考
- 来源:力扣(LeetCode)