版权声明:Tian Run https://blog.csdn.net/u013908099/article/details/86491966
题目
请实现啊函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个
复杂链表。在复杂链表中除了有一个m_pNext指针指向下一个节点,还有一个m_pSaibling
指针指向链表中的任意节点或者nullptr。
节点定义如下:
class ComplexListNode(object):
def __init__(self, x):
self.val = x
self.next = None
self.sibling = None
思路
- 第一步,复制主链,解决所有节点的next配置。
第二步,解决silbing配置,遍历旧链表,如果有sibling,则旧链表头遍历寻找该节点,记录离链表头的距离后在新链表里同样设置。- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
- 第一步,复制主链,解决next,同时设置hash表,将旧节点和新节点建立映射。
第二步,解决sibling,node遍历旧链表,当有node.sibling时,新链表new_node.sibling设置为hash表中node.sibling映射的结果。- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 第一步,将主链每个节点都复制一个拷贝连接入原节点的后面。A-B -> A-A’-B-B’
第二步,将按原节点设置复制节点的sibling,有node’.sibling = node.sibling.next
第三步,将链表分解成新旧两条,奇数链和偶数链。- 时间复杂度:O(n)
- 2空间复杂度:O(1)
代码
思路2:时间复杂度:O(n),空间复杂度:O(n)
def complex_list_node_clone(head):
"""
:param head: origin head
:return:copy head
"""
sham_head = ComplexListNode(0)
new_node = sham_head
node = head
reflect = {}
while node:
new_node.next = ComplexListNode(node.val)
new_node = new_node.next
reflect[node] = new_node
node = node.next
node = head
new_node = sham_head.next
while node:
if node.sibling:
new_node.sibling = reflect[node.sibling]
node = node.next
new_node = new_node.next
return sham_head.next
思路3:时间复杂度:O(n),空间复杂度:O(11)
def complex_list_node_clone_2(head):
"""
:param head: origin head
:return:copy head
"""
node = head
while node:
new_node = ComplexListNode(node.val)
node.next, node = new_node, node.next
new_node.next = node
node = head
while node:
if node.sibling:
node.next.sibling = node.sibling.next
node = node.next.next
node = head
copy_head = head.next
while node.next:
node.next, node = node.next.next, node.next
return copy_head
思考
- 思路3其实和思路2异曲同工,就是建立新旧节点的映射关系,以便处理sibling属性,而不用再次从头查找。思路2采用额外哈希表使查询时间为O(1),思路3则将新节点特别的安排为旧节点的Next,这样映射关系即为new_node = node.next 也是O(1)。
同样的题目
LeetCode 138. 复制带随机指针的链表
代码
# Definition for singly-linked list with a random pointer.
# class RandomListNode(object):
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution(object):
def copyRandomList(self, head, hash_table={}):
"""
:type head: RandomListNode
:rtype: RandomListNode
"""
if not head:
return None
if head in hash_table:
return hash_table[head]
hash_table[head] = RandomListNode(head.label)
hash_table[head].random = self.copyRandomList(head.random, hash_table)
hash_table[head].next = self.copyRandomList(head.next, hash_table)
return hash_table[head]
分析
- 上面的代码是别人的解法。很有意思因此分享
- 他的思路很特别,不是分步解决next 和 sibling属性,而是在一次遍历中解决。
具体操作如下:- 遍历链表,对于一个节点一次性设置完next和sibiling属性,将设置好的节点存入字典
- 对于next和sibling这两条支链,都递归设置,直到遇到设置好的节点或者链表到头。
- 在字典中出现的节点,意味着此节点以后的所有节点都已经被设置完毕。
- 这份代码采用了递归,十分简洁。基本思路也比较清晰,就是只要next和sibling还未配置就一路配置到配置完成为止。哈希表记录是否配置过用来防止死循环。