從尾到頭打印鏈表 之 “C++代碼+思路解析 ”(允許原地修改鏈表)
上一篇 從尾到頭打印鏈表 (第一種情況 不允許原地打印鏈表)
希望我的文字始終給您帶來畫面感。
其實做算法題的過程也是在考驗我們的大腦日常解決問題的能力,懂不懂得將生活中碰到的難題拆分,一一解決。
今日感悟:
//不要去刻意記憶代碼句,先用起來,積累框架,慢慢拿出來用。
//不是所有的框架都是一樣的,也要學會適應不同的變化。
題目開始咯!
題目描述:輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。
//這裏敲黑板,千萬注意:我們做算法題 ,最基本的也是最關鍵的題目一定要 理解準確。這道題涉及到允不允許原地修改鏈表,所以分爲以下兩種情況。這裏是第二種情況。
第二種情況:允許原地修改鏈表,那麼只需要用三個指針來解決。
代碼實現部分:
//5月9日
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* next = nullptr;
while(cur)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
思路解析部分:
我不知道大家的寫算法思路是思維習慣和先後順序是怎樣的,我會習慣將代碼拆分成小的代碼塊進行 ,再進行邏輯組合安裝。當然這裏無法評判哪種一定是正確的,這裏我想分享一下:我個人認爲最快的寫代碼順序。
第一步:我會先搞清楚題目 ,需要我給它一個什麼,定下來整體的框架。
這道題的第二種情況是允許原地修改鏈表,那麼只需要返回傳進來的鏈表就OK了,只不過這個鏈表被操作了一番。
那第一步函數整體的框架就出來咯!
class Solution {
public:
ListNode* reverseList( ) {
.............................................
return 頭指針;//鏈表被原地操作,此時的頭指針已經不是head了
}
};
這裏的第二步:我會把參數定下來,進到函數體首先就檢查參數合不合法。
加入 if 語句檢驗參數 鏈表指針 head 是否爲空。
class Solution {
public:
ListNode* reverseList( ListNode* head) {
if( !head )
{
return head;
}
.............................................
return 頭指針;
}
};
第三步:給框架裏面填上語句塊。發揮( if,while,for…)語句的作用,語句其實就是思考邏輯的實現。
原地反轉鏈表的邏輯就是把鏈表的數值比如-1-2-3-4-5-變成-5-4-3-2-1-。這裏設置三個指針 ,前後中分別用cur,pre和next來表示。
1 填入 這塊代碼,使用while 語句做不斷重複做兩件事。
第1件事:使得當前結點的後繼結點變成前驅結點,也就是2的後面不連3,要連1。用這句代碼來實現這件事:cur->next = pre;
第2件事:不斷推動三個指針向後走。用這三句代碼來實現。
1next = cur->next; …(第一件事)…2 pre = cur; 3 cur = next;
大家都看出來了這三句是有順序的。進入循環時一定要先把cur->next保存起來,使next先後移一步,不然下一步cur的後繼結點的改變會讓next指向亂掉。然後前指針和當前指針一起向後移動。
while ( cur )
{
next = cur->next;
cur->next = pre; //使當前結點的後繼結點變成前驅結點。
pre = cur;
cur = next;
}
第四步:摳細節,這裏給加上定義,附上初值。
1 給變量加上定義+賦值。
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* next = nullptr;
此題總結:
這道題目最大的難點就在於拆分語句的四句代碼 ,怎樣安排三指針的移動順序,還有就是進入循環體就一定要先把當前結點的後繼結點保存起來。