鍊錶 劍指offer

2021-08-20 05:22:36 字數 3715 閱讀 7227

從尾到頭列印鍊錶

思路:先把鍊錶翻轉,然後將翻轉後的鍊錶列印出來

這種方法:因為多分配鍊錶節點指標,故可能會對記憶體的消耗要大一點

時間複雜度為o(n)

vector

printlistfromtailtohead(listnode *head)

head=p2;//鍊錶翻轉後,頭結點為p2

while(head!=null)

return a;

}

遞迴方法:占用記憶體要少

vector

dev;

vector

printlistfromtailtohead(listnode *head)

return dev;

}

鍊錶中倒數第k個結點

思路:先統計鍊錶中一共有的節點數:n

倒數第k個節點,則為正數第n-k+1個節點

正序找到這個節點

時間複雜度為o(n)

listnode *(listnode *phead,int k)

//以上統計所得為鍊錶的節點個數

count=count-k;//用來正序訪問用

phead=temp;//讓phead還是指向鍊錶的首位址

if(count>=0)

else

return null;

}

合併兩個排序的鍊錶

時間複雜度為o(n)

listnode* merge(listnode* phead1, listnode* phead2)

else

//把p2的當前節點插入新建鍊錶

}if(p1==

null)

cur->next=p2;

if(p2==

null)

cur->next=p1;

return p3->next;

}

刪除鍊錶中重複的節點

時間複雜度為 o(n)

listnode * deleteduplication(listnode *phead)

//若存在多個連續相同的值,則上述while迴圈結束後,pnext為最後乙個重複值的節點。

pdel=pnext;

p=pnext->next;//下乙個要比較的節點為當前重複值得最後乙個的下乙個

delete pdel;

}else

//當前節點不是重複值,則把這個節點鏈結在新建鍊錶中

temp->next=

null;//最後乙個節點為空

return pnew->next;

}

5.二叉搜尋樹與雙向鍊錶

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成乙個排序的雙向鍊錶。要求不能建立任何新的結點,只能調整樹中結點指標的指向。

treenode *(treenode *root)

return cur;

}void convertnode(treenode *root,treenode *

&last_node)//注意此處形參為引用型別

6.鍊錶中環的入口結點

時間複雜度o(n)

listnode *entrynodeofloop(listnode *root)

return p1;}}

return

null;

}

如果要計算環中的長度:可以採用上述快慢指標相遇後,在繼續走,然後記錄從這次相遇到下一次相遇慢指標走過的步數,即為環中節點個數。

7.兩個鍊錶的第乙個公共結點

思路:找兩個鍊錶的公共節點,最暴力的解決辦法為:遍歷第乙個鍊錶的每個節點,然後在第二個節點中尋找是否存在與其相同的節點,如果存在,則返回第乙個存在相同的節點。這種方法如果鍊錶長度分別為m,n則時間複雜度為o(mn) 第二種方法是考慮從兩個鍊錶的尾部向前遍歷,最後乙個相同的節點為鍊錶的公共節點,因為單鏈表只存在乙個next指標,不能倒敘遍歷,這裡需要借助兩個棧。把兩個鍊錶元素分表放入兩個棧中,依次取棧頂元素。第乙個最後乙個相同的為第乙個公共節點。這種方法的時間複雜度為o(m+n)但是這種方法需要額外開闢棧空間,所以空間複雜度為:o(m+n)

第三種解決辦法:兩個鍊錶長度可能不同,我們先求出每個鍊錶的長度,然後求出兩個鍊錶長度差diff。讓長度大的鍊錶,先往前移動diff個節點,然後兩個鍊錶再一起移動。當兩個鍊錶移動到的節點相同時為第乙個公共節點。這種方法的時間複雜度為o(m+n)但是不需要開闢額外空間,空間複雜度節省。

int lengthoflist(listnode *phead)

return sum;

}listnode *firstcommonnode(listnode *phead1,listnode *phead2)

else

while(p1&&p2)

return null;

}

8.複雜鍊錶的複製

題目描述:

輸入乙個複雜鍊錶(每個節點中有節點值,以及兩個指標,乙個指向下乙個節點,另乙個特殊指標指向任意乙個節點),返回結果為複製後複雜鍊錶的head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空)

思路:(1)先複製每乙個鍊錶節點圖1中所有節點,並且每複製乙個節點把其插入到原先節點的後邊如圖2 ;

(2)複製完所有節點後,則原先節點與新複製的節點構成乙個新鍊錶,但是每隔乙個都是新複製的鍊錶節點。根據這一規律,則原先乙個節點的random指標指向的節點,在新複製的節點中對應的應是原來指向的下乙個節點:new->random=old->random->next如圖3;

(3)當完成上述兩部分之後,則新結點的隨機指標已經指向正確,但是next指標指向錯誤,此時第乙個節點的複製節點的指標指向第二個節點,其實應該指向第二個節點的複製節點。所以需要調整一下,圖4 圖5

圖1

圖2

圖3

圖4

圖5

**如下:

randomlistnode* clone(randomlistnode* phead)

//把新複製節點的random指標正確指向

p=phead;

while(p)

//當random指標分配好之後,進行新複製節點next指標的調整

p=phead;//p指向新舊節點組成的鍊錶的首節點,也是原先鍊錶的第//乙個節點

head=p->next;//新複製鍊錶的首節點為組合鍊錶的第二個節點

while(p->next)//此處p知識新建鍊錶中正在經歷的節點,p要把所有的//節點經歷一次

return head;

}

劍指offer 鍊錶

單向鍊錶的結構定義 typedef int datatype struct listnode 問題1 往鍊錶的末尾新增乙個結點 給定頭結點,往末尾插入乙個結點 void insertnode listnode head,datatype key listnode p head while p nex...

劍指offer 鍊錶

鍊錶 鍊錶是一種動態資料結構 struct listnode 往鍊錶的末尾新增乙個節點的c 程式如下 void addtotail listnode phead,int value 注意第乙個引數phead是乙個指向指標的指標。當我們往乙個空鍊錶插入乙個結點時,else pnode m pnext ...

劍指offer 鍊錶

在乙個排序的鍊錶中,存在重複的結點,請刪除該鍊錶中重複的結點,重複的結點不保留,返回煉表頭指標。思路1 遞迴版 class solution 找到當前節點與下乙個節點不重複的點,從不重複的點開始遞迴 return deleteduplication phead next else 思路2 非遞迴版 ...