鍊錶是面試裡面經常涉及到的考點,因為鍊錶的結構相比於hashmap、hashtable、concurrenthashmap或者圖等資料結構簡單許多,對於後者更多面試的側重點在於其底層實現。比如hashmap中entry等操作、如何擴容、容量的設定等。鍊錶的考察更側重於**的書寫和思路的形成。雖然說,鍊錶的結構簡單,但是涉及到指標的操作,容易引申出一些挑戰性的考題,其中也牽涉到諸多小的細節的考慮,更能看出**書寫的能力和功底。
題目:定義乙個函式,輸入乙個鍊錶的頭結點,反轉該鍊錶並輸出反轉後鍊錶的頭結點。
下面給出了鍊錶結點的定義:
struct listnode
};
分析:
鍊錶前後元素的關聯就是通過指標實現的,每個鍊錶都有乙個next指標指向下乙個結點,末尾的節點的next域則置null;
反轉鍊錶就是要求修改指標的指向。下面的圖就是反轉前和反轉後的效果。
反轉前:
反轉後:
下面來談談如何對鍊錶進行反轉。
假設我們現在正在對結點v進行反轉操作,即原來結點u的next域指向v(圖中已經調整完畢,現在指向前乙個結點),v的next域指向w。現在要做的是將v的next域指向u。從圖中我們可以看出,當把v的next指標指向u的同時,原先指向的w就已經無法被正常的訪問到了,為了避免「斷鏈」,我們必須在指標更改指向之前,儲存修改結點的下一結點。同時我們也必須儲存上乙個結點,因為next域即將修改指向該結點。因此定義三個指標,分別指向當前遍歷的結點,前乙個結點和後乙個結點。
演算法實現如下:
listnode* reverselist(listnode* phead)
phead->next=null;
return preversedhead;
}
當然,上面的原始碼中用到了四個指標,看完原始碼就會發現和上面分析的原理並沒有相悖。或者下面這樣也是可以的,兩者的思路一致,沒有差別。只不過下面的**必須注意一點,跳出while迴圈的時候,最後乙個結點的next域別忘記指向前乙個結點,否則就會導致「斷鏈」。
listnode* reverselist(listnode* phead)
root->next=pre;
return root;
}
擴充套件:雙向鍊錶逆序(感覺意義不大)
// 雙向鍊錶
public static class doublenode
} // 反轉雙向鍊錶
public static doublenode reverselist(doublenode head)
return pre;
}
鍊錶 反轉鍊錶
問題 兩兩交換鍊錶中的節點 問題 k 個一組翻轉鍊錶 問題鏈結 利用棧先進後出的特性,遍歷鍊錶,將每個結點加入棧中,最後進行出棧操作,先出棧的結點指向臨近的後出棧的結點。definition for singly linked list.struct listnode class solution ...
反轉鍊錶與分組反轉鍊錶
經典的反轉鍊錶,先上 public class listnode public class printlist system.out.println public class reverse public listnode reverse listnode root listnode pre nul...
鍊錶的反轉
鍊錶的反轉是乙個經常被問到的乙個面試題,也是乙個非常基礎的問題。比如乙個鍊錶是這樣的 1 2 3 4 5 通過反轉後成為5 4 3 2 1。最容易想到的方法遍歷一遍鍊錶,利用乙個輔助指標,儲存遍歷過程中當前指標指向的下乙個元素,然後將當前節點元素的指標反轉後,利用已經儲存的指標往後面繼續遍歷。源 如...