题目:

请实现函数ComplexListNode clone(ComplexListNode head)复制一个复杂链表。在复杂链表中,每个结点除了一个next引用指向下一个结点,还有一个sibling引用指向任意结点或null。

面试题35:复杂链表的复制_时间复杂度

分析:

第一种方法:

第一步复制原始链表上的每个结点,并用next连接起来,第二步设置每个结点的sibling引用,在第二步设置sibling的时候,因为无法确定sibling的位置,所以每次查找sibling都需要O(n)的时间。所以总体的时间复杂度是O(n²)。

第二种方法:

第一步复制原始链表上每个结点N创建N',然后把这些结点用next连接起来,同时我们把<N,N'>的配对信息保存到哈希表中,第二步设置sibling引用,如果原始链表结点N的sibling是结点S,那么在复制链表中,对应N'指向S',有了哈希表,可以在O(1)时间找到S'。此时时间复杂度是O(n)。

第三种方法:第一步根据原始链表的每个结点N创建对应的N',这一次,我们把N'接在N的后面。第二步设置N'结点的sibling,原始链表上N的sibling是S,复制出来的N'的sibling是S',S'是S的next结点。第二种方法将<N,N'>的关系存储在了哈希表里,这里将关系存储在next上,所以这种方法节省了内存空间。第三步将链表拆分,将奇数位置上结点用next连接起来,就是原始链表,将偶数位置上结点用next连接起来,就是复制出来的链表。

解法:

package com.wsy;

class ComplexListNode {
private char value;
private ComplexListNode next;
private ComplexListNode sibling;

public ComplexListNode() {
}

public ComplexListNode(char value) {
this.value = value;
this.next = this.sibling = null;
}

public ComplexListNode(char value, ComplexListNode next, ComplexListNode sibling) {
this.value = value;
this.next = next;
this.sibling = sibling;
}

public char getValue() {
return value;
}

public void setValue(char value) {
this.value = value;
}

public ComplexListNode getNext() {
return next;
}

public void setNext(ComplexListNode next) {
this.next = next;
}

public ComplexListNode getSibling() {
return sibling;
}

public void setSibling(ComplexListNode sibling) {
this.sibling = sibling;
}

@Override
public String toString() {
return "value=" + value +
", next=" + (next == null ? "null" : next.getValue()) +
", sibling=" + (sibling == null ? "null" : sibling.getValue() + "");
}
}

public class Main {
public static void main(String[] args) {
ComplexListNode head = init();
print(head);
ComplexListNode cloneHead = clone(head);
print(cloneHead);
}

public static ComplexListNode init() {
ComplexListNode A = new ComplexListNode('A');
ComplexListNode B = new ComplexListNode('B');
ComplexListNode C = new ComplexListNode('C');
ComplexListNode D = new ComplexListNode('D');
ComplexListNode E = new ComplexListNode('E');
A.setNext(B);
A.setSibling(C);
B.setNext(C);
B.setSibling(E);
C.setNext(D);
D.setNext(E);
D.setSibling(B);
return A;
}

public static void print(ComplexListNode head) {
while (head != null) {
System.out.println(head);
head = head.getNext();
}
System.out.println();
}

public static ComplexListNode clone(ComplexListNode head) {
if (head == null) {
return null;
}
head = step1(head);
head = step2(head);
head = step3(head);
return head;
}

private static ComplexListNode step1(ComplexListNode head) {
ComplexListNode cloneNode;
ComplexListNode tempHead = head;
while (head != null) {
cloneNode = new ComplexListNode(head.getValue());
cloneNode.setNext(head.getNext());
head.setNext(cloneNode);
head = cloneNode.getNext();
}
return tempHead;
}

private static ComplexListNode step2(ComplexListNode head) {
ComplexListNode tempHead = head;
while (head != null) {
ComplexListNode cloneNode = head.getNext();
if (head.getSibling() != null) {
cloneNode.setSibling(head.getSibling().getNext());
}
head = cloneNode.getNext();
}
return tempHead;
}

private static ComplexListNode step3(ComplexListNode head) {
ComplexListNode cloneHead = head.getNext();
ComplexListNode cloneNode = head.getNext();
ComplexListNode node = cloneNode.getNext();
while (node != null) {
cloneNode.setNext(node.getNext());
cloneNode = cloneNode.getNext();
node.setNext(cloneNode.getNext());
node = node.getNext();
}
return cloneHead;
}
}