鏈表
鏈表部分個人認爲是最煩的,大部分鏈表題考的都是coding技巧,不需要怎麼思考,但是沒有寫過幾次的話,鏈表的coding是各種陷阱。
先總結一下題型,鏈表的題目主要兩種:
1. 鏈表翻轉(包括全翻轉,部分翻轉,分段翻轉);
2. 鏈表刪除/增加(包括刪除某值,刪除倒數第K個,去重)。
具體說,全翻轉就是給你一個單向鏈表,你把它倒過來;部分翻轉就是,給一個單向鏈表,給一個a和b,讓你把第a到第b個節點翻轉;分段翻轉就是給一個單向鏈表,給一個k,讓你把每k個作爲一組,翻轉過來。(真是你妹啊。。。。)
鏈表的刪除就是,一個是刪除某個值,一個是刪除倒數第k個值(這個可以遍歷兩次,或者一次遍歷同時保留k個指針,或者遞歸,在回溯時刪除),一個是給一個鏈表,讓你把出現超過一次的元素全部刪除或者只留一個(這個又有有序鏈表和無序鏈表之分)。(真是你妹啊。。。。)
其實對於翻轉,也可以直接使用刪除,插入的方法。每次把下一個節點插入到頭,就可以實現鏈表的翻轉,所以,鏈表的插入刪除是最重要的。要刪除一個node節點,再把node放到head後面,核心代碼就這三句,但是經常用到:
pre->next = node->next;//刪除
node->next = head->next;//head->next接到node後面
head->next = node;//node接到head後面
先斷開,再接node->next再head->next。其他要注意的是head是不是爲NULL(用dummy head 可以解決)、如果只是刪除記得斷開後delete、記得更新你的迭代節點(就是例子中的node)。
主要的技巧就是要用dummy head,就是在鏈表頭加一個節點指向head,這樣可以避免判斷頭指針,統一處理所有情況,最後返回dummy->next;另外有一個跟dummy head等價的方法是用指針的指針**p去處理,也能達到dummy head的效果,比dummy好的地方是,不用delete dummy head,另外如果一個節點比較大的話,用**p也比較省空間,但是邏輯上比dummy要繞一點,可以參考這個文章:http://coolshell.cn/articles/8990.html
一般來說用dummy head就好,大概意思如下:
ListNode* ProcessList(ListNode* head){
ListNode* dummy = new ListNode();
dummy->next = head;
//process the list
head = dummy->next;
delete dummy;
return head; //再提醒一次,請記得delete
}
鏈表的東西不多說,主要就是記住刪除插入時操作順序(上面的那三行代碼),記住delete自己new出來的node。
leetcode上關於鏈表的題目,還算蠻多的(代碼放到另一篇blog裏面);
Remove Duplicates from Sorted List
Remove Duplicates from Sorted List II
Remove Nth Node From End of List