目录
题目描述
输入一个链表,输出该链表中倒数第k个结点
题解
第一种
这题有很多的想法,我最初想到的是先获取链表的长度,然后根据前后的关系,从前往后遍历,遍历到指定点时,返回该结点。代码如下:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
int length = getLength(head);
ListNode l1 = head;
int count=0;
while(l1!=null){
if(count == length-k){ //到达指定节点
return l1;
}
count++;
l1 = l1.next;
}
return l1;
}//获取链表长度
public int getLength(ListNode head){
ListNode cur = new ListNode(0);
cur = head;
int count=0;
while(cur!=null){
count++;
cur = cur.next;
}
return count;
}
}
第二种
用栈来存储,然后反向弹出并计数,这时候要注意的是,栈中记录的是每个节点,即地址,这样返回的时候直接返回弹出的这个值。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack; //不要忘记头文件哦
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head == null || k<=0)
return null;
ListNode list = head;
//借助栈的结构,保存链表结点的地址
Stack<ListNode> stack = new Stack<ListNode>();
int count = 1;
//全部入栈
while(head!=null){
stack.push(head);
head = head.next;
}
//判断
while(!stack.isEmpty()){
if(count != k){
stack.pop();
count++;
}
else if(count == k)
return list = stack.pop();
}
//为空,说明越界了
return null;
}
}
加上栈的结构,其时间复杂度和空间复杂度都是会有所增加
第三种
看了解题的讨论,由衷感觉比较巧妙的解法,可以用两个指针来实现,意思是这样的:有两个指针slow,fast初始都指向头指针head 。 slow先不动,fast先跑k-1个结点,然后两个一起开始跑,当fast到最后一个结点的时候,slow指针所在的位置就是倒数第K个结点。而且这样的时间复杂度只有O(N),且额外空间复杂度为O(1),比前两种要好!!!
时间复杂度O(n),一次遍历即可
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
ListNode pre=null,p=null;
//两个指针都指向头结点
p=head;
pre=head;
//记录k值
int a=k;
//记录节点的个数
int count=0;
//p指针先跑,并且记录节点数,当p指针跑了k-1个节点后,pre指针开始跑,这时两者一起跑
//当p指针跑到最后时,pre所指指针就是倒数第k个节点
while(p!=null){
p=p.next;
count++;
if(k<1){
pre=pre.next;
}
k--;
}
//如果节点个数小于所求的倒数第k个节点,则返回空
if(count<a) return null;
return pre;
}
}