克隆链表

链表克隆,今天看面经的时候,发现很多公司都考了这个题目,也有很多童鞋挂在这个题目上,废话不多说,直接说解决办法。

1. 克隆链表

最简单的,从直接克隆简单链表开始吧,链表结构定义如下:

 class RandomListNode {
     int label;
     RandomListNode next, random;
     RandomListNode(int x) { this.label = x; }
 };

使用递归或遍历链表进行求解
1, 使用遍历的方法

  public RandomListNode copyRandomList(RandomListNode head) {
      if(head == null){
          return head;
      }
      RandomListNode t = head;
      RandomListNode res = new RandomListNode(0);
      RandomListNode p = res;;
      while(t != null){
          RandomListNode t = new RandomListNode(head.label);
          p.next = t;
          p = p.next;
          t = t.next;
      }
      return res.next;
 }

2,使用递归的方法

  public RandomListNode copyRandomList(RandomListNode head) {
      if(head == null){
          return head;
      }else{
          RandomListNode p = new RandomListNode(head.label);
          p.next = copyRandomList(head.next);
          return p;
      }
  }

2. 克隆带有两个next指针的链表

除了指向next的指针,还多了一个random指针,这个random可以指向链表中的任意元素或者为null,链表结构定义如下:

 class RandomListNode {
     int label;
     RandomListNode next, random;
     RandomListNode(int x) { this.label = x; }
 };

解决方法如下:

    public RandomListNode copyRandomList(RandomListNode head) {
        if(head == null){
            return head;
        }
        RandomListNode p = head;

        while(p != null){
            //new 新节点
            RandomListNode newNode = new RandomListNode(p.label);
            newNode.random = p.random;

            //将新节点插到当前节点之后
            newNode.next = p.next;
            p.next = newNode;
            //当前节点后移
            p = newNode.next;
        }

        //调整random节点 指向新的copy节点
        p = head.next;
        while(p != null){
            if(p.random != null){
                p.random = p.random.next;
            }
            if(p.next == null){
                break;
            }
            p = p.next.next;
        }
        RandomListNode result = new RandomListNode(0);
        RandomListNode t = head;
        p = result;
        //拆分链表,偶数节点都是新链表中的节点,其余的是原始链表中的节点
        while(t != null){
            p.next = t.next;
            p = p.next;
            //断开原始链表连接到新节点的next指针
            t.next = p.next;
            t = p.next;
        }
        return result.next;
    }

这个题目来自leetcode,还有一种解法,挺直观的,但是需要用到Map这种数据结构,不知道在面试的时候,是不是可以用,解法如下:

    public RandomListNode copyRandomList(RandomListNode head) {
        RandomListNode result = new RandomListNode(0);
        Map<RandomListNode, RandomLsitNode> randomLinks = new HashMap<>();
        RandomListNode p = result;
        RandomListNode t1 = head;

        while(t1.next != null){
            //new新的节点
            RandomListNode newNode = new RandomListNode(t1.label);
            // 设置新链表的random 指向原来链表的random
            newNode.random = t1.random;
            // add node 到新链表上
            p.next = newNode;
            p = p.next;

            //记录原始链表和新链表的对应关系
            randomLinks.put(t1, newNode);

            t1 = t1.next;
        }
        //将新链表中的原始random更改指向新链表中的节点(原来的random 是指向的原始链表中的节点的。)
        t1 = result.next;
        while(t1 != null){
            if (t1.random != null){
                t1.random = randomLinks.get(t1.random);
            }
            t1 = t1.next;
        }
        return result.next;
    }

3. 克隆带有三个next指针的链表

哈哈,要是在多一个random2 指针 怎么搞? 数据结构定义如下:

 class RandomListNode {
     int label;
     RandomListNode next, random, random2;
     RandomListNode(int x) { this.label = x; }
 };

区别在25-27行
好吧,原谅我在扯淡,这个解法和二中的解法一样,没啥区别,代码如下:

    public RandomListNode copyRandomList(RandomListNode head) {
        if(head == null){
            return head;
        }
        RandomListNode p = head;

        while(p != null){
            //new 新节点
            RandomListNode newNode = new RandomListNode(p.label);
            newNode.random = p.random;

            //将新节点插到当前节点之后
            newNode.next = p.next;
            p.next = newNode;
            //当前节点后移
            p = newNode.next;
        }

        //调整random节点 指向新的copy节点
        p = head.next;
        while(p != null){
            if(p.random != null){
                p.random = p.random.next;
            }
            if(p.random2 != null){
                p.random2 = p.random2.next;
            }

            if(p.next == null){
                break;
            }
            p = p.next.next;
        }
        RandomListNode result = new RandomListNode(0);
        RandomListNode t = head;
        p = result;
        //拆分链表,偶数节点都是新链表中的节点,其余的是原始链表中的节点
        while(t != null){
            p.next = t.next;
            p = p.next;
            //断开原始链表连接到新节点的next指针
            t.next = p.next;
            t = p.next;
        }
        return result.next;
    }

当有n个next的时候,我就不继续扯淡了,解法可以类比克隆三个next的时候,多做几次调整random就好了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值