Given an array of integers cost
and an integer target
. Return the maximum integer you can paint under the following rules:
- The cost of painting a digit (i+1) is given by
cost[i]
(0 indexed). - The total cost used must be equal to
target
. - Integer does not have digits 0.
Since the answer may be too large, return it as string.
If there is no way to paint any integer given the condition, return "0".
Example 1:
Input: cost = [4,3,2,5,6,7,2,5,5], target = 9 Output: "7772" Explanation: The cost to paint the digit '7' is 2, and the digit '2' is 3. Then cost("7772") = 2*3+ 3*1 = 9. You could also paint "977", but "7772" is the largest number. Digit cost 1 -> 4 2 -> 3 3 -> 2 4 -> 5 5 -> 6 6 -> 7 7 -> 2 8 -> 5 9 -> 5
思路:这题暴力解,就是backtracking,但是这题这样想:我选择一个数之后,target减少,那么给定target找最大的数,又是一个子问题,那么给定target,就有最优解,那么这可以用dp来cache住最优解,那么就是我选择了一个数d + dfs(subproblem),我每次从9往0走,greedy的走,这样只要result的string的长度在增加,那么就是最优的,因为前面都是最优的解,我cache住了,那么从后往前走,得到的最长的string,就是最优的解;huahua有个思维导图,很清晰,贴过来,就是怎么表示subproblem;
class Solution {
public String largestNumber(int[] cost, int target) {
String[] dp = new String[target + 1];
return dfs(cost, target, dp);
}
private String dfs(int[] cost, int target, String[] dp) {
if(target < 0) {
return "0";
}
if(target == 0) {
return "";
}
if(dp[target] != null) {
return dp[target];
}
String res = "0";
for(int d = 9; d >= 1; d--) {
String cur = dfs(cost, target - cost[d - 1], dp);
if(cur.equals("0")) {
continue;
}
cur = d + cur;
if(res.equals("0") || cur.length() > res.length()) {
res = cur;
}
}
dp[target] = res;
return dp[target];
}
}
思路2:这题可以buttom up写;计算顺序就是:t从1到target,然后d从1到9,一个个试探,生成最优解;
class Solution {
public String largestNumber(int[] cost, int target) {
String[] dp = new String[target + 1];
Arrays.fill(dp, "0");
dp[0] = "";
for(int t = 1; t <= target; t++) {
for(int d = 1; d <= 9; d++) {
int s = t - cost[d - 1];
if(s < 0 || dp[s].equals("0") || dp[s].length() + 1 < dp[t].length()) {
continue;
}
dp[t] = d + dp[s];
}
}
return dp[target];
}
}