C語(yǔ)言復(fù)雜鏈表的復(fù)制實(shí)例詳解
一、題目描述
請(qǐng)實(shí)現(xiàn) copyRandomList 函數(shù),復(fù)制一個(gè)復(fù)雜鏈表。在復(fù)雜鏈表中,每個(gè)節(jié)點(diǎn)除了有一個(gè) next 指針指向下一個(gè)節(jié)點(diǎn),還有一個(gè) random 指針指向鏈表中的任意節(jié)點(diǎn)或者 null。
示例1:

輸入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
輸出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例2:

輸入:head = [[1,1],[2,1]]
輸出:[[1,1],[2,1]]
示例3:

輸入:head = [[3,null],[3,0],[3,null]]
輸出:[[3,null],[3,0],[3,null]]
示例4:
輸入:head = []
輸出:[]解釋:給定的鏈表為空(空指針),因此返回 null。
提示:
-10000 <= Node.val <= 10000
Node.random 為空(null)或指向鏈表中的節(jié)點(diǎn)。
節(jié)點(diǎn)數(shù)目不超過(guò) 1000 。
二、思路分析
注:思路分析中的一些內(nèi)容和圖片參考自力扣各位前輩的題解,感謝他們的無(wú)私奉獻(xiàn)
分析
復(fù)制普通鏈表:給定鏈表的頭結(jié)點(diǎn)head,復(fù)制普通鏈表很簡(jiǎn)單,只需遍歷鏈表,每輪需要:建立新結(jié)點(diǎn) + 讓前驅(qū)結(jié)點(diǎn)的next指向當(dāng)前這個(gè)新結(jié)點(diǎn) + 讓當(dāng)前這個(gè)新結(jié)點(diǎn)的next指向空
復(fù)制復(fù)雜鏈表:本題鏈表的結(jié)點(diǎn)新增了 random 指針,指向鏈表中的任意結(jié)點(diǎn)或者null。這個(gè) random 指針意味著在復(fù)制過(guò)程中,除了構(gòu)建前驅(qū)結(jié)點(diǎn)的next指針,還要構(gòu)建前驅(qū)結(jié)點(diǎn)的ramdom指針。因此,每輪需要:建立2個(gè)新結(jié)點(diǎn) + 讓前驅(qū)結(jié)點(diǎn)的next指向第1個(gè)新結(jié)點(diǎn) + 讓前驅(qū)結(jié)點(diǎn)的random指向第2個(gè)新結(jié)點(diǎn)。但是這有一個(gè)問(wèn)題:并不是每次都需要建立2個(gè)新結(jié)點(diǎn)。有時(shí)候前驅(qū)結(jié)點(diǎn)的random指向的是已經(jīng)存在的結(jié)點(diǎn),但是如何判斷出來(lái)呢?如果把所有結(jié)點(diǎn)遍歷一遍,那就太麻煩了。
思路
利用哈希表的查詢特點(diǎn),考慮構(gòu)建原鏈表結(jié)點(diǎn)和新鏈表對(duì)應(yīng)結(jié)點(diǎn)的鍵值對(duì)映射關(guān)系,再遍歷構(gòu)建新鏈表各結(jié)點(diǎn)的next和random引用指向即可。
算法流程:
①若頭節(jié)點(diǎn)head為空結(jié)點(diǎn),直接返回NULL ;
②初始化:聲明一個(gè)哈希表dic,定義一個(gè)結(jié)點(diǎn)cur指向頭結(jié)點(diǎn),這個(gè)cur控制后面的循環(huán)
③建立哈希映射:遍歷這個(gè)鏈表,每個(gè)鏈表結(jié)點(diǎn)對(duì)應(yīng)建立一個(gè)新結(jié)點(diǎn),并向dic添加鍵值對(duì)(原cur結(jié)點(diǎn), 新cur結(jié)點(diǎn))
④構(gòu)建新鏈表的引用指向:構(gòu)建新結(jié)點(diǎn)的next和random引用指向
⑤返回值: 返回新鏈表的頭結(jié)點(diǎn),即dic[cur]

三、整體代碼
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
//若是空鏈表,則返回NULL
if(head == NULL) return NULL;
//創(chuàng)建一個(gè)結(jié)點(diǎn),指向這個(gè)鏈表的頭結(jié)點(diǎn)。這個(gè)結(jié)點(diǎn)用來(lái)控制后面的循環(huán)
Node* cur = head;
//創(chuàng)建一個(gè)哈希表
unordered_map<Node*, Node*> map;
while(cur != NULL){
//為鏈表每個(gè)結(jié)點(diǎn)創(chuàng)建一個(gè)對(duì)應(yīng)的新結(jié)點(diǎn),并建立原結(jié)點(diǎn)和新結(jié)點(diǎn)的Map映射
map[cur] = new Node(cur->val);
cur = cur->next;
}
cur = head;
//為新鏈表每個(gè)結(jié)點(diǎn)的next和random設(shè)置對(duì)應(yīng)的指向
while(cur != NULL){
map[cur]->next = map[cur->next];
map[cur]->random = map[cur->random];
cur = cur->next;
}
//返回新鏈表的頭結(jié)點(diǎn)
return map[head];
}
};

總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++之構(gòu)造函數(shù)默認(rèn)值設(shè)置方式
這篇文章主要介紹了C++之構(gòu)造函數(shù)默認(rèn)值設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
C語(yǔ)言實(shí)現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生學(xué)籍管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
學(xué)生成績(jī)管理系統(tǒng)C語(yǔ)言代碼實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言代碼實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
Linux中使用VS Code編譯調(diào)試C++項(xiàng)目詳解
最近因?yàn)轫?xiàng)目的需求,需要在Linux下開(kāi)發(fā)C++相關(guān)項(xiàng)目,經(jīng)過(guò)一番摸索最終實(shí)現(xiàn)了,下面這篇文章就給大家簡(jiǎn)單總結(jié)了一下如何通過(guò)VS Code進(jìn)行編譯調(diào)試的一些注意事項(xiàng)。有需要的朋友們可以參考借鑒,下面來(lái)跟著小編一起看看吧。2016-12-12

