剑指offer 34-37题 python题解记录

本文解析了二叉树中和为某一值的路径、复杂链表复制及二叉搜索树转换为双向链表等问题,并给出了序列化与反序列化二叉树的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题34:二叉树中和为某一值的路径

深度优先能想到,但还是有几个点是自己没想清楚的:

  • 关于target匹配,我想的是从0开始,加上当前节点的值,去判断是否和target相等,但大佬的做法是从target开始,减去当前节点的值,判断是否为0;这一做法的好处是,避免了回朔过程中的当前值难以记录的问题,妙啊
  • 关于将list的append问题,由于path指向列表,因此直接用res.append(path)是将path指向的空间加到了res里,后续path改变时,res也会变(深浅拷贝问题),解决方法是,采用res.append(list(path),这样相当于创建了一个新的列表,将其加到了res里,妙啊
  • 关于path在哪里pop问题,嗯……很妙!
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def pathSum(self, root: TreeNode, target: int) -> List[List[int]]:
        res = []
        def dfs(root:TreeNode,cum:int,path:List[int]):
            if root!=None:
                path.append(root.val)
                cum-=root.val
                if cum == 0 and root.left==None and root.right==None:
                    res.append(list(path))
                else:
                    dfs(root.left,cum,path)
                    dfs(root.right,cum,path)
                path.pop()
        dfs(root,target,[])
        return res

题35:复杂链表的复制

自己想的:一共两次遍历,

  • 第一次遍历用于创造出新的链表,构建next关系,同时,将新旧链表的每个节点都放到各自的list中(目的是使其可通过下标寻找)
  • 第二次遍历则利用list.index函数找到下标,将其对应

可能并不是最优解,但还是自己想出来的,鼓励一下👏

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if head==None:
            return None
        newhead=Node(head.val)
        old,new=head,newhead
        oldlist,newlist=[],[]
        while old!=None:
            oldlist.append(old)
            newlist.append(new)
            if old.next!=None:
                tmp=Node(old.next.val)
                new.next=tmp
            else:
                new.next=None
            old,new=old.next,new.next
        old,new=head,newhead
        while old!=None:
            if old.random!=None:
                ind=oldlist.index(old.random)
                new.random=newlist[ind]
            else:
                new.random=None
            old,new=old.next,new.next
        return newhead

题36:二叉搜索树与双向链表

法一:比较暴力,中序遍历一遍把节点存在list中,然后遍历一遍list,构造引用关系

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        if root==None:
            return None
        nodelist = []
        def inorder(root:'Node'):
            if root!=None:
                inorder(root.left)
                nodelist.append(root)
                inorder(root.right)
        inorder(root)
        for i in range(len(nodelist)):
            if i!=len(nodelist)-1 and i!=0:
                nodelist[i].left=nodelist[i-1]
                nodelist[i].right=nodelist[i+1]
            elif i==len(nodelist)-1:
                nodelist[i].left=nodelist[i-1]
                nodelist[i].right=nodelist[0]
            else:
                nodelist[i].left=nodelist[-1]
                nodelist[i].right=nodelist[i+1]
        return nodelist[0]

法二:画一画图可以发现,只需要调整节点的指向即可->cur.left,pre.right=pre,cur
几个细节:
1、head节点的记录
2、当dfs运行完后,此时的pre就是最后一个节点!!

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        if not root:return
        pre,head=None,None
        def dfs(cur:"Node"):
            nonlocal pre,head
            if not cur: return
            dfs(cur.left)
            if pre:
                pre.right,cur.left=cur,pre
            else:
                head=cur
            pre=cur
            dfs(cur.right)
        dfs(root)
        head.left,pre.right=pre,head
        return head

题37:序列化二叉树

序列化还好做,利用队列即可,但是反序列化是第一次,本想用二叉树的性质(第i个节点的左节点处于2i处,右节点处于2i+1处,但这样遇到null时很难处理,参考了大佬的题解,发现反序列化也可以用队列,代码如下:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.
        
        :type root: TreeNode
        :rtype: str
        """
        if root==None:
            return '[]'
        queue,res=[root],'['
        while len(queue)!=0:
            tmp=queue.pop(0)
            if tmp!=None:
                res+=str(tmp.val)+','
                queue.append(tmp.left)
                queue.append(tmp.right)
            else:
                res+=('null,') 
        res=res[:-1]+']'
        return res


    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        if data=='[]':
            return None
        data=data[1:-1].split(',')
        rt=TreeNode(int(data[0]))
        queue,ind=[rt],1
        while len(queue)!=0:
            root=queue.pop(0)
            if data[ind]!='null':
                root.left=TreeNode(int(data[ind]))
                queue.append(root.left)
            ind+=1
            if data[ind]!='null':
                root.right=TreeNode(int(data[ind]))
                queue.append(root.right)
            ind+=1
        return rt

        
        

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值