leetcode题解python版:96-100

96、不同的二叉搜索树

给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
解:按照第95题的思路就可以,只不过要把集合换成计数,为了加快速度要储存中间结果

class Solution:
    def numTrees(self, n: int) -> int:
        if n==0:
            return 0
        def countTree(k,ans):
            if k==1:
                ans.append(1)
                return 1
            if k==2:
                ans.append(2)
                return 2
            count=0
            for i in range(1,k+1):
                count=count+ans[i-1]*ans[k-i]
            ans.append(count)
            return ans[k]
        
        ans=[1]
        for i in range(1,n+1):
            a=countTree(i,ans)
        return a

执行用时:40 ms, 在所有 Python3 提交中击败了67.67%的用户
内存消耗:13.6 MB, 在所有 Python3 提交中击败了86.21%的用户

97、交错字符串

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。
解法一:最简单的办法就是递归,根据s1或者s2第一个元素与s3的关系进行分类讨论,只可惜最后超时了

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if sorted(s1+s2)!=sorted(s3):
            return False
        if not s1 and s2==s3:
            return True
        elif not s1 and s2!=s3:
            return False
        elif not s2 and s1==s3:
            return True
        elif not s2 and s1!=s3:
            return False
        elif s1[0]!=s3[0] and s2[0]!=s3[0]:
            return False
        elif s1[0]==s3[0] and s2[0]==s3[0]:
            if (self.isInterleave(s1[1:],s2,s3[1:])) or (self.isInterleave(s1,s2[1:],s3[1:])):
                return True
            else:
                return False
        elif s1[0]==s3[0]:
            if (self.isInterleave(s1[1:],s2,s3[1:])):
                return True
            else:
                return False
        else:
            if (self.isInterleave(s1,s2[1:],s3[1:])):
                return True
            else:
                return False

解法二:使用回溯不成功,但是我们又没有其它的办法(dfs的效果可能更差),所以我们可以考虑二维的动态规划dp[i][j]代表s1[:i],s2[:j]与s3[:i+j]
如果s1[i-1]与s[j-1]均与s3[i+j-1]不相等那dp[i][j]=False
如果s1满足,那就看dp[i-1][j],s2满足就看dp[i][j-1]
初始条件是dp[0][j]与dp[i][0]

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        m=len(s1)
        n=len(s2)
        l=len(s3)
        if m+n!=l:
            return False
        dp=[[False for _ in range(n+1)] for _ in range(m+1)]
        dp[0][0]=True
        for i in range(1,m+1):
            if s1[i-1]==s3[i-1]:
                dp[i][0]=dp[i-1][0]
            else:
                break
        for j in range(1,n+1):
            if s2[j-1]==s3[j-1]:
                dp[0][j]=dp[0][j-1]
            else:
                break
        for i in range(1,m+1):
            for j in range(1,n+1):
                dp[i][j]=(dp[i][j-1] and s2[j-1]==s3[i+j-1]) or (dp[i-1][j] and s1[i-1]==s3[i+j-1])
        return dp[m][n]

执行用时:40 ms, 在所有 Python3 提交中击败了95.01%的用户
内存消耗:13.7 MB, 在所有 Python3 提交中击败了78.06%的用户

98、验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

解:用递归就可以,关键是怎么判定一个子树节点的上下界。每访问一次左子树,上界变为当前根节点,每访问一次右子树,下界变为当前根节点。

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

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        def isValid(root,down,up):
            if not root:
                return True
            if not down<root.val<up:
                return False
            return isValid(root.left,down,root.val) and isValid(root.right,root.val,up)
        
        return isValid(root,float("-inf"), float("inf"))

执行用时:56 ms, 在所有 Python3 提交中击败了74.08%的用户
内存消耗:15.9 MB, 在所有 Python3 提交中击败了72.88%的用户

99、恢复二叉搜索树

二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
解:先遍历一遍,得到所有元素并排序。
有了左子节点的个数和右子节点的个数就可以知道根节点该放谁了,然后把原集合按根节点分为两个集合,一个要填入左子树,一个要填入右子树

# 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 recoverTree(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        def travelTree(root,treeList1):
            if not root:
                return 
            travelTree(root.left,treeList1)
            treeList1.append(root.val)
            travelTree(root.right,treeList1)

        def countTree(root):
            treeList=[]
            travelTree(root,treeList)
            return len(treeList)

        def putroot(tree,treeList1):
            if not tree:
                return
            a=countTree(tree.left)
            tree.val=treeList1[a]
            putroot(tree.left,treeList1[:a])
            putroot(tree.right,treeList1[a+1:])
            return
        
        treeList=[]
        travelTree(root,treeList)
        treeList.sort()
        putroot(root,treeList)
        return

执行用时:96 ms, 在所有 Python3 提交中击败了47.94%的用户
内存消耗:14 MB, 在所有 Python3 提交中击败了77.74%的用户

100、相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
解:本质上就是遍历树

# 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 isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and q:
            return False
        if not q and p:
            return False
        if not q and not p:
            return True
        return (self.isSameTree(p.left,q.left) and (p.val==q.val) and self.isSameTree(p.right,q.right))

执行用时:36 ms, 在所有 Python3 提交中击败了90.39%的用户
内存消耗:13.7 MB, 在所有 Python3 提交中击败了63.21%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值