开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
周日的我,依然在加班工作,我也不知道为了这几两碎银是干嘛...
最接近目标价格的甜点成本
该题是出自力扣的1774题 —— 最接近目标价格的甜点成本【中等题】
审题
规则: 必须选择 一种 冰激凌基料。 可以添加 一种或多种 配料,也可以不添加任何配料。 每种类型的配料 最多两份 。 给你以下三个输入: baseCosts ,一个长度为 n 的整数数组,其中每个 baseCosts[i] 表示第 i 种冰激凌基料的价格。 toppingCosts,一个长度为 m 的整数数组,其中每个 toppingCosts[i] 表示 一份 第 i 种冰激凌配料的价格。 target ,一个整数,表示你制作甜点的目标价格。 你希望自己做的甜点总成本尽可能接近目标价格 target 。 返回最接近 target 的甜点成本。如果有多种方案,返回 成本相对较低 的一种。
- 这道题是中等题,确实是挺拗口的,也挺麻烦的,虽然知道是回溯,但是并不能马上做出来
- 回溯:
- 业务规则已经列出来了,给出三个数组,第一个数组属于是必选项,必须是在基料中选择一款出来
- 第二个数组是选择配料,可以选1种,或者多种多次,也可以不选
- 在两个数组中找出最接近目标数的组合
- 基于这些业务规则,那么直接遍历第一个必选项的数组
- 遍历内部执行函数 —— 回溯
- 判断如果当前成本已经大于目标值,那么直接返回,剪枝
- 判断如果成本小于等于当前方案,如果是小于,则覆盖,如果是等于,则选择成本最小的方案
- 如果长度已经等于配料长度,那么也是直接返回
- 对三种情况进行递归回溯
编码
class Solution {
int res;
public int closestCost(int[] baseCosts, int[] toppingCosts, int target) {
int min = Arrays.stream(baseCosts).min().getAsInt();
if (min >= target)return min;
res = min;
for (int a:baseCosts) {
dfs(toppingCosts,0,a,target);
}
return res;
}
private void dfs(int[] toppingCosts, int i, int a, int target) {
if (a - target > Math.abs(res - target))return;
if (Math.abs(a - target) <= Math.abs(res - target)){
if (Math.abs(a - target) < Math.abs(res - target)) {
res = a;
} else {
res = Math.min(res, a);
}
}
if (i >= toppingCosts.length) {
return;
}
// 对于当前元素(基料),三种选择
dfs(toppingCosts, i + 1, a, target);
dfs(toppingCosts, i + 1, a + toppingCosts[i], target);
dfs(toppingCosts, i + 1, a + 2 * toppingCosts[i], target);
}
}