复制带随机指针的链表的题型分析(包含流程图分析)

一、题目要求

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的 深拷贝

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0n-1);如果不指向任何节点,则为 null

示例 1:

img

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

示例 2:

img

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

img

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。

二、使用HashMap的解法

public class Solution {

    public Node copyRandomList(Node head) {
        if (head == null) {
            return head;
        }
        HashMap<Node, Node> hashMap = new HashMap<Node, Node>();
        Node newNode = head;
        while (newNode != null) {
            if (!hashMap.containsKey(newNode)) {
                Node node = new Node(newNode.val);
                hashMap.put(newNode, node);
            }
            if (newNode.random != null) {
                Node random = newNode.random;
                if (!hashMap.containsKey(random)) {
                    Node node = new Node(random.val);
                    hashMap.put(random, node);
                }
                hashMap.get(newNode).random = hashMap.get(random);
            }
            newNode = newNode.next;
        }
        newNode = head;
        while (newNode.next != null) {
            hashMap.get(newNode).next = hashMap.get(newNode.next);
            newNode = newNode.next;
        }
        return hashMap.get(head);
    }
}

三、使用添加节点的解法

public class Solution {

    public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        copy(head);
        copyRandom(head);
        return split(head);
    }


    private Node split(Node head) {
        Node result = head.next;
        Node move = head.next;
        while (head != null && head.next != null) {
            head.next = head.next.next;
            head = head.next;
            if (move != null && move.next != null) {
                move.next = move.next.next;
                move = move.next;
            }
        }
        return result;
    }

    private void copyRandom(Node head) {
        Node node = head;
        while (node != null && node.next != null) {
            if (node.random != null) {
                node.next.random = node.random.next;
            }
            node = node.next.next;
        }
    }


    private void copy(Node head) {
        Node node = head;
        while (node != null) {
            Node copy = new Node(node.val);
            copy.next = node.next;
            node.next = copy;
            node = copy.next;
        }
    }
}

四、测试用例

public class Test {

    public static void main(String[] args) {
        // 空链表测试
        Node empty = null;
        Node emptyNode1 = Solution1.copyRandomList(empty);
        Node emptyNode2 = Solution2.copyRandomList(empty);
        System.out.println("空链表测试:");
        System.out.println("方法1:");
        show(emptyNode1);
        System.out.println("方法2:");
        show(emptyNode2);

        // 一个节点链表测试
        Node one = new Node(1);
        one.next = null;
        one.random = null;
        Node oneNode1 = Solution1.copyRandomList(one);
        Node oneNode2 = Solution2.copyRandomList(one);
        System.out.println("一个节点链表测试:");
        System.out.println("方法1:");
        show(oneNode1);
        System.out.println("方法2:");
        show(oneNode2);

        // 两个节点链表测试
        Node two = new Node(1);
        two.next = new Node(2);
        two.random = null;
        two.next.random = two;
        Node twoNode1 = Solution1.copyRandomList(two);
        Node twoNode2 = Solution2.copyRandomList(two);
        System.out.println("两个节点链表测试:");
        System.out.println("方法1:");
        show(twoNode1);
        System.out.println("方法2:");
        show(twoNode2);

        // 正常链表测试
        Node list = new Node(1);
        list.next = new Node(2);
        list.next.next = new Node(3);
        list.next.next.next = new Node(4);
        list.random = list.next.next;
        list.next.random = list;
        list.next.next.random = null;
        list.next.next.next.random = list.next;
        Node listNode1 = Solution1.copyRandomList(list);
        Node listNode2 = Solution2.copyRandomList(list);
        System.out.println("正常链表测试:");
        System.out.println("方法1:");
        show(listNode1);
        System.out.println("方法2:");
        show(listNode2);
    }

    private static void show(Node node) {
        while (node != null) {
            System.out.println("数值:" + node.val);
            if (node.next != null) {
                System.out.println("下一节点数值:" + node.next.val);
            } else {
                System.out.println("下一节点数值:" + null);
            }
            if (node.random != null) {
                System.out.println("随机节点数值:" + node.random.val);
            } else {
                System.out.println("随机节点数值:" + null);
            }
            node = node.next;
        }
    }
}

五、流程图

(一)、使用HashMap的流程图

1、初始状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hk6baDgq-1603641247828)(C:\Users\huang\AppData\Roaming\Typora\typora-user-images\image-20201025235347376.png)]
2、开始复制节点

在这里插入图片描述
3、复制节点结束

在这里插入图片描述
4、赋值next节点

在这里插入图片描述

(二)、添加节点的流程图

1、初始状态
在这里插入图片描述
2、创建第一个复制节点
在这里插入图片描述
3、第一个复制节点添加完毕
在这里插入图片描述

4、复制节点添加完毕
在这里插入图片描述

5、复制节点random指针赋值完毕
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值