劍指offer66題--Java實現,c++實現和python實現 25.複雜連結串列的複製
阿新 • • 發佈:2018-12-29
題目描述
輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空)
C++
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: /* 三步法 */ RandomListNode* Clone(RandomListNode* pHead) { if (!pHead) return nullptr; RandomListNode* pNode = pHead; // 複製原始連結串列的任一節點並連結到該節點的後邊 while (pNode) { RandomListNode* pTemp = new RandomListNode(pNode->label); pTemp->next = pNode->next; pNode->next = pTemp; pNode = pTemp->next; } // 初始化複製節點的random關係 pNode = pHead; while (pNode) { RandomListNode* pTemp = pNode->next; if(pNode->random) pTemp->random = pNode->random->next; pNode = pTemp->next; } // 從連結串列中拆分出新連結串列 RandomListNode* pCopyHead = pHead->next; RandomListNode* pCopyNode= pHead->next; pNode = pHead; while (pNode) { pNode->next = pCopyNode->next; if(pNode->next) pCopyNode->next = pNode->next->next; pNode = pNode->next; pCopyNode = pCopyNode->next; } return pCopyHead; } /* Hash表法 */ RandomListNode* Clone2(RandomListNode* pHead) { if (!pHead) return nullptr; map<RandomListNode*, RandomListNode*> nodeMap; RandomListNode* pNode = pHead; /* 建立結點 */ while (pNode) { RandomListNode* pTemp = new RandomListNode(pNode->label); nodeMap[pNode] = pTemp; pNode = pNode->next; } pNode = pHead; /* 建立連線關係 */ while (pNode) { RandomListNode* pTemp = nodeMap[pNode]; pTemp->next = nodeMap[pNode->next]; pTemp->random = nodeMap[pNode->random]; pNode = pNode->next; } return nodeMap[pHead]; } };
java
/* public class RandomListNode { int label; RandomListNode next = null; RandomListNode random = null; RandomListNode(int label) { this.label = label; } } */ import java.util.HashMap; import java.util.Map; /* public class RandomListNode { int label; RandomListNode next = null; RandomListNode random = null; RandomListNode(int label) { this.label = label; } } */ public class Solution { public RandomListNode Clone(RandomListNode pHead) { if (pHead == null) { return null; } RandomListNode pHead1 = pHead; RandomListNode pHead2 = new RandomListNode(pHead.label); RandomListNode newHead = pHead2; Map<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>(); map.put(pHead1, pHead2); while (pHead1 != null) { if (pHead1.next != null) { pHead2.next = new RandomListNode(pHead1.next.label); } else { pHead2.next = null; } pHead1 = pHead1.next; pHead2 = pHead2.next; map.put(pHead1, pHead2); } pHead1 = pHead; pHead2 = newHead; while (pHead1 != null) { pHead2.random = map.get(pHead1.random); pHead1 = pHead1.next; pHead2 = pHead2.next; } return newHead; } }
python
# -*- coding:utf-8 -*- # class RandomListNode: # def __init__(self, x): # self.label = x # self.next = None # self.random = None class Solution: # 返回 RandomListNode def Clone(self, pHead): # write code here head = pHead p_head = None new_head = None #頭結點 random_dic = {} old_new_dic = {} while head: node = RandomListNode(head.label) #這道題還有一個要求就是不能用節點引用,一定要建立新的節點 #複製原節點的label到新的連結串列中 node.random = head.random #複製原節點的隨機指標到新的連結串列中 old_new_dic[id(head)] = id(node) #建立字典,以原節點的記憶體地址作為key,新節點的記憶體地址作為value random_dic[id(node)] = node #建立另一個字典,以新節點的地址作為key,新節點作為value head = head.next #將head指向下一個節點 if new_head: new_head.next = node new_head = new_head.next #給新連結串列 else: new_head = node p_head = node #當新連結串列為空時,為新連結串列的頭結點賦值,這裡比較巧妙的就是phead可以作為頭結點,而new_head可以放心 #向後移動 new_head = p_head while new_head: if new_head.random != None: new_head.random = random_dic[old_new_dic[id(new_head.random)]] #這裡的問題就是old_new_dic中就沒有id(new_head.random])的鍵, #因為old_new_dic中的鍵是原節點的地址,但是這裡以新節點的隨機節點指標指向了 #一個隨機的節點,這樣的話,隨機節點也是原節點中的,因此,這根據隨機節點找到對應的新節點的記憶體地址了, #然後通過random_dic就找到了新節點了 new_head = new_head.next #這個迴圈的目的就是找到new_head的random屬性 #現在又出現一個問題,在上邊,不是已經把head.random賦給了new_head.random嗎? #那麼進一步推理,存在一種可能,那就是前邊並沒有給new_head賦予屬性random return p_head