假設鏈表有n個節點,那麼倒數第k個節點,就是從頭結點開始數到n-k+1個節點;所以自然就會兩種思路:
1、如果可以遍歷鏈表兩次的話,第一次計數得到鏈表節點個數,第二次直接循環找到第n-k+1個節點返回就是。
2、如果鏈表只允許遍歷一次的話,就必須使用兩個指針(or引用):第一個指針從頭開始走k-1步,第二個指針從頭開始走,第一個到鏈表尾部,第二個指針的所指的就是倒數第k個節點
注意程序的(Robust)魯棒性(這裏魯棒性是指:程序檢查輸入是否合乎規範,對於不合理的輸入進行合理的處理)
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
//方法一
import java.util.*;
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(k<=0||head==null) return null;
Stack<ListNode> stack = new Stack<ListNode>();// 建立棧結構
while(head!=null){//入棧操作
stack.push(head);
head = head.next;
}
if(k>stack.size()) return null;
ListNode count = head;
for(int i=1;i<=k;i++){//出棧操作
count = stack.pop();
}
return count;
}
}
//方法二:
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head ==null||k<=0) return null;
ListNode h1 = head;
ListNode h2 = head;
for(int i=1;i<k;i++){//i應該指向第k個時,因爲最後一次i 也+1了,但是不滿足條件跳出循環了,第一次循環結束,h1指向了第二個,第k-1此循環結束,h1指向第k個
if (h1==null)return null;
h1 = h1.next;
}
//由於循環條件判斷的是h1,不是h1.next,循環到第k-1次結束時,h1指向第k個(如果第k個節點不存在的話只能循環到第k-2次,指向第k-1個節點)所以最後h1指向第k個節點是否存在需要如下驗證
if(h1==null)return null;//最後一次不滿足條件跳出循環了,所以需要驗證h1循環的最後一次是否爲空;
while(h1.next!=null){//h1到最後一個節點,h2就是倒數第k個節點
h1 = h1.next;
h2 = h2.next;
}
return h2;
}
}
//方法三(跟上面的方法二幾乎完全一樣,除了循環條件之外)
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k<=0)return null;
ListNode p = head,q = head;
for(int i=1;i<k;i++){
if(p.next!=null) p = p.next;//如果p節點後面還有節點,p指向後續節點
else return null; //否則的話,說明節點數少於k個,返回空
}
if(p.next==null)return q;//如果此時k恰好是最後一個節點返回頭結點
while(p.next!=null){//如果k不是最後一個節點,循環,判斷p是否有後續節點
p = p.next;
q = q.next;
}
return q;
}
}