这里是题目描述:LeetCode-5399.数位成本和为目标值的最大数字
本题使用背包动态规划来解。维护一个一维表dp
,dp[i]
用来存储总成本为i
时能得到的最大数字。从i=1
开始构建dp[i]
,一直构建到i=target
。不能恰好用完成本i
构建出数字的,记为dp[i]="0"
;对于每个dp[i]
,遍历数位成本数组cost
,如果cost[j]>i
,总成本不够,不能选用,而对于cost[j]<=i
,我们对数位j
有“选用”和“不选”两种情况,需要视构建的最大数字情况而定。状态转移方程如下:
dp[i]=max("0",max(dp[i-cost[j]]+j))
题解代码:
class Solution {
public String largestNumber(int[] cost, int target) {
String[] dp=new String[target]; //用于动规的数组,dp[i]记录成本为i+1时可以得到的最大整数,不能得到是记为"0"
HashMap<Integer,Integer> costMap=new HashMap<>();
for(int i=0;i<cost.length;i++)
{
costMap.put(cost[i],i+1); //只保留相同cost中最大的
}
for(int i=0;i<target;i++)
{
int i1=i+1;
dp[i]="0";
for(int c:costMap.keySet())
{
int j=costMap.get(c)-1;
int j1=j+1;
if(i1==cost[j]) //cost[j]刚好等于总成本
{
String t=j1+"";
if(compareStr(t,dp[i]))
{
dp[i]=t;
}
}
else if(i1>cost[j] && !dp[i-cost[j]].equals("0")) //cost[j]小于总成本
{
String t=dp[i-cost[j]]+j1;
if(compareStr(t,dp[i]))
{
dp[i]=t;
}
}
}
}
return dp[dp.length-1];
}
boolean compareStr(String s1,String s2) //比较两个字符串,s1是否大于s2
{
if(s1.length()!=s2.length())
{
return s1.length()>s2.length();
}
else
{
return s1.compareTo(s2)>0;
}
}
}
本题中,成本i
可以类比为背包动态规划中的背包容量,花费cost[j]
相当于物品的体积,数位j
可以看做物品价值。因此,可以看做一个背包动规问题。
时间复杂度:设总成本为m
,不同数位成本有m
种,于是总体时间复杂度为O(mn)。又因为数位成本必不超过9
种,因此最大时间复杂度为O(10*m)
空间复杂度:设总成本为m
,O(m)