记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
9/27 639. 解码方法 II
动态规划
dp[i] 代表s前i个字符的解码数
使用1个字符:
s[i]为* 可以为1-9 dp[i] = 9dp[i-1]
s[i]为0 无法解码 dp[i] = 0
否则s[i]=[1,9] dp[i] = dp[i-1]
使用2个字符:
s[i],s[i-1]都为 可以为[11-19,21-26]十五种情况 dp[i] = 15dp[i-2]
只有s[i]为 s[i]=1 dp[i]=9dp[i-2] s[i]=2 dp[i]=6dp[i-2] 否则 dp[i]=0
只有s[i-1]为* s[i-1]=[1,6] dp[i]=2dp[i-2] s[i-1]=[7,9] dp[i]=dp[i-2]
若都不为 只有s[i-1]!=0且s[i-1]s[i]<=“26” dp[i]=dp[i-2] 否则dp[i]=0
只有dp[i],dp[i-1],dp[i-2]相关 可以只用三个遍历
dp0,dp1,dp2
dp0 = xdp1+ydp2
def numDecodings(s):
"""
:type s: str
:rtype: int
"""
mod = 10**9+7
def one(c):
if c=="0":
return 0
elif c=="*":
return 9
else:
return 1
def two(c0,c1):
if c0==c1=="*":
return 15
if c0=="*":
if c1<="6":
return 2
else:
return 1
if c1=="*":
if c0=="1":
return 9
elif c0=="2":
return 6
else:
return 0
if c0>"0" and int(c0+c1)<=26:
return 1
else:
return 0
n = len(s)
dp0,dp1,dp2 = 0,1,0
for i in range(n):
dp0 = dp1*one(s[i])
if i>0:
dp0 += dp2*two(s[i-1],s[i])
dp0 %=mod
dp2 = dp1
dp1 = dp0
print(s[i],dp0,dp1,dp2)
return dp0
9/28 437. 路径总和 III
start用来寻找从root点作为起点的情况
同时考虑从左右子节点作为起点的情况
注意 当sum==val时不能停止 需要继续往下找 存在和为0的情况
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def pathSum(root, targetSum):
"""
:type root: TreeNode
:type sum: int
:rtype: int
"""
def start(root,sum):
ret = 0
if not root:
return ret
if root.val == sum:
ret+=1
if root.left:
ret += start(root.left,sum-root.val)
if root.right:
ret += start(root.right,sum-root.val)
return ret
if not root:
return 0
res = start(root,targetSum)
res += pathSum(root.left,targetSum)
res += pathSum(root.right,targetSum)
return res
9/29 517. 超级洗衣机
计算总件数 如果无法均分 返回失败-1
得到每台洗衣机最终需要的件数ave
如果一台洗衣机件数小于ave 那么它左右都可以给他衣服
但如果一台洗衣机件数v大于ave 那么它至少需要v-ave次才能把衣服给出去
使用前缀和presum记录前i台目前有的总件数
对于第i台洗衣机 前i台最终需要的件数为iave
那么缺少或者多余的件数为 abs(presum-iave)
这些件数需要从左往右 或者从右往左经过i
取每个位置最大操作次数
def findMinMoves(machines):
"""
:type machines: List[int]
:rtype: int
"""
total = sum(machines)
n = len(machines)
if total%n>0:
return -1
ave = total//n
presum = 0
ans = 0
for i,v in enumerate(machines):
diff = v-ave
presum +=v
ans = max(ans,max(diff,abs(presum-(i+1)*ave)))
return ans
9/30 223. 矩形面积
分别计算两个矩形面积s1,s2 需要求重叠矩形面积over
1.将左下角点靠左边的设为a
分别考虑a左下点在b左下点的下面;上面两种情况
以上两种情况中 出去不想交的情况 在分别考虑四种情况
2.将a,b两个矩形的长投影到x轴 宽投影到y轴 分别有两条线段
两条线段相交的的即为相交矩阵的长或宽
def computeArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2):
"""
:type ax1: int
:type ay1: int
:type ax2: int
:type ay2: int
:type bx1: int
:type by1: int
:type bx2: int
:type by2: int
:rtype: int
"""
s1 = (ax2-ax1)*(ay2-ay1)
s2 = (bx2-bx1)*(by2-by1)
if ax1>bx1:
ax1, ay1, ax2, ay2, bx1, by1, bx2, by2 = bx1, by1, bx2, by2,ax1, ay1, ax2, ay2
over = 0
if ay1>=by1:
if ay1>=by2:
over = 0
elif ax2<=bx1:
over = 0
elif ax2<=bx2 and ay2<=by2:
over = (ax2-bx1)*(ay2-ay1)
elif ax2<=bx2 and ay2>by2:
over = (ax2-bx1)*(by2-ay1)
elif ax2>bx2 and ay2<=by2:
over = (bx2-bx1)*(ay2-ay1)
elif ax2>bx2 and ay2>by2:
over = (bx2-bx1)*(by2-ay1)
else:
if ay2<=by1:
over = 0
elif ax2<=bx1:
over = 0
elif ax2<=bx2 and ay2<=by2:
over = (ax2-bx1)*(ay2-by1)
elif ax2<=bx2 and ay2>by2:
over = (ax2-bx1)*(by2-by1)
elif ax2>bx2 and ay2<=by2:
over = (bx2-bx1)*(ay2-by1)
elif ax2>bx2 and ay2>by2:
over = (bx2-bx1)*(by2-by1)
return s1+s2-over
def computeArea2(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2):
"""
:type ax1: int
:type ay1: int
:type ax2: int
:type ay2: int
:type bx1: int
:type by1: int
:type bx2: int
:type by2: int
:rtype: int
"""
s1 = (ax2-ax1)*(ay2-ay1)
s2 = (bx2-bx1)*(by2-by1)
overw = min(ax2,bx2)-max(ax1,bx1)
overh = min(ay2,by2)-max(ay1,by1)
overs = max(overw,0)*max(overh,0)
return s1+s2-overs
10/1 1436. 旅行终点站
target存储所有出现的终点站
source存储所有出现的起点
从target中找到一个未出现在source中的点即为最终终点站
def destCity(paths):
"""
:type paths: List[List[str]]
:rtype: str
"""
target = set()
source = set()
for s,t in paths:
source.add(s)
target.add(t)
for loc in target:
if loc not in source:
return loc
10/2 405. 数字转换为十六进制数
s为16进制用到的字符
32位转化为16进制 最多8位 循环最多8次
num对16取余 -1%16=15
余数即为当前位结果
最后将结果倒序输出
def toHex(num):
"""
:type num: int
:rtype: str
"""
s = "0123456789abcdef"
ans = []
for _ in range(8):
ans.append(num%16)
num = num//16
if not num:
break
return "".join(s[i] for i in ans[::-1])
10/3 166. 分数到小数
x/y
如果可以整除 则直接返回结果
s用来记录结果
如果x,y正负不同 则结果为负数 添加"-"
整数部分 x//y 并且添加"."
余数部分 yu=x%y
index用来记录出现过的余数 如果该余数已经出现过 说明后续结果会重复
记录当前yu数位置
每次yu乘以10 用来除以y 为当前位结果
得到新余数 yu=yu%y
退出循环 如果yu不为0 说明存在循环
找到位置ind=index[yu]
添加"(" 并在结尾添加")"
将结果组合成字符串输出
def fractionToDecimal(numerator, denominator):
"""
:type numerator: int
:type denominator: int
:rtype: str
"""
if numerator%denominator==0:
return str(numerator//denominator)
s = []
if (numerator>0)!=(denominator>0):
s.append("-")
x = abs(numerator)
y = abs(denominator)
z = x//y
s.append(str(z))
s.append(".")
yu = x%y
index = {}
while yu and yu not in index:
index[yu] = len(s)
yu *=10
s.append(str(yu//y))
yu = yu%y
if yu:
ind = index[yu]
s.insert(ind,"(")
s.append(")")
return "".join(s)