zoukankan      html  css  js  c++  java
  • 面试题26:复杂链表的赋值

    题目:请实现ComplexListNode*clone(ComplexListNode*pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中任意一个节点。结点定义如下:

    1 struct ComplexListNode
    2 {
    3     int m_val;
    4    ComplexListNode* m_pNext;
    5    ComplexListNode* m_pSibling;
    6 };

    下图为一个含有5个结点的复杂链表:

    解法一:时间复杂度为O(N2)的算法

    将整个复制过程分为两步:第一步复制原始链表上的每一个节点,并用m_pNext链接起来。第二步是设置m_pSibling指针。假设原始链表中的某个结点N的m_pSibling指向结点S,由于S的位置可能在N的前面也可能在N的后面,所以需要从原始链表的头结点开始查找。如果从原始链表的头结点开始沿着m_pNext经过s步到达S结点,那么在赋值链表中结点N'的m_pSibling离赋值链表的头结点的距离也是沿着m_pSibling指针S步。

    解法二:空间换时间的解法

    解法一的时间主要花费在定位结点的m_pSibling上,可以从这方面做优化。还是分为两步求解:

    第一步仍然是复制原始链表上的每一个节点,并用m_pNext链接起来。同时,我们把<N,N'>的配对信息放到一个哈希表中。第二步还是设置m_pSibling指针。如果在原始链表中结点N的m_pSibling指针指向结点S,那么对应的N’应该指向S'。由于有了hash表,我们可以在O(1)的时间内根据S找到S'。

    解法三:无需辅助空间,时间复杂度为O(N)的解法。

    第一步仍然根据原始链表中的每个结点N创建对应的节点N'。这一次,我们把N'链接在N的后面。

     1 void cloneNodes(CommplexNode* pHead)
     2 {
     3     ComplexListNode* pNode = pHead;
     4     while (pNode != NULL)
     5     {
     6         ComplexListNode* pCloned = new ComplexListNode();
     7         pCloned->m_val = pNode->m_val;
     8         pCloned->m_pNext = pNode->next;
     9         pCloned->m_pSibling = NULL;
    10         pNode->next = pCloned;
    11         pNode = pCloned->m_pNext;
    12     }
    13 }

    第二步设置复制出来的结点的m_pSibling指针。假设原始链表上N的m_pSibling指针指向S,那么其对应复制出来的N'是N的下一个结点,同样S'也是S的下一个结点。

     1 void connectSibingNodes(ComplexListNode* pHead)
     2 {
     3     ComplexListNode* pNode = pHead;
     4     while (pNode != NULL)
     5     {
     6         ComplexListNode* pCloned = pNode->m_pNext;
     7         if (pNode->m_pSibling != NULL)
     8             pCloned->m_pSibing = pNode->m_pSibling->m_pNext;
     9         pNode = pCloned->m_pNext;
    10     }
    11 }

    第三步把这个长链表拆分成两个链表:将奇数位置的结点链接起来就是原始链表,将偶数位置的结点链接起来就是复制的链表。

     1 ComplexListNode* reconnectNodes(ComplexListNode* pHead)
     2 {
     3     ComplexListNode* pNode = pHead;
     4     ComplexListNode* pCloneHead = NULL;
     5     ComplexListNode* pCloneNode = NULL;
     6     if (pNode!=NULL)
     7     {
     8         pCloneHead = pCloneNode = pNode->m_pNext;
     9         pNode->m_pNext = pCloneNode->m_pNext;
    10         pNode = pNode->m_pNext;
    11     }
    12     while (pNode != NULL)
    13     {
    14         pCloneNode->m_pNext = pNode->m_pNext;
    15         pCloneNode = pClonedNode->m_pNext;
    16         pNode->m_pNext = pClonedNode->m_pNext;
    17         pNode = pNode->m_pNext;
    18     }
    19     return pClonedHead;
    20 }

    最后将三步合起来:

    1 ComplexListNode* clone(ComplexListNode* pHead)
    2 {
    3     cloneNodes(pHead);
    4     connectSiblingNodes(pHead);
    5     return reconnectNodes(pHead);
    6 }
  • 相关阅读:
    记录百度编辑器bug(在编辑框输入光标到达页面最底部时,功能区块会悬浮在页面最顶部并且与编辑框分离)
    ThinkPHP5实用的数据库操作方法
    Windows10专业工作站版激活方法
    ThinkPHP5验证码不显示的原因及解决方法
    PHPExcel导出工作蒲(多表合并)教程+详细代码解读
    将input file的选择的文件清空的两种解决方案
    微信公众号网页开发——阻止微信客户端内点击任何图片自动放大
    开发中能快速定位错误也是技术的表现,附上【Chrome开发者工具官方中文文档】
    thinkPHP5 报错session_start(): No session id returned by function解决方法
    Linux安装PHPRedis扩展
  • 原文地址:https://www.cnblogs.com/happygirl-zjj/p/4631336.html
Copyright © 2011-2022 走看看