提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
冲!
一、题目
解码方法
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
‘A’ -> “1”
‘B’ -> “2”
…
‘Z’ -> “26”
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:
“AAJF” ,将消息分组为 (1 1 10 6)
“KJF” ,将消息分组为 (11 10 6)
注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 32 位 的整数。
示例
示例 1:
输入:s = “12”
输出:2
解释:它可以解码为 “AB”(1 2)或者 “L”(12)。
示例 2:
输入:s = “226”
输出:3
解释:它可以解码为 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。
示例 3:
输入:s = “0”
输出:0
解释:没有字符映射到以 0 开头的数字。
含有 0 的有效映射是 ‘J’ -> “10” 和 ‘T’-> “20” 。
由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。
提示
1 <= s.length <= 100
s 只包含数字,并且可能包含前导零。
二、思路
这道题一看就被唬住了,完全没有一点思路,感觉数字串太长了,不知道怎么挨个组合才能不遗漏。事实上所有涉及大问题的题都可以转化为小问题来求解,即动态规划(也可以叫做“递推”)。
对于一个字符串来说,遍历每一个字母都会产生两种情况,①将这个字母i单独翻译,fi=f(i-1)(需要该字母!=0)②将这个字母和他前面的字母一起翻译(需要两个数的值属于【1,26】)将这两种情况的和加起来就是当前字母的情况了~
根据这个思路,我们再来规划一下初始值,对于第一个字母,需要求f0的值,其值需要依靠f(-1)和f(-2),第二种显然不可能,因此直接根据s(1)是否为0可以判断出f(0)的值,f(-1)直接赋值1(根据f(2)的计算)
有了初始值和状态转移方程,剩下的就很好办了,为了优化存储空间,每次保留相邻三个数据即可~
三、代码
class Solution:
def numDecodings(self, s: str) -> int:
f=[0,0] #记录当前需要计算的数的前面两个数据(f(i-2)、(f(i-1))
f[0]=1 #f(-1)
if(s[0] == '0'): #f(0)
f[1]=0
else:
f[1]=1
for i in range(1,len(s)):
if(s[i] !='0'): #①
temp1=f[1]
else:
temp1=0
temp=int(s[i-1:i+1])
if(s[i-1]!='0' and temp>=1 and temp<=26 ): #②
temp2=f[0]
else:
temp2=0
f[0]=f[1]
f[1]=temp1+temp2
return f[1]
四、题目
反转链表 II
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表 。
示例
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
提示:
链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
进阶:
你可以使用一趟扫描完成反转吗?
五、思路
首先把指针移动到left前的位置,找到不用翻转的最后的尾巴,为了防止第一个元素就是left,需要补一个虚表头
然后反转链表至少需要三个指针,部署三个指针,使中间那个指针指向left元素,然后不断反转后移直到right,
都反转完之后把断点处处理一下就可以了!
六、代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
Head=ListNode(0,head)
left=left-1
right=right-1
i=-1 #计数
keyrear=Head #不用翻转的最后的尾巴
while(i<left-1): #把指针移动到left前的位置
keyrear=keyrear.next
i+=1
keystart=keyrear.next
p1=keyrear.next #指针1,初始指向left
if(p1 != None):
p2=p1.next #指针2
else:
p2=None
if(p2 != None):
p3=p2.next
i+=2
#开始翻转
while(i<=right): #开始翻转
p2.next=p1
p1=p2
p2=p3
if(p3 != None):
p3=p3.next
i+=1
#连接
keyrear.next=p1
if(keystart != None):
keystart.next=p2
return Head.next