原題鏈結
題意很簡單。給定乙個單鏈表,反轉這個單鏈表,返回翻轉後的頭節點。
要將鍊錶翻轉,很容易想到借助棧的後進先出的性質來改變鍊錶的順序。
將鍊錶節點順序壓入棧中,鍊錶節點全部進棧以後,取棧頂元素作為新鍊錶的頭節點,然後將元素不斷出棧,每齣棧乙個元素就連線到新鍊錶的末尾。
時間複雜度:將鍊錶元素壓入棧中需要遍歷一次鍊錶,將棧中所有元素連線起來需要遍歷一遍棧,時間複雜度是o(n).
空間複雜度:需要額外開乙個棧存放所有元素,空間複雜度是o(n).
**如下:
class solution
stackst;
listnode* cur = head; //記錄當前節點
while(cur != null)
auto dummy = new listnode(-1); //用乙個附加頭節點的next指標指向翻轉後的鍊錶的頭節點,這樣返回值就可以是dummy -> next
if(!st.empty())
while(!st.empty())
cur -> next = null; //鍊錶尾節點的next指標指向空
return dummy -> next;}};
翻轉操作就是將鍊錶中所有節點的next指標指向他們原來的前驅節點。
由於鍊錶是單鏈表,只有next
指標沒有pre
指標指向前驅節點,因此我們需要額外用乙個變數pre
記錄每個節點的前驅節點,並且將當前節點cur
的next
指標指向pre
,由於改變了cur
的next
指標的值,但是在改變next
的值之前我們還是需要記錄cur
的下乙個節點(為了進行遍歷/迭代),
所以還需要額外用乙個變數next
來記錄節點(按原來順序的)下乙個節點。
時間複雜度:只遍歷一次鍊錶,時間複雜度是o(n)
.
空間複雜度:額外開了三個變數pre
,cur
,next
,空間複雜度是o(1)
.
**如下:
class solution
return pre; //跳出上面的while迴圈時,cur為空,pre指向原鍊錶的最後乙個節點,也就是翻轉後的鍊錶的頭節點}};
reverselist
函式的功能是給定乙個鍊錶的頭節點,返回新鍊錶的頭節點(也就是原鍊錶的尾節點),
head
最開始為頭節點(只有乙個節點,我們可以認為已經翻轉好了,只不過還沒修改next指標為空),
我們可以遞迴處理head -> next
,head -> next
是當前遍歷到的鍊錶長度的尾節點(也就是加入了乙個新的需要翻轉的節點),
也就是新鍊錶的頭節點newhead
, 這時需要先記錄newhead
的next
指標指向head(翻轉):head -> next -> next = head;
然後head
的next
指標要指向空(原來指向後繼結點)。
時間複雜度:鍊錶中每個節點遍歷一次,時間複雜度是o(n)
.
空間複雜度:總共遞迴n
層,總共需要o(n)的空間,系統棧的空間複雜度是o(n)
.
**如下:
class solution
listnode* newhead = reverselist(head -> next); //遞迴
head -> next -> next = head;
head -> next = null;
return newhead;}};
另一道鍊錶題目
有乙個鍊錶,它有next以及child屬性,每乙個child或者next指向的node也有相同的屬性,現在問如何遍歷所有的node。演算法有幾種option,第一種是用額外儲存空間,另一種是no extra memory。昨天和同事討論了一下,發現這道題目其實可以用遞迴來做,非常容易,幾句話就寫好了...
一道this的題目
請問下面 中的this值指向的是全域性物件還是物件o?function f return c var o new f console.log o.constructor.name object這裡的this指向全域性物件,因為 c call without new。這裡用正常的方式呼叫的函式 c 所...
一道題目 intel
從序列中找四個四字子串形成十進位制數使之乘積最大 就是求四個最大的?我目前只想到如下辦法。這個題並不是關於複雜的演算法,其本意是要利用並行處理,但目前尚未考慮到 除了其中比較求最小值部分有希望用simd include int g teststring int main void int picke...