題目:定義一個函數,輸入一個鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的頭結點。面試
解決與鏈表相關的問題老是有大量的指針操做,而指針操做的代碼老是容 易出錯的。不少的面試官喜歡出鏈表相關的問題,就是想經過指針操做來考察應聘者的編碼功底。爲了不出錯,咱們最好先進行全面的分析。在實際軟件開發週期 中,設計的時間一般不會比編碼的時間短。在面試的時候咱們不要急於動手寫代碼,而是一開始仔細分析和涉及,這將會給面試官留下好的印象。與其給出一段漏洞 百出的代碼,倒不如仔細分析再寫出魯棒性好的代碼。函數
爲了正確的反轉一個鏈表,須要調整鏈表中指針的方向。爲了將調整指針 這個複雜的過程分析清楚,咱們能夠藉助圖形來直觀的分析。在圖中所示的鏈表中,h,i,j是3個相鄰的結點。假設通過若干的操做,咱們已經把結點h以前的 指針調整完畢,這些結點的m_pNext都指向前面的一個結點。接下來咱們把i的m_pNext指向h,此時的鏈表結構如圖b所示。編碼
不難注意到,因爲結點i的m_pNext指向了它的前一個結點,致使咱們沒法在鏈表中遍歷到結點j。爲了不鏈表在結點i處斷開,咱們須要在調整結點i的m_pNext以前,把結點j保存下來。spa
也就是說咱們在調整結點i的m_pNext指針時,除了須要知道結點 i自己以外,還須要i的前一個結點h,由於咱們須要把結點i的m_pNext指向結點h,同時,咱們還實現須要保存i個結點j,以防止鏈表斷開。所以相應 地咱們須要三個指針,分別指向當前遍歷到的結點,它的前一個結點和後一個結點。設計
最後咱們試着找到反轉鏈表的頭結點。不難分析出反轉後的鏈表的頭結點是原始鏈表的尾節點。什麼結點是尾節點,天然是m_pNext爲 Null 的結點。指針
分析寫出下面的代碼:遞歸
package cglib;
class ListNode
{
int data;
ListNode nextNode;
}開發
public class DeleteNode {
public static void main(String[] args) {
ListNode head=new ListNode();
ListNode second=new ListNode();
ListNode third=new ListNode();
ListNode forth=new ListNode();
head.nextNode=second;
second.nextNode=third;
third.nextNode=forth;
head.data=1;
second.data=2;
third.data=3;
forth.data=4;
DeleteNode test=new DeleteNode();
ListNode resultListNode=test.reverseList(head);
System.out.println(resultListNode.data);
}
public ListNode reverseList(ListNode head){
if(head == null)
return null;
ListNode preListNode = null;
ListNode nowListNode = head;
while(nowListNode != null){ //1->2->3->4
ListNode nextListNode = nowListNode.nextNode; //保存下一個結點2
nowListNode.nextNode = preListNode; //當前結點指向前一個結點null<-1
preListNode = nowListNode; //前任結點 等於現任節點 null<-1<-2
nowListNode = nextListNode; //現任節點等於下一結點 null<-1<-2,而後從2開始循環,直至preListNode=4,nowListNode=null
}
return preListNode;
}
}class
輸出 4test
拓展: 遞歸實現一樣的反轉鏈表的功能。
public ListNode reverseList(ListNode head){ if(head==null || head.nextNode==null) return head; else { //1->2->3->4 ListNode nextNode = head.nextNode; //2 head.nextNode = null; //null<-1 ListNode reverseRest = reverseList(nextNode); //從2開始遞歸 nextNode.nextNode = head; //3<-4 return reverseRest; } }