2020.05.12
题目
请实现函数ComplexListNode clone(ComplexListNode head),复制一个复杂链表。在复杂链表中,每个结点除了有一个next 域指向下一个结点外,还有一个sibling 指向链表中的任意结点或者null。
点击链接
结点定义
public static class ComplexListNode {
int value;
ComplexListNode next;
ComplexListNode sibling;
}
解题思路
图4.8 是一个含有 5 个结点的复杂链表。图中实线箭头表示 next 指针,虚线箭头表示 sibling 指针。为简单起见,指向 null 的指针没有画出。
在不用辅助空间的情况下实现O(n)的时间效率。
第一步:**仍然是根据原始链表的每个结点 N 创建对应的 N’。**把 N’ 链接在 N 的后面。图4.8的链表经过这一步之后的结构,如图4.9 所示。
第二步:**设置复制出来的结点的 sibling 。**假设原始链表上的 N 的 sibling 指向结点 S ,那么其对应复制出来的 N’ 是 N 的 pext 指向的结点,同样 S’ 也是 S 的 next 指向的结点。设置 sibling 之后的链表如图4.10 所示。
第三步:**把这个长链表拆分成两个链表。**把奇数位置的结点用 next .
链接起来就是原始链表,把偶数位置的结点用 next 链接起来就是复制
出来的链表。图 4.10 中的链表拆分之后的两个链表如图 4.11 所示。
package offer26;
public class Test {
/**
* 复杂链表结点
*/
public static class ComplexListNode {
int value;
ComplexListNode next;
ComplexListNode sibling;
}
public static ComplexListNode cloneNode(ComplexListNode head) {
if(head == null) {
throw new RuntimeException("链表结点为空");
}
copyNode(head);
copySibling(head);
return extractCloneNode(head);
}
public static void copyNode(ComplexListNode head) {
ComplexListNode currentNode = head;
while (currentNode != null) {
ComplexListNode newNode = new ComplexListNode();
//方便查看是否是clone过来的
newNode.value = currentNode.value + 100;
newNode.next = currentNode.next;
currentNode.next = newNode;
currentNode = newNode.next;
}
}
public static void copySibling(ComplexListNode head) {
ComplexListNode currentNode = head;
while (currentNode != null) {
ComplexListNode tmpNode = currentNode.next;
if(currentNode.sibling != null) {
//这里注意的是复制结点第二指向的是原结点第二指向的下个结点
tmpNode.sibling = currentNode.sibling.next;
}
currentNode = tmpNode.next;
}
}
public static ComplexListNode extractCloneNode(ComplexListNode head) {
//当前处理原链表的结点
ComplexListNode currentNode = head;
//当前处理的复制链表的结点
ComplexListNode currentCloneNode = head.next;
//复制链表的头结点
ComplexListNode cloneNode = head.next;
//将处理的前后结点顺序调换,这样处理,处理的第一个结点是复制结点的头结点、原来链表的第二个结点
currentNode.next = currentCloneNode.next;
currentNode = currentNode.next;
while (currentNode != null) {
//复制结点的下个值指向原结点的下个值;复制节点后移;
currentCloneNode.next =currentNode.next;
currentCloneNode = currentCloneNode.next;
//原结点的下个值指向复制结点的下个值(当复制结点下个值没有)
currentNode.next = currentCloneNode.next;
currentNode = currentNode.next;
}
return cloneNode;
}
public static void print(ComplexListNode head) {
while (head != null) {
System.out.print(head.value + " —> ");
head = head.next;
}
System.out.println();
}
public static boolean isSame(ComplexListNode head1, ComplexListNode head2) {
if(head1 == null||head2 == null) {
return false;
}
ComplexListNode h1 = head1;
ComplexListNode h2 = head2;
while (h1 != null || h2 != null) {
if(h1.value == h2.value - 100) {
h1 = h1.next;
h2 = h2.next;
}else {
return false;
}
}
return h1 == null && h2 == null;
}
public static void main(String[] args) {
ComplexListNode head = new ComplexListNode();
head.value = 1;
head.next = new ComplexListNode();
head.next.value = 2;
head.next.next = new ComplexListNode();
head.next.next.value = 3;
head.next.next.next = new ComplexListNode();
head.next.next.next.value = 4;
head.next.next.next.next = new ComplexListNode();
head.next.next.next.next.value = 5;
head.sibling = head.next.next;
head.next.sibling = head.next.next.next.next.next;
head.next.next.next.sibling = head.next;
print(head);
ComplexListNode cloneHead = cloneNode(head);
print(head);
print(cloneHead);
System.out.println(isSame(head, cloneHead));
}
}
没理清代码没关系,我这次也写了好久,思路清晰,但是码的时间太长,欢迎前辈指正