【剑指Offer学习】【面试题26:复杂链表的复制】

题目:

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

结点模型定义:

#import 
// 复杂 链表
@interface QNComplexListNode : NSObject
// value
@property (nonatomic, assign) NSInteger value;
// next
@property (nonatomic, strong) QNComplexListNode *next;
// sibling
@property (nonatomic, strong) QNComplexListNode *sibling;
@end

思路:

图4.8 是一个含有5 个结点的复杂链表。图中实线箭头表示next 指针,虚线箭头表示sibling指针。为简单起见,指向null 的指针没有画出。

【剑指Offer学习】【面试题26:复杂链表的复制】_第1张图片
图4.8.png

在不用辅助空间的情况下实现O(n)的时间效率。

  • 仍然是根据原始链表的每个结点N 创建对应的N’。把N’链接在N的后面。图4.8 的链表经过这一步之后的结构,如图4.9所示。
【剑指Offer学习】【面试题26:复杂链表的复制】_第2张图片
图4.9.png
  • 设置复制出来的结点的sibling。假设原始链表上的Nsibling指向结点S,那么其对应复制出来的N’Npext指向的结点,同样S’也是Snext指向的结点。设置sibling之后的链表如图4.10所示。
【剑指Offer学习】【面试题26:复杂链表的复制】_第3张图片
图4.10.png
  • 把这个长链表拆分成两个链表。把奇数位置的结点用next .
    链接起来就是原始链表,把偶数位置的结点用next 链接起来就是复制
    出来的链表。图4. 10 中的链表拆分之后的两个链表如图4.11 所示。
【剑指Offer学习】【面试题26:复杂链表的复制】_第4张图片
4.11.png

实现代码:

#import "QNComplexListNode.h"
#import 

// 复制 链表
void cloneComplexListNode (QNComplexListNode *headerListNode){
    if (headerListNode == nil) {
        return;
    }
    
    QNComplexListNode *currentNode = headerListNode;
    while (currentNode != nil) {
        QNComplexListNode *newNode = [[QNComplexListNode alloc] init];
        newNode.value = currentNode.value;
        newNode.next = currentNode.next;
        currentNode.next = newNode;
        currentNode = newNode.next;
    }
}

// 复制 额外 指针
void cloneComplexSiblingListNode (QNComplexListNode *headerListNode){
    if (headerListNode == nil) {
        return;
    }
    
    QNComplexListNode *currentNode = headerListNode;
    while (currentNode != nil) {
        if (currentNode.sibling != nil) {
            currentNode.next.sibling = currentNode.sibling.next;
        }
        currentNode = currentNode.next.next;
    }
}

// 将 原链表 和 复制链表 分开
QNComplexListNode * splitComplexListNode (QNComplexListNode *headerListNode) {
    if (headerListNode == nil) {
        return headerListNode;
    }
    
    // 用于 记录 当前 处理 原链表 的 节点
    QNComplexListNode *currentNode = headerListNode;
    // 用于 记录 复制 链表 的头结点
    QNComplexListNode *copyHeaderNode = currentNode.next;
    // 用来记录 当前 处理 的复制 节点
    QNComplexListNode *currentCopyedNode = copyHeaderNode;
    // 被 复制节点的next指向下一个被复制节点
    currentNode.next = copyHeaderNode.next;
    // 指向 新的 被 复制 的节点
    while (currentNode != nil) {
        // 指向 复制 节点
        currentCopyedNode.next = currentNode.next;
        // 当前 处理 复制 节点 指向 下一个 源链表 节点
        currentCopyedNode = currentCopyedNode.next;
        // 当前 处理 原链表 下一跳 指向 原链表 下一条 节点
        currentNode.next = currentCopyedNode.next;
        // 指向 下一个 原来 链表 上的节点
        currentNode = currentCopyedNode.next;
        
    }
    return copyHeaderNode;
}

// 打印 链表
void printList (QNComplexListNode *headerListNode) {
    while (headerListNode != NULL) {

        printf("%ld -->", (long)headerListNode.value);
        headerListNode = headerListNode.next;
    }
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        QNComplexListNode *head = [QNComplexListNode new];
        head.value = 1;
        head.next = [QNComplexListNode new];
        head.next.value = 2;
        head.next.next = [QNComplexListNode new];
        head.next.next.value = 3;
        head.next.next.next = [QNComplexListNode new];
        head.next.next.next.value = 4;
        head.next.next.next.next = [QNComplexListNode new];
        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;
        
        cloneComplexListNode(head);
        cloneComplexSiblingListNode(head);
        splitComplexListNode(head);
        printList(head);
        
    }
    return 0;
}

你可能感兴趣的:(【剑指Offer学习】【面试题26:复杂链表的复制】)