记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
1/20 2239. 找到最接近 0 的数字
遍历记录最小差值
def findClosestNumber(nums):
"""
:type nums: List[int]
:rtype: int
"""
ans = float("inf")
for num in nums:
if abs(num)<abs(ans) or (abs(num)==abs(ans) and num>ans):
ans = num
return ans
1/21 2218. 从栈中取出 K 个硬币的最大面值和
dp[i]表示i次操作可以得到的最大值
对于每个栈最多取k个数
def maxValueOfCoins(piles, k):
"""
:type piles: List[List[int]]
:type k: int
:rtype: int
"""
dp=[0]+[-1]*k
for p in piles:
for i in range(k,0,-1):
v = 0
for t in range(1,len(p)+1):
v+=p[t-1]
if i>=t and dp[i-t]!=-1:
dp[i]=max(dp[i],dp[i-t]+v)
return dp[k]
1/22 1561. 你可以获得的最大硬币数目
每次选最大的两堆和最小的一堆 让自己可以拿到更多硬币
每个人取k个 从大到小排序 隔一个取一个取k个
def maxCoins(piles):
"""
:type piles: List[int]
:rtype: int
"""
k = len(piles)//3
piles.sort(reversed=True)
return sum(piles[1:2*k:2])
1/23 2920. 收集所有金币可获得的最大积分
dfs 记录做了多少次减半操作
node为当前节点 p为父节点
f为之前已经做过减半操作的次数
ans0 ans1分别代表进行操作一、二的结果
def maximumPoints(edges, coins, k):
"""
:type edges: List[List[int]]
:type coins: List[int]
:type k: int
:rtype: int
"""
n= len(coins)
c = [[] for _ in range(n)]
for x,y in edges:
c[x].append(y)
c[y].append(x)
mem={}
def dfs(node,p,f):
if (node,p,f) in mem:
return mem[(node,p,f)]
ans0 = (coins[node]>>f)-k
ans1 = coins[node]>>(f+1) if f+1<14 else 0
for child in c[node]:
if child==p:
continue
ans0 += dfs(child,node,f)
if f+1<14:
ans1+=dfs(child,node,f+1)
ans=max(ans0,ans1)
mem[(node,p,f)]=ans
return ans
return dfs(0,-1,0)
1/24 2944. 购买水果需要的最少金币数
单调队列
f[i]表示购买i的情况下 获取后面所有水果最少金币数
def minimumCoins(prices):
"""
:type prices: List[int]
:rtype: int
"""
n=len(prices)
l = [(n+1,0)]
for i in range(n,0,-1):
while l[-1][0]>i*2+1:
l=l[:-1]
f = prices[i-1]+l[-1][1]
while f<=l[0][1]:
l=l[1:]
l = [(i,f)]+l
return l[0][1]
1/25 2412. 完成所有交易的初始最少钱数
每次交易有两种情况 亏 或者 不亏
任意交易顺序都要能完成 最坏的情况就是最先遇到的都是亏的
total记录所有亏钱总和
对于赚钱的情况cost<=cashback 假设是第一笔赚钱 那么经过了所有亏钱交易 需要total+cost 初始钱数
对于亏钱的情况cost>cashback 假设是最后一笔亏钱 需要total+cashback 初始钱数
综上两种情况都是 total+min(cost,cashback)
def minimumMoney(transactions):
"""
:type transactions: List[List[int]]
:rtype: int
"""
total = mx = 0
for cst,back in transactions:
total += max(cst-back,0)
mx = max(mx,min(cst,back))
return total+mx
1/26 40. 组合总和 II
递归
1.按顺序排序 记录使用过的位置loc 防止继续取到前面的数造成重复
因为有重复的数字 所以set要防重复
2.不用set防重复 直接排序后移动 并且判断当前是否已经有重复的了
def combinationSum2(candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates = sorted(candidates)
ans=set()
def dfs(v,l,nums,loc):
print(v,l,nums)
if v==0:
ans.add(tuple(l))
return
if not nums:
print("empty")
return
for i in range(loc,len(nums)):
tmpl = l[:]
tmp = nums[:]
c = tmp.pop(i)
if c>v:
return
tmpl.append(c)
dfs(v-c,tmpl,tmp,i)
dfs(target,[],candidates,0)
ret = [list(i) for i in ans]
return ret
print(ret)
def combinationSum22(candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates = sorted(candidates)
n = len(candidates)
ret = []
def dfs(v,l,loc):
print(v,l,candidates)
if v==0:
ret.append(l)
return
for i in range(loc,n):
value = candidates[i]
if value>v: #有序排列 后面的都不符合
return
if i>loc and candidates[i]==candidates[i-1]:
continue
tmp = l[:]
tmp.append(candidates[i])
dfs(v-value,tmp,i+1)
dfs(target,[],0)
return ret
print(ret)