zoukankan      html  css  js  c++  java
  • LeetCode 138 复制带随机指针的链表

    链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer

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

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

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

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

    示例 1:

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

    示例 2:

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


    示例 3:

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


    示例 4:

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

    提示:

    -10000 <= Node.val <= 10000
    Node.random 为空(null)或指向链表中的节点。
    节点数目不超过 1000 。

    这道题画个图会比较好理解,做法就是在原链表中,在每个结点的后面复制一个与它相同的结点。然后,让复制的结点的random指针和被复制的结点的一样。再将原链表和复制链表分离开来。

    写了两个版本的代码,区别在于一个用的while循环,一个用的for循环,用for循环会比较简洁。还有就是在分离操作的时候,一个用了双指针,有点繁琐,但是很好想啦。其实用一个指针就可以完成分离操作,但要定义一个dummy虚拟头结点。

    c++代码如下:

     1 class Solution {
     2 public:
     3     Node* copyRandomList(Node* head) {
     4         if(!head) return head;
     5         auto p = head;
     6         while(p){
     7             auto q = new Node(p->val);
     8             q->next = p->next;
     9             p->next = q;
    10             p = q->next;
    11         }
    12         auto k = head;
    13         while(k){
    14             if(k->random) k->next->random = k->random->next;
    15             k = k->next->next;
    16         }
    17         auto copy = head->next;
    18         auto a = head, b = head->next->next; 
    19         while(b){
    20             a->next->next = b->next;
    21             a->next = b;
    22             a = b;
    23             b = b->next->next;
    24         }
    25         a->next = b;
    26         return copy;
    27     }
    28 };

    更简洁、更妙的解法如下:

     1 class Solution {
     2 public:
     3     Node* copyRandomList(Node* head) {
     4         if(!head) return head;
     5         for(auto p = head; p; p = p->next->next){
     6             auto q = new Node(p->val);
     7             q->next = p->next;
     8             p->next = q;
     9         }
    10         
    11         for(auto k = head; k; k = k->next->next){
    12             if(k->random) k->next->random = k->random->next;
    13         }
    14         auto dummy = new Node(-1);
    15         auto cur = dummy;
    16         for(auto p = head; p;p = p->next){
    17             cur->next = p->next;
    18             p->next = cur->next->next;
    19             cur = cur->next;
    20         }
    21 
    22         return dummy->next;
    23     }
    24 };
  • 相关阅读:
    Chapter 2 Sockets and Patterns【选译,哈哈】 Part 2 Messags Partterns
    WPF动态更改Image控件图片路径
    Chapter 2 Sockets and Patterns【选译,哈哈】 Part 1
    Chapter 2 Sockets and Patterns【选译,哈哈】 Part 4 Handling Errors and ETERM
    Chapter 2 Sockets and Patterns【选译,哈哈】 Part 3 Messags Partterns
    Visual Studio 2008 测试项目无法正常显示解决办法
    Ext.NET控件介绍—Form控件
    ThoughtWorks(中国)程序员读书雷达
    Ext.net 中日期格式的计算
    Sql 分割 键值对字符串 得到某值对应的名称
  • 原文地址:https://www.cnblogs.com/hellosnow/p/12247142.html
Copyright © 2011-2022 走看看