• 算法练习(9)-复杂带随机指针的单链表


    所谓带随机指针的链表,结构如下:

    class Node {
        int val;
        Node next;
        Node random;
    
        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }
    

    除next外,还有一个随机指针random,随机指向链表中的某个元素(当然 :random也可能为null). 复制的难度在于, 新节点刚new出来时,其random指向的另外1个“新”节点,可能还没复制出来(即:首次无法确定新节点的random该指向谁,除非所有老节点全复制完)

     
    有二种做法:
    1、借助额外的Map记录“新-老”节点的映射
    public Node copyRandomList(Node head) {
            if (head==null){
                return null;
            }
            Node h = head;
            Map<Node,Node> map = new HashMap<>();
            Node newHead = new Node(head.val);
            Node curr = newHead;
            //第一轮,复制节点,random挂空,同时记录处理过的老节点与新节点的映射关系
            while(head!=null){
                if (head.next!=null){
                    Node newNext = new Node(head.next.val);
                    curr.next = newNext;
                }
                map.put(head,curr);
                head = head.next;
                curr = curr.next;
            }
            head = h;
            //第二轮,处理random指向,通过map映射,查到random指向的新节点
            while(head!=null){
                Node newNode = map.get(head);
                if (head.random!=null){
                    newNode.random = map.get(head.random);
                }
                head = head.next;
            }
            return newHead;
        }
    

      

    2、如果要求空间复杂度为O(1),还有1个比较巧妙的思路

    a、 先把每个节点复制一份, 挂在自己身后,相当于A -> B -> C 变成 A -> A' -> B -> B' -> C -> C'
    b、 每2轮,处理random时,通过身后的“影子”,就能找到random的新节点在哪
    c、 将链表分离, A -> A' -> B -> B' -> C -> C' 变成 A -> B -> C 和A' -> B' -> C' 返回A'
    public Node copyRandomList(Node head) {
            if (head==null){
                return head;
            }
            Node curr = head;
            //复制自身,挂在身后
            while(curr!=null){
                Node newNode = new Node(curr.val);
                newNode.next = curr.next;
                curr.next = newNode;
                curr = curr.next.next;
            }
    
            //复制random
            curr = head;
            while(curr!=null){
                if (curr.random!=null){
                    curr.next.random = curr.random.next;
                }
                curr = curr.next.next;
            }
    
            //分离链表
            curr = head;
            Node newHead = head.next;
    
            while(curr!=null){
                Node newCurr = curr.next;
                curr.next = curr.next.next;
                if (newCurr.next!=null){
                    newCurr.next = newCurr.next.next;
                }
                curr = curr.next;
            }
    
            return newHead;
        }
    

      

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    线上一个数组查询遇到的坑
    Java加密解密字符串
    图片和字符串相互转换
    fastweixin 微信服务器开发框架
    从url下载图片--java与python实现方式比较
    jvm 配置,看看
    牛腩新闻公布系统---外键约束下怎样删除记录
    jquery常见面试题
    [Oracle] 位图索引
    hadoop经常使用的压缩算法总结和实验验证
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/15448823.html
Copyright © 2020-2023  润新知