1. 程式人生 > >劍指offer66題--Java實現,c++實現和python實現 25.複雜連結串列的複製

劍指offer66題--Java實現,c++實現和python實現 25.複雜連結串列的複製

題目描述

輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的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