This commit is contained in:
programmercarl
2023-11-09 14:32:56 +08:00
parent 4dac467907
commit 2caee6fe9f
12 changed files with 618 additions and 1266 deletions

View File

@@ -4,30 +4,34 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 70. 爬楼梯
# 70. 爬楼梯(进阶版)
[力扣题目链接](https://leetcode.cn/problems/climbing-stairs/)
[卡码网57. 爬楼梯](https://kamacoder.com/problempage.php?pid=1067)
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
注意:给定 n 是一个正整数。
示例 1
输入: 2
输出 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
输入描述输入共一行包含两个正整数分别表示n, m
输出描述:输出一个整数,表示爬到楼顶的方法数。
输入示例3 2
输出示例3
提示:
当 m = 2n = 3 时n = 3 这表示一共有三个台阶m = 2 代表你每次可以爬一个台阶或者两个台阶。
此时你有三种方法可以爬到楼顶。
* 1 阶 + 1 阶 + 1 阶段
* 1 阶 + 2 阶
* 2 阶 + 1 阶
示例 2
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
## 思路
@@ -35,11 +39,13 @@
**这次终于讲到了背包问题,我选择带录友们再爬一次楼梯!**
这道题目 我们在[动态规划:爬楼梯](https://programmercarl.com/0070.爬楼梯.html) 中已经讲过一次了,原题其实是一道简单动规的题目。
这道题目 我们在[动态规划:爬楼梯](https://programmercarl.com/0070.爬楼梯.html) 中已经讲过一次了,这次我又给本题加点料,力扣上没有原题,所以可以在卡码网[57. 爬楼梯](https://kamacoder.com/problempage.php?pid=1067)上来刷这道题目。
既然这么简单为什么还要讲呢,其实本题稍加改动就是一道面试好题
我们之前做的 爬楼梯 是只能至多爬两个台阶
**改为:一步一个台阶,两个台阶,三个台阶,.......,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢**
这次**改为:一步一个台阶,两个台阶,三个台阶,.......,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢**
这又有难度了,这其实是一个完全背包问题。
1阶2阶.... m阶就是物品楼顶就是背包。
@@ -86,27 +92,31 @@
以上分析完毕C++代码如下:
```CPP
class Solution {
public:
int climbStairs(int n) {
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
while (cin >> n >> m) {
vector<int> dp(n + 1, 0);
dp[0] = 1;
for (int i = 1; i <= n; i++) { // 遍历背包
for (int j = 1; j <= m; j++) { // 遍历物品
for (int i = 1; i <= n; i++) { // 遍历物品
for (int j = 1; j <= m; j++) { // 遍历背包
if (i - j >= 0) dp[i] += dp[i - j];
}
}
return dp[n];
cout << dp[n] << endl;
}
};
}
```
* 时间复杂度: O(nm)
* 时间复杂度: O(n * m)
* 空间复杂度: O(n)
代码中m表示最多可以爬m个台阶代码中把m改成2就是 力扣70.爬楼梯的解题思路。
**当然注意 力扣是 核心代码模式卡码网是ACM模式**
代码中m表示最多可以爬m个台阶代码中把m改成2就是本题70.爬楼梯可以AC的代码了。
## 总结
@@ -129,123 +139,22 @@ public:
### Java:
```java
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n + 1];
int m = 2; //有兩個物品itme1重量爲一item2重量爲二
dp[0] = 1;
for (int i = 1; i <= n; i++) { // 遍历背包
for (int j = 1; j <= m; j++) { //遍历物品
if (i >= j) //當前的背包容量 大於 物品重量的時候,我們才需要記錄當前的這個裝得方法(方法數+
dp[i] += dp[i - j];
}
}
return dp[n];
}
}
```
### Python3
```python
class Solution:
def climbStairs(self, n: int) -> int:
dp = [0]*(n + 1)
dp[0] = 1
m = 2
# 遍历背包
for j in range(n + 1):
# 遍历物品
for step in range(1, m + 1):
if j >= step:
dp[j] += dp[j - step]
return dp[n]
```
### Go
```go
func climbStairs(n int) int {
//定义
dp := make([]int, n+1)
//初始化
dp[0] = 1
// 本题物品只有两个1,2
m := 2
// 遍历顺序
for j := 1; j <= n; j++ { //先遍历背包
for i := 1; i <= m; i++ { //再遍历物品
if j >= i {
dp[j] += dp[j-i]
}
//fmt.Println(dp)
}
}
return dp[n]
}
```
### JavaScript:
```javascript
var climbStairs = function(n) {
const dp = new Array(n + 1).fill(0);
const m = 2;
dp[0] = 1;
for(let i = 1; i <= n; i++){
for(let j = 1; j <= m; j++){
if(i >= j) {
dp[i] += dp[i - j];
}
}
}
return dp[n];
};
```
### TypeScript
```typescript
function climbStairs(n: number): number {
const m: number = 2; // 本题m为2
const dp: number[] = new Array(n + 1).fill(0);
dp[0] = 1;
// 遍历背包
for (let i = 1; i <= n; i++) {
// 遍历物品
for (let j = 1; j <= m; j++) {
if (j <= i) {
dp[i] += dp[i - j];
}
}
}
return dp[n];
};
```
### Rust:
```rust
impl Solution {
pub fn climb_stairs(n: i32) -> i32 {
let (n, m) = (n as usize, 2);
let mut dp = vec![0; n + 1];
dp[0] = 1;
for i in 1..=n {
for j in 1..=m {
if i >= j {
dp[i] += dp[i - j];
}
}
}
dp[n]
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">