动态规则笔记
框架
# 初始化 base case
dp[0][0][...] = base
# 进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)
斐波那契数
class Solution {
public int fib(int n) {
if(n == 0 || n==1) {
return n;
}
int answer = 0;
int last = 1;
int last_last = 0;
for(int i=2; i<=n; i++) {
answer = last + last_last;
last_last = last;
last = answer;
}
return answer;
}
}
零钱兑换
题目:
给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能组成总金额,返回 -1。
class Solution {
Map<Integer, Integer> map = new HashMap<>();
// 非递归版本
public int coinChange(int[] coins, int amount) {
if(amount == 0) {
return 0;
}
int[] arr = new int[amount + 1];
for(int i=1; i<arr.length; i++) {
arr[i] = -1;
}
for(int coin: coins) {
if(coin < arr.length) arr[coin] = 1;
}
for(int i=1; i<=amount; i++) {
if(arr[i] != -1) continue;
int min = i;
boolean hasAnawer = false;
for(int coin: coins) {
if(i-coin < 0) continue;
if(arr[i-coin] == -1) continue;
min = Math.min(min, arr[i-coin] + 1);
hasAnawer = true;
}
if(hasAnawer) arr[i] = min;
}
return arr[amount];
}
// 递归版本
public int coinChange2(int[] coins, int amount) {
if(map.containsKey(amount)) return map.get(amount);
if(amount == 0) {
map.put(amount, 0);
return 0;
}
if(amount < 0) {
map.put(amount, -1);
return -1;
}
int min = amount;
boolean hasAnawer = false;
for(int coin : coins) {
if(amount - coin < 0) continue;
int subAnswer = coinChange(coins, amount - coin);
if (subAnswer == -1) continue;
min = Math.min(min, subAnswer + 1);
hasAnawer = true;
}
if (!hasAnawer) min = -1;
map.put(amount, min);
return min;
}
}
发布于 2020/08/23
浏览
次