[LeetCode] 983. 最低票价
方法一:记忆化搜索(日期变量型)
class Solution { int[] costs; Integer[] memo; Set<Integer> dayset; public int mincostTickets(int[] days, int[] costs) { this.costs = costs; memo = new Integer[366]; dayset = new HashSet(); for (int d: days) { dayset.add(d); } return dp(1); } public int dp(int i) { if (i > 365) { return 0; } if (memo[i] != null) { return memo[i]; } if (dayset.contains(i)) { memo[i] = Math.min(Math.min(dp(i + 1) + costs[0], dp(i + 7) + costs[1]), dp(i + 30) + costs[2]); } else { memo[i] = dp(i + 1); } return memo[i]; } }
方法二:动态规划思路步骤 (从后向前迭代)
class Solution { public int mincostTickets(int[] days, int[] costs) { int len = days.length, maxDay = days[len - 1], minDay = days[0]; int[] dp = new int[maxDay + 31]; // 多扩几天,省得判断 365 的限制 // 只需看 maxDay -> minDay,此区间外都不需要出门,不会增加费用 for (int d = maxDay, i = len - 1; d >= minDay; d--) { // i 表示 days 的索引 // 也可提前将所有 days 放入 Set,再通过 set.contains() 判断 if (d == days[i]) { dp[d] = Math.min(dp[d + 1] + costs[0], dp[d + 7] + costs[1]); dp[d] = Math.min(dp[d], dp[d + 30] + costs[2]); i--; // 别忘了递减一天 } else dp[d] = dp[d + 1]; // 不需要出门 } return dp[minDay]; // 从后向前遍历,返回最前的 minDay } }