算法日志 --- 12.04---最接近目标价格的甜点成本

78 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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);

    }
}

image.png