剑指OFFER DAY2

第 2天

链表(简单)

剑指 Offer 06. 从尾到头打印链表

没什么可说的,直接上代码

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        num_list = []
        while head:
            num_list.append(head.val)
            head = head.next
        num_list.reverse()
        return num_list

剑指 Offer 24. 反转链表

先上代码

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        num_list = []
        while head != None:
            num_list.append(head.val)
            head = head.next
        num_list.reverse()
        tem_head = ListNode()
        tem = tem_head
        for i in range(len(num_list)):
            tem.next = ListNode(num_list[i])
            tem = tem.next

        return tem_head.next

刷题心得:

此题在第一问的基础上做了延伸,我的思路,先利用第一问的List,在构造一个心得Linklist,将List中的元素倒叙一个一个加入Linklist。

当然又一点问题就是新链表的头元素,如果我们直接将List最后一个元素付给链表头,当输入List = [] 时,返回值为Null 实际应为[],系统报错。

这里我们使用伪头节点,最后return tem_head.next返回真正链表即可。

这里List也可用Stack替代,就不需要反转列表了。

当然也有不用中间List的思路,不过上面是最容易想到的。

下面是不用List的双指针方法:

  1. 设置两个指针,cur 指向链表头节点,pre 指向空
  2. 暂存 cur 的后继节点,tmp = cur.next
  3. 将 cur.next 反指向pre
  4. 将 pre 指向 cur,即 pre 指针后移
  5. 将 cur 指向 2 中暂存的 tmp 节点,即 cur 指针后移 循环 第2 到 5 步,直到 cur 遍历完整个链表
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        cur = head
        pre = None
        while cur:
            tem = cur.next
            cur.next = pre
            pre = cur
            cur = tem
        return pre

剑指 Offer 35. 复杂链表的复制

说实话第三题有点离谱,可能是我基本功不够的原因,明知道是DeepCopy依然return head,哈哈哈哈,然后我的思路很奇怪,先把每个节点复制一遍,用next先把链表连起来,剩下的就是把random补全。

我的想法是根据节点的val,把符合某一个节点.random.value的节点加到list,然后找出哪一个是他真正的random节点再加入true_ran_list,这个list保存着全部复制节点的index,然后根据index挨个把random补全。

以下是我的最原始代码

但是该方法时间复杂度O(n**2),且用到了很多循环,很浪费时间,但是对我这种菜鸡来说能两遍做出来就很满足了,另外还有老哥非常的幽默哈哈哈哈。

 

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        node_list = []
        val_list = []
        ran_val_list = []
        while head:
            node_list.append(head)
            val_list.append(head.val)
            if head.random:
                ran_val_list.append(head.random.val)
            else:
                ran_val_list.append(None)
            head = head.next
        #print(val_list)

        #new linklist node
        new_node_list = []
        for i in val_list:
            new_node_list.append(Node(i))
        

        #find random index
        ran_index_list = []
        for i in ran_val_list:
            tem = []
            for j in range(len(val_list)):
                if i == val_list[j]:
                    tem.append(j)
                elif i == None:
                    tem.append(None)
                    break
            ran_index_list.append(tem)
        #print("+++",ran_index_list)
        
        true_ran_list = []
        for i in range(len(ran_index_list)):
            if len(ran_index_list[i])>=2:
                for j in ran_index_list[i]:
                    if node_list[i].random == node_list[j]:
                        true_ran_list.append(j)
            else:
                true_ran_list.append(ran_index_list[i][0])
        #print("true:",true_ran_list)


        #add next and random
        new_head = Node(0)
        cur = new_head
        for i in range(len(node_list)):
            
            #next
            cur.next = new_node_list[i]
            #random
            if true_ran_list[i] != None:
                cur.next.random = new_node_list[true_ran_list[i]]
            else:
                cur.next.random = None
            cur = cur.next
        cur.next = None
        return new_head.next


哈希表法

这个方法很精妙,先用字典存储原node(key)和新node(value),接下来使用map将dic key中的next,random一一对应到dic value中

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if head == None:
            return None
        nodeDict = {}
        node = head
        while node:
            nodeDict[node] = Node(node.val)
            node = node.next

        l = head
        while l:
            nodeDict[l].next = nodeDict.get(l.next)
            nodeDict[l].random = nodeDict.get(l.random)
            l = l.next
        return nodeDict[head]

这里涉及了一个知识点:

get() 方法 Vs dict[key] 访问元素区别

get(key) 方法在 key(键)不在字典中时,可以返回默认值 None 或者设置的默认值。

dict[key] 在 key(键)不在字典中时,会触发 KeyError 异常。

所以尽量使用get()方法,避免报错


原地算法

思路:

1:复制每一个结点,并且使复制的结点在原结点的后面,实现从1->2->3->null, 变成1->1->2->2->3->3->null
2:复制random指针,注意判断random是否为null
3:将复制完成的结点一分为二,注意还要将原来的链表还原回去

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if head == None:
            return None

        node = head
        while node != None:  # 首先复制一遍链表
            new = Node(node.val)
            temp = node.next
            node.next = new
            new.next = temp
            node = node.next.next

        node = head  # 然后给复制的节点加上random引用
        while node != None:
            node2 = node.next
            if node.random != None:
                node2.random = node.random.next
            node = node.next.next

        # 最后拆开复制的链表
        node, node2 = head, head.next
        ans = node2
        while node.next != None and node2.next != None:
            node.next = node.next.next
            node2.next = node2.next.next
            node = node.next
            node2 = node2.next

        return ans

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Weber77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值