從尾到頭打印鏈表 之 “C++代碼+思路解析 ”
希望我的文字始終給您帶來畫面感。
其實做算法題的過程也是在考驗我們的大腦日常解決問題的能力,懂不懂得將生活中碰到的難題拆分,一一解決。
今日感悟:
做算法題不要過分依賴於自己舊的的知識庫,獨立的把它看做一道新鮮的算法題。千萬不要一碰到陌生的知識點就丟失信心。做新的算法題一定會涉及到不熟悉的數據結構知識和語法問題,把它當做工具先使用,有時間的話再去了解它是什麼,不要在認識它的本質上浪費一分一秒的時間。
題目開始咯!
題目描述:輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。
//這裏敲黑板,千萬注意:我們做算法題 ,最基本的也是最關鍵的題目一定要 理解準確。這道題涉及到允不允許原地修改鏈表,所以分爲以下兩種情況。
第一種情況:不允許原地修改鏈表,如果不允許原地修改鏈表,
那麼可以利用棧後進先出的特點,遍歷鏈表,逐個將鏈表元素放入棧中,
然後依次彈出棧頂元素並打印。
代碼實現部分:
//5月8日
struct ListNode {
int val;
struct ListNode* next;
ListNode(int x) :
val(x), next(NULL) {
}//這裏不懂爲什麼這麼寫,沒關係
};
class Solution {
public:
vector<int> printListFromTailToHead( ListNode* head ){
vector<int> res;
if ( !head )
return res;
//我寫代碼定義一般先不寫,後面需要用到就把它加上。
stack<int> sta;
ListNode* p = head;//指針就記着在內存裏面給這個變量p分配一塊地址,跟變量一樣使用。
while ( p )
{
sta.push( p->val );//循環裏面最關鍵的是push這個動作
p = p->next;
}
while ( !sta.empty() )
{
int a = sta.top();
sta.pop();
res.push_back(a);
}
return res;
}
};
思路解析部分:
我不知道大家的寫算法思路是思維習慣和先後順序是怎樣的,我會習慣將代碼拆分成小的代碼塊進行 ,再進行邏輯組合安裝。當然這裏無法評判哪種一定是正確的,這裏我想分享一下:我個人認爲最快的寫代碼順序。
第一步:我會先搞清楚題目 ,需要我給它一個什麼,定下來整體的框架。
比如這道題它要我給它返回一個 數組。一個裝着鏈表中倒序值的數組。那麼 返回值類型 和 返回語句
心裏就有個概念了。還要搞清楚我們這道題需要的數組選擇用靜態的還是動態,動態就用vector。
那第一步函數整體的框架就出來咯!
vector< int > printListFromTailToHead(..........){
vector< int > res;
................................
return res;
}
第二步:我會把參數定下來,進到函數體首先就檢查參數合不合法。
加入 if 語句檢驗參數 鏈表指針 head 是否爲空。
vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
//加入這塊代碼檢驗參數。
if( !head )
{
return res;
}
................................
return res;
}
第三步:給框架裏面填上語句塊。發揮( if,while,for…)語句的作用,語句其實就是思考邏輯的實現。
這道題的邏輯就是把鏈表的數值一個一個倒進棧裏,再從棧一個一個倒入新的容器裏,拿到這個容器就OK了。
1 填入 這塊代碼,使用while 語句,把鏈表裏的值一個一個推到棧裏。
vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
if( !head )
{
return res;
}
//加入這塊代碼向棧裏推數值
...............................//這裏要加定義
while ( p )
{
sta.push( p->val );//循環裏面最關鍵的是push這個動作
p = p->next;
}
................................
return res;
}
2 再填入一塊代碼,繼續使用while語句,把棧裏的值一個一個彈出來,再一個一個推到容器裏面。
vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
if( !head )
{
return res;
}
//加入這塊代碼向棧裏推數值
...............................//這裏要加定義
while ( p )
{
sta.push( p->val );//循環裏面最關鍵的是push這個動作
p = p->next;
}
//加入這塊代碼,把棧裏的值一個一個彈出來,再一個一個推到容器裏面。
while ( !sta.empty() )
{
int a = sta.top();
sta.pop();
res.push_back(a);
}
return res;
}
第四步:摳細節,扣語句塊裏的細節,沒定義的變量要給定義。對象要使用什麼函數來實現,組裝起來。
1 給對象加上定義。
while ( p )
{
sta.push( p->val );//循環裏面最關鍵的是push這個動作
p = p->next;
}
while語句循環檢驗的這個指針p ,要在前面加上定義。
sta 是一個棧變量,它是一個數據的臨時存放容器,繼續補上定義。
ListNode* p = head;
stack<int> sta;
這就知道了p指向的是傳進來的鏈表head的頭結點,sta是一個棧變量。
2 使用函數 top() ,pop(), push_back(),也就是組裝動作。
while ( !sta.empty() )
{
int a = sta.top();
sta.pop();
res.push_back(a);
}