面试题22. 链表中倒数第k个节点
1:题目描述
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2:题目分析
思路1:常规思路
- 首先遍历链表长度为n。
- 再从头遍历链表n-k步,找到倒数第k个节点即可!
思路2:由于第一种方法,要通过两次遍历链表,浪费一定时间,所以我们可以通过双指针的方式来遍历链表一次即能定位到倒数第k个节点。
- 定义former和latter指针初始化为head位置。
- 先将former移动k步。latter保持不变。
- 然后再将former和latter指针一起向后移动,直到former到达尾部后的null,这是latter即为倒数第k位链表
- return latter
思路3:如何才能避免多次遍历?我们可以时钟保存当前node前的k-1个node,当指针到达尾部的时,则直接再保存的数组里的节点,直接输出即可,用空间换速度。
3:代码示例
思路2:
public ListNode getKthFromEndDoublePointer(ListNode head, int k) { //定义前后双指针 ListNode former = head; ListNode latter = head; //former指针先移动k步 for(int i=0;i<k;i++){ former = former.next; } //双指针同时移动,指代former值为null while(true){ if(former == null){ break; } former = former.next; latter = latter.next; } return latter; }
思路3:
public ListNode getKthFromEnd(ListNode head, int k) { //创建缓存数组 ListNode[] arrayNode = new ListNode[k]; int i = 0; ListNode curNode = head; while(true){ if(curNode == null){ break; } //按照当前位置,存入对应数组中 arrayNode[i%k] = curNode; curNode = curNode.next; i++; } //找到目标节点 ListNode result = arrayNode[(i-k)%k]; return result; }