1. 程式人生 > 其它 >劍指offer——複雜連結串列的複製C++

劍指offer——複雜連結串列的複製C++

技術標籤:劍指Offer#連結串列指標連結串列單鏈表演算法劍指offer

在這裡插入圖片描述
預設所有結點的random指標不會指向不在連結串列中的獨立結點。
兩種方法:遞迴和迴圈
遞迴:需要通過一個輔助的map來實現,這個map是用來處理random指標指向的結點的,防止重複新建node。在遞迴函式中根據當前結點的值new一個結點指標,在map記錄當前指標對應的指標是新建的這個。然後遞迴next結點。當next都遞迴完後,判斷當前結點的random是否為空,如果不為空,就將新建的這個結點的random指向map儲存的原結點的random指標的拷貝指標。最後返回新建的指標即可。

迴圈:三步法,每一步都不簡單,每一步都有細節,好處就是不用O(N)空間複雜度的map

1.複製單鏈表,將A1插入到A後面,A2前面
2.連線random域,A1.random = A.random.next
3.拆分單鏈表,改變A1的next為A的next的next
定義一個currentnode來指向當前遍歷到的結點,初始賦值為pHead
第一步:當currentnode為空時結束迴圈,根據currennode來new一個克隆結點,並且定義一個nextnode來儲存當前結點的下一個結點(防止等下改變next後找不到後序的結點)。將當前結點的next改為克隆結點,將克隆結點的next改為nextnode,currentnode=nextnode。
第二步:將currentnode重新指向pHead,重新回到這條鏈的起點處。這次currentnode指的全是原先連結串列中的結點,不是克隆結點,所以跳著訪問。找原連結串列上的所有結點random指標是否為空,如果不為空,就將當前結點的random指標的next賦給當前結點的拷貝(也就是當前結點的next)的random。最後使currentnode指向它next的next。
第三步:將克隆結點的next指向克隆結點next的next,記得返回pHead的next,這才是克隆連結串列的頭結點。

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    //map<RandomListNode*,RandomListNode*> ma;
RandomListNode* Clone(RandomListNode* pHead) { //首先我們要知道所有random結點都是在這條連結串列裡的,不存在一個獨立結點被random指到 //所有random結點都能被next指到 //所以先遞迴複製所有next指標指向的結點,並將其存入ma中,可以通過原結點找到深拷貝的結點 //每一輪遞迴複製完next後,從ma中拿出原結點的random復給現在結點的random /*if(pHead == NULL) return NULL; RandomListNode* node = new RandomListNode(pHead->label); ma[pHead] = node; node->next = Clone(pHead->next); node->random = NULL; if(pHead->random) node->random = ma[pHead->random]; return node;*/ //法2:三步法,通過next指標關聯,不用輔助map //複製單鏈表,將A1插入到A後面,A2前面 //連線random域,A1.random = A.random.next //拆分單鏈表,改變A1的next為A的next的next if(pHead == NULL) return NULL; RandomListNode* currentNode = pHead; while(currentNode != NULL){ RandomListNode* cloneNode = new RandomListNode(currentNode->label); RandomListNode* nextNode = currentNode->next; currentNode->next = cloneNode; cloneNode->next = nextNode; currentNode = nextNode; } currentNode = pHead; while(currentNode != NULL){ //這個判斷必須加! if(currentNode->random != NULL){//如果原結點random指標不為空 //那麼複製的結點的random就指向原結點的random的複製結點 currentNode->next->random = currentNode->random->next; } currentNode = currentNode->next->next; } currentNode = pHead; RandomListNode* pCloneHead = pHead->next; while(currentNode != NULL){ RandomListNode* cloneNode = currentNode->next; currentNode->next = cloneNode->next; cloneNode->next = cloneNode->next == NULL ? NULL : cloneNode->next->next; currentNode = currentNode->next; } return pCloneHead; } };