力扣原题,链表面试题之复制带随机指针的链表

简介: 力扣原题,链表面试题之复制带随机指针的链表

一种特殊的单链表节点类型描述如下:

public static class Node{
    public int value;
    public Node next;
    public Node rand;
    public Node(int v) {
      value=v;
    }
  }

rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。要求:时间复杂度O(N),额外空间复杂度O(1),注意,无环是指next方向上是无环的!!!

方法一(笔试用,最简单):在next方向上正常遍历一遍链表,遍历过程种将每个结点克隆存入HashMap<Node,Node>,表中的key是老结点,value是克隆的结点。就是人为构造一种对应关系,之后再遍历一遍链表,便可实现,具体看下面代码。但是这种方法在空间复杂度上没有做到O(1)

方法二(面试用):额外空间复杂度O(1),具体看代码

package com.harrison.class06;
import java.util.HashMap;
public class Code04_CopyListWithRandom {
  public static class Node {
    public int value;
    public Node next;
    public Node rand;
    public Node(int v) {
      value = v;
    }
  }
  public static Node copyRandomList1(Node head) {
    HashMap<Node, Node> map = new HashMap<Node, Node>();
    Node cur = head;
    while (cur != null) {
      map.put(cur, new Node(cur.value));
      cur = cur.next;
    }
    cur = head;
    while (cur != null) {
      // cur (key)老结点 map.get(cur) (value)新结点
      map.get(cur).next = map.get(cur.next);
      map.get(cur).rand = map.get(cur.rand);
      cur = cur.next;
    }
    return map.get(head);
  }
  public static Node copyRandomList2(Node head) {
    if (head == null) {
      return null;
    }
    // 1 -> 2 -> 3 -> null
    // 1 -> 1' -> 2 -> 2' -> 3 -> 3' -> null
    Node cur = head;// 老结点
    Node next = null;// 老结点的下一个结点
    while (cur != null) {
      next = cur.next;// next记住老结点的下一个结点
      cur.next = new Node(cur.value);// 当前的老结点指向 复制自己的结点
      cur.next.next = next;// 复制的结点指向 next
      cur = next;
    }
    cur = head;
    Node copy = null;// 复制的结点
    // 依次设置 1' 2' 3' 的rand指针
    while (cur != null) {
      next = cur.next.next;// next 记住老结点的下一个结点
      copy = cur.next;// copy 来到(第一个)复制的结点
      // copy结点的rand指针指向 老结点的rand指针指向的结点的next指针
      copy.rand = cur.rand != null ? cur.rand.next : null;
      cur = next;// 当前结点往下跳
    }
    Node res = head.next;// 记住复制后的链表的头结点
    cur = head;
    // next方向上,把新老链表分离,rand方向不要动
    while (cur != null) {
      next = cur.next.next;// next 记住老结点的下一个结点
      copy = cur.next;// copy 来到(第一个)复制的结点
      // copy结点的next指针指向 下一个老结点的next指针
      copy.next = next != null ? next.next: null;
      cur = next;// 当前结点往下跳
    }
    return res;
  }
  public static void printLinkedList(Node node) {
    System.out.print("Linked List:");
    while (node != null) {
      System.out.print(node.value + " ");
      node = node.next;
    }
    System.out.println();
  }
  public static void main(String[] args) {
    Node head1 = new Node(7);
    head1.next = new Node(9);
    head1.next.next = new Node(1);
    head1.next.next.next = new Node(8);
    head1.next.next.next.next = new Node(5);
    head1.next.next.next.next.next = new Node(2);
    head1.next.next.next.next.next.next = new Node(5);
    printLinkedList(head1);
    //head1=copyRandomList1(head1);
    head1 = copyRandomList2(head1);
    printLinkedList(head1);
  }
}
相关文章
|
13天前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
15 0
|
13天前
|
编译器 C语言
经典左旋,指针面试题
文章介绍了两种C语言实现字符串左旋的方法,以及如何使用C语言对整数数组进行奇偶数排序。通过实例演示了如何使用函数reverse_part和leftRound,以及在swap_arr中实现数组元素的重新排列。
24 0
|
19天前
|
Serverless 编译器 C语言
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
|
3月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
50 1
【数据结构OJ题】复制带随机指针的链表
|
2月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
19 1
|
2月前
|
存储 算法 数据处理
指针与链表
指针与链表
55 0
|
3月前
|
Python
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题
|
3月前
|
存储 算法 索引
1124. 表现良好的最长时间段 (python) 前缀和 分类讨论 最大长度 力扣 面试题
1124. 表现良好的最长时间段 (python) 前缀和 分类讨论 最大长度 力扣 面试题
|
3月前
|
存储 算法
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
|
13天前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
15 0