《劍指offer》之鏈表中倒數第k個結點
題目:輸入一個鏈表,輸出該鏈表中倒數第k個結點。
分析:倒數第k個節點,也就是正數的第n-k+1個節點(鏈長爲n),例如:在n=6的鏈表中,倒數第2個節點就是正數第5個節點(6-2=1)。
解決方案:
-
直接遍歷法:先遍歷一遍鏈表獲得鏈表長n,然後再從頭開始遍歷第n-k+1個節點。
代碼:
public ListNode FindKthToTail(ListNode head,int k) { ListNode pre = head; ListNode last =head; int count = 0; if(head == null || k <= 0){ return null; } while(pre != null){ pre = pre.next; count++; } if(k>count){ return null; } for(int i =1;i<count-k+1;i++){ last = last.next; } return last; }
性能測試分析:
運行時間:26ms 佔用內存:9280k
-
類似於第一種方法的變形:使用兩個指針,指針A先進行遍歷,當遍歷到第k-1個數時,指針B開始從頭遍歷。當指針A到達鏈表尾的時候,指針B的位置就剛好爲倒數第k個數。
代碼:
public ListNode FindKthToTail(ListNode head,int k) { ListNode pre = head; ListNode last = head; if(head == null || k <= 0){ return null; } for(int i=1;i<k;i++){ if(pre.next!=null){ pre = pre.next; }else{ return null; } } while(pre.next != null){ pre = pre.next; last = last.next; } return last; }
性能測試分析:
運行時間:24ms 佔用內存:9552k
-
使用堆棧。對鏈表進行遍歷並存入堆棧中,然後再從堆棧中彈出k個元素(這種方法需要注意鏈表的長度是否會造成堆棧的溢出)
代碼:
public ListNode FindKthToTail(ListNode head,int k) { ListNode pre = head; ListNode last = null; int count = 0; Stack stack = new Stack(); if(head == null || k <= 0){ return null; } while(pre != null){ stack.push(pre); pre = pre.next; count++; } //判斷k是否超過鏈表長度 if(k>count){ return null; } for(int i =1;i<=k;i++){ last = (ListNode) stack.pop(); } return last; }
測試性能分析:
運行時間:25ms 佔用內存:9576k