leetcode题解python版:91-95

91、解码方法

一条包含字母 A-Z 的消息通过以下方式进行了编码:

'A' -> 1
'B' -> 2
...
'Z' -> 26

给定一个只包含数字的非空字符串,请计算解码方法的总数
解:这道题用递归显然是没有问题的。这里要注意的是0,单独一个0显然无法解码,0只能变为10,20来解码,否则s是无法解码的。

class Solution:
    def numDecodings(self, s: str) -> int:
        n=len(s)
        if n==1:
            if s[0]=='0':
                return 0
            else:
                return 1
        if n==2:
            if s[0]=='0':
                return 0
            elif s[1]=='0' and int(s)<=26:
                return 1
            elif s[1]=='0' and int(s)>26:
                return 0
            elif int(s)<=26:
                return 2
            else:
                return 1
        if s[-1]=='0':
            if int(s[-2])>2 or s[-2]=='0':
                return 0
            else:
                return self.numDecodings(s[:n-2])
        elif s[-2]=='0':
            return self.numDecodings(s[:n-1])
        elif int(s[-2:])<=26:
            return self.numDecodings(s[:n-2])+self.numDecodings(s[:n-1])
        else:
            return self.numDecodings(s[:n-1])

然而很遗憾,最后会超时,但可以改成记忆化的递归

class Solution:
    def numDecodings(self, s: str) -> int:
        n=len(s)
        ans=[0]
        def memory(s,ans,i):
            if i==1:
                if s[0]=='0':
                    return 0
                else:
                    return 1
            if i==2:
                if s[0]=='0':
                    return 0
                elif s[1]=='0' and int(s)<=26:
                    return 1
                elif s[1]=='0' and int(s)>26:
                    return 0
                elif int(s)<=26:
                    return 2
                else:
                    return 1
            if s[-1]=='0':
                if int(s[-2])>2 or s[-2]=='0':
                    return 0
                else:
                    return ans[i-2]
            elif s[-2]=='0':
                return ans[i-1]
            elif int(s[-2:])<=26:
                return ans[i-2]+ans[i-1]
            else:
                return ans[i-1]
        
        for i in range(1,n+1):
            a=memory(s[:i],ans,i)
            ans.append(a)
        return ans[n]

这样就满足时间限制了
执行用时:36 ms, 在所有 Python3 提交中击败了94.01%的用户
内存消耗:13.5 MB, 在所有 Python3 提交中击败了92.10%的用户

92、反转链表 II

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
解:用一趟完成说明要用很多变量
先移动m次,同时记录m-1和m,在移动n-m+1次,这时要再引入两个新变量,一个记录下一步,一个用来反转即next=res.next,res.next=trans,trans=res,res=next,这样就完成了一次旋转,走完n-m+1步后res在n+1,trans在n,让m-1连n,m连n+1就可以了

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        count=0
        ans=ListNode(None)
        ans.next=head
        res=ans
        for _ in range(m):
            pre=res#pre记录m-1
            res=res.next#res记录m
        M=res#记录m
        resNext=None
        back=None#用于反转的
        for _ in range(n-m+1):
            resNext=res.next
            res.next=back
            back=res
            res=resNext
        pre.next=back#m-1的下一个是n
        M.next=res#m的下一个是n+1
        return ans.next

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

93、复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。
解:这种题还是用dfs最靠谱,而且由于数字小,所以不会花费太长的时间。

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        def dfs(s,path,depth,n,ans):
            if len(path)>4 or (len(path)==4 and depth<n-1):#没找对
                return
            if depth >=n:
                if len(path)==4:
                    ans.append(".".join(path))
                return
            if s[depth]=='0':
                dfs(s,path+[s[depth]],depth+1,n,ans)
                return
            for i in range(depth,n):
                if 0<int(s[depth:i+1])<=255:
                    dfs(s,path+[s[depth:i+1]],i+1,n,ans)
                else:
                    break
            return
        
        n=len(s)
        ans=[]
        dfs(s,[],0,n,ans)
        return ans

执行用时:32 ms, 在所有 Python3 提交中击败了99.14%的用户
内存消耗:13.7 MB, 在所有 Python3 提交中击败了48.44%的用户
速度快得令人难以置信,说明这道题只能遍历

94、二叉树的中序遍历

给定一个二叉树,返回它的中序 遍历。
解:递归先遍历左子树,再加入根,再遍历右子树。

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

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)

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

95、不同的二叉搜索树 II

给定一个整数 n,生成所有由 1 … n 为节点所组成的 二叉搜索树 。
解法一:比父节点小的key都出现在左子树,比父节点大的都出现在右子树。
这种题用递归和dfs都是可以的,但是递归的思路更简单,因为当确定了根节点后问题自然被分成了更小的两部分。解法一就先用递归。
对于k作为根顶点的情况1,…,k-1在左子树,递归[1,…,k-1]的情况,k+1,…n在右子树,递归[k+1,…n]的情况。当n=0或1时是特殊情况或者说递归的初始条件。

# 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 generateTrees(self, n: int) -> List[TreeNode]:
        if n==0:
            return []
        def generation(nums):
            k=len(nums)
            if k==0:
                return [None]#返回null
            if k==1: 
                return [TreeNode(nums[0])]
            ans = []
            for i in range(k):
                for left in generation(nums[:i]):
                    for right in generation(nums[i + 1:]):
                        ans.append(TreeNode(nums[i], left=left, right=right))
            return ans
        return generation(list(range(1, n+1)))

执行用时:68 ms, 在所有 Python3 提交中击败了83.93%的用户
内存消耗:15.7 MB在所有 Python3 提交中击败了5.21%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值