剑指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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值