题目描述
输入一个链表,输出该链表中倒数第k个结点。
思路一
简单方法,找倒数第k个转换成正数第i-k个 i为链表长度
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head ==null || k<=0)
{
return null;
}
int i = 1;
ListNode temp = head;
while(temp.next!=null){
i++;
temp = temp.next;
}
if (i < k) return null;
//输出第i-k+1的值
temp = head;
for(int j = 0;j<i-k;j++){
temp =temp.next;
}
return temp;
}
}
时间复杂度:O(2*n),n为链表的总长度,如果k总是在倒数第一个节点,那么此方法需要遍历链表2次
空间复杂度:O(1)
思路二
严格的O(n)解法,快慢指针
我们从图中可以看出,倒数第k个节点与最后的空节点之间有2个指针,此时的2正好就是k,于是我们可以想到可以通过平移来到达最后的状态。
如图:
如果懂了上面的过程,接下来再说说具体编程要怎么写?
使用如图的快慢指针,首先让快指针先行k步,然后让快慢指针每次同行一步,直到快指针指向空节点,慢指针就是倒数第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) {
if(head ==null || k<=0)
{
return null;
}
ListNode fast = head;
ListNode slow =head;
for(int i = 1; i <k;i++){
if(fast.next!=null){
fast = fast.next;
}else{
return null;
}
}
while(fast.next!=null){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
时间复杂度:O(n),不管如何,都只遍历一次单链表
空间复杂度:O(1)