数据结构与算法_剑指Offer26_复杂链表的复制_JAVA实现

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));
    }
}

没理清代码没关系,我这次也写了好久,思路清晰,但是码的时间太长,欢迎前辈指正

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值