代码随想录第四十五天|70. 爬楼梯 (进阶)、 322. 零钱兑换、279.完全平方数

70. 爬楼梯 (进阶)

1.代码展示

//70.爬楼梯
int climbStairs(int n) {
	vector dp(n + 1, 0);
	//dp[j]的含义是爬到j层高的楼梯有多少种方法
	dp[0] = 1;
	for (int j = 0; j <= n; j++) {
		for (int i = 1; i <= 2; i++) {
			if (j >= i) dp[j] += dp[j - i];
		}
	}
	return dp[n];
}

2.本题小节

        思考: 通过题意可以知道本题是完全背包求方法次数的排序问题,因此先遍历背包容量(台阶数),再遍历物品(每次可以爬多少阶),本题如果是每次可以爬1-m阶的话,第二个for循环2就应该变为m。

        基本思路:构建dp数组,初始化dp[0] = 1,这个一定不能初始化为0,两层for循环,注意j >= i时才能计算方法,方法次数的状态转移方程为dp[j] += dp[j - i];

322. 零钱兑换

1.代码展示

//322. 零钱兑换
int coinChange(vector& coins, int amount) {
	//dp数组的含义是填满容量为amount的背包所需要的最少硬币数目
	//由于要求的是最小个数,因此dp数组初始化为INT_MAX
	vector dp(amount + 1, INT_MAX);
	dp[0] = 0;
	//先遍历容量,再遍历物品
	for (int j = 0; j <= amount; j++) {
		for (int i = 0; i < coins.size(); i++) {
			if(j >= coins[i] && dp[j - coins[i]] != INT_MAX)
				dp[j] = min(dp[j], dp[j - coins[i]] + 1);
		}
	}
	if (dp[amount] == INT_MAX) return -1;
	return dp[amount];
}

 2.本题小节

        思考:本题是完全背包求解装满背包容量为amount所需要的最小物品(硬币)数目,本题不涉及到排序与组合问题,因此物品和背包遍历顺序可以颠倒,注意初始化时除了dp[0] = 0之外,其他的数都初始化为INT_MAX,如果dp[0]没有初始化为0的话,无法比较,都是INT_MAX,由于dp[j - coins[i]] 会为INT_MAX,因此为了防止dp[j - coins[i]] + 1越界,除了j >= coins[i],dp[j - coins[i]] != INT_MAX,此时dp[j]不变,最后dp[amount] != INT_MAX时,return。

        基本思路:如上,注意初始化dp[0] = 0;完全背包求最小物品数与遍历顺序无关;注意越界的问题。

279.完全平方数

1.代码展示

//279 完全平方数
int numSquares(int n) {
	//step1 构建dp数组
	vector dp(n + 1, INT_MAX);
	//step2 状态转移方程
	//dp[j] = min(dp[j], dp[j - i * i] + 1)
	//step3 初始化数组
	dp[0] = 0;
	//step4 确定遍历顺序
	for (int j = 0; j <= n; j++) {
		for (int i = 1; i <= 100; i++) {
			if (j >= i * i && dp[j - i * i] != INT_MAX) 
				dp[j] = min(dp[j], dp[j - i * i] + 1);
		}
	}
	return dp[n];
}

2.本题小节

        思考:本题和上一题一样,包括初始化等,不同的是物品是从1到100 ,这里还有优化空间,可以让i <= 100,变为i * i <= j,这样遍历的物品更少,这里因为n最大为10000,所以我给物品的是1-100。

你可能感兴趣的:(算法,数据结构)