题目
输入一个链表,输出该链表中倒数第k个结点。
牛客网给定以下链表类。
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
分析
思路1:
暴力法:先从头到尾遍历链表,使用临时变量自增得到链表的长度len。然后题目要得到倒数第k个结点,从正数也就是第len-k+1个结点,输出即可。
代码:
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
ListNode tmp = head; //此处需创建一个临时结点作为第一次遍历需要的结点。
int len = 0; //链表长度
while(tmp != null){ //遍历链表,计算链表长度
len++;
tmp = tmp.next;
}
if(k<1||k>len||head==null) return null; //注意边界问题
for(int i=0;i<=len-k-1;i++) {
head = head.next;
}
return head;
}
}
思路2:
采用双指针的形式。即初始化指针tmp1和tmp2都指向头结点。第一个指针tmp1从头到尾遍历链表,直到遍历到i=k+1即tmp1指向第k+2个结点时,则tmp2也从头结点开始遍历到下一个结点即第二个结点,依次类推。如此,tmp1始终比tmp2多k个结点,则当tmp1结束遍历时,tmp2就遍历到了倒数第k个结点。
注意:此处要注意3个边界条件:
1)输入的链表为空;
2)输入的k<1;
3)输入的k>链表长度;
当满足这三个条件时,应返回空结点。
代码:
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
ListNode tmp = head; //作为临时结点用于得出链表长度
ListNode tmp1 = head;//第一个遍历整个链表的临时结点
ListNode tmp2 = head;//比tmp1永远少k的用于返回的结点
int len = 0;
while(tmp != null){ //得出链表长度
tmp = tmp.next;
len++;
}
if(head==null||k<1||k>len) return null; //判断边界条件
for(int i=1;tmp1 != null;i++){
tmp1 = tmp1.next;
if(i>=k+1){//如果tmp1遍历到了第k+2个结点,注意上面是i=k+1时,tmp1.next为其下一个结点,所以是遍历到了第k+2个结点。
tmp2 = tmp2.next;
}
}
return tmp2;
}
}