Coin Change
转移方程:
f(x)
f
(
x
)
:amount
x
x
需要的最少硬币数。
初值:
def coinChange(coins, amount):
# write your code here
num=[float('inf')]*(amount+1)
num[0]=0
for i in range(amount+1):
for money in coins:
if i>=money:
num[i]=min(num[i],num[i-money]+1)
if num[-1]==float('inf'):
return -1
return num[-1]
Paint House
def minCost(costs):
# write your code here
if not costs:
return 0
n=len(costs)
minCost0=[0]*n
minCost1=[0]*n
minCost2=[0]*n
for i in range(n):
if i==0:
minCost0[i]=costs[0][0]
minCost1[i]=costs[0][1]
minCost2[i]=costs[0][2]
else:
minCost0[i]=min(minCost1[i-1],minCost2[i-1])+costs[i][0]
minCost1[i]=min(minCost0[i-1],minCost2[i-1])+costs[i][1]
minCost2[i]=min(minCost0[i-1],minCost1[i-1])+costs[i][2]
return min(minCost0[-1],minCost1[-1],minCost2[-1])
Longest Increasing Continuous Subsequence
def longestIncreasingContinuousSubsequence(lst):
if not lst:
return 0
ret_increase=[1]*len(lst) #以自己结尾的最长连续子序列
ret_decrease=[1]*len(lst)
for i in range(len(lst)):
if i>=1:
if lst[i]>lst[i-1]:
ret_increase[i]=ret_increase[i-1]+1
elif lst[i]<lst[i-1]:
ret_decrease[i]=ret_decrease[i-1]+1
return max(max(ret_decrease),max(ret_increase))
Counting Bits
def countingBits(num):
ret=[0]*(num+1)
for i in range(1,num+1):
ret[i]=ret[i>>2]+i%2
return ret
Paint House 2
第
i
i
个房子涂第种颜色的最小费用:
class Solution:
"""
@param costs: n x k cost matrix
@return: an integer, the minimum cost to paint all houses
"""
def minCostII(self, costs):
# write your code here
if not costs:
return 0
if not costs[0]:
return 0
N=len(costs)
K=len(costs[0])
money=[[0]*(K) for _ in range(N+1)]
for n in range(1,N+1):
for k in range(K):
money[n][k]=float('inf')
for j in range(K):
if j!=k:
money[n][k]=min(money[n-1][j]+costs[n-1][k],money[n][k])
return min(money[-1])
直接遍历的话,时间复杂度为
O(nk2)
O
(
n
k
2
)
,运行超时。
优化算法:
计算第
i
i
个房子涂色需要的最小费用时,我们需要记录的最小两个值,时间复杂度变为
O(nk)
O
(
n
k
)
。
class Solution:
"""
@param costs: n x k cost matrix
@return: an integer, the minimum cost to paint all houses
"""
def minCostII(self, costs):
# write your code here
if not costs:
return 0
if not costs[0]:
return 0
N=len(costs)
K=len(costs[0])
money=[[0]*(K) for _ in range(N+1)]
for n in range(1,N+1):
#找到上一轮最小的两个值
min1=float('inf')
min2=float('inf')
j1=-1; j2=-1
for k in range(K):
if money[n-1][k]<min1:
min2=min1
j2=j1
min1=money[n-1][k]
j1=k
elif money[n-1][k]<min2:
min2=money[n-1][k]
j2=k
for k in range(K):
if k!=j1:#如果k并不是上一轮最小的那个颜色,直接取最小值
money[n][k]=min1+costs[n-1][k]
else:#如果k是上一轮最小的颜色,取第二小
money[n][k]=min2+costs[n-1][k]
return min(money[-1])
House Robber 1
对于第
i
i
栋房子,有两种选择,如果不偷,那么总共偷到的最多的钱和一样,如果偷,那么总共偷到的最多的钱为
f(i−2)+A[i]
f
(
i
−
2
)
+
A
[
i
]
:
class Solution:
"""
@param A: An array of non-negative integers
@return: The maximum amount of money you can rob tonight
"""
def houseRobber(self, A):
# write your code here
if not A:
return 0
n=len(A)
money=[e for e in A]
for i in range(n):
if i>=1:
money[i]=max(money[i-1],money[i])#不偷
if i>=2:
money[i]=max(money[i-2]+A[i],money[i])#偷
return money[-1]
House Robber 2
第0个和
n−1
n
−
1
不能同时偷。
参考资料:
侯卫东老师动态规划专题课程