第一个小目标:50道动态规划题目。
使用prev进行返回可能存在越界风险。使用cur进行返回需要在程序最开始时判断条件并返回。
1. 509 斐波那契数
本题的核心在于两个变量(prev和cur)逐步往前走。
class Solution {
public:
int fib(int n) {
int prev = 0, cur = 1;
while (n--) {
int temp = cur;
cur = cur + prev;
prev = temp;
}
return prev;
}
};
class Solution {
public:
int fib(int n) {
if (n <= 1) return n;
int prev = 0, cur = 1;
n -= 1;
while (n--) {
int temp = cur;
cur = cur + prev;
prev = temp;
}
return cur;
}
};
2. 1137 第 N 个泰波那契数
需要注意的是用哪个变量作为返回值,其中该变量的范围很重要,比如返回值的最大值为 2 31 − 1 2^{31}-1 231−1,如果使用prev作为返回,则cur和prev使用int则会产生越界现象。
class Solution {
public:
int tribonacci(int n) {
unsigned int prev = 0, cur = 1, nex = 1;
while (n--) {
unsigned int t1 = cur;
unsigned int t2 = nex;
nex = prev + cur + nex;
prev = t1;
cur = t2;
}
return prev;
}
};
class Solution {
public:
int tribonacci(int n) {
if (n <= 1) return n;
int prev = 0, cur = 1, nex = 1;
n -= 2;
while (n--) {
int t1 = cur;
int t2 = nex;
nex += cur + prev;
cur = t2;
prev = t1;
}
return nex;
}
};
3. 70 爬楼梯
class Solution {
public:
int climbStairs(int n) {
if (n == 1) return 1;
int prev = 1, cur = 2;
n -= 2;
while (n--) {
int temp = cur;
cur += prev;
prev = temp;
}
return cur;
}
};
确定零点很重要,这里的零点是2。
4. 746 使用最小花费爬楼梯
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
if (cost.size() == 2) return min(cost[0], cost[1]);
cost.push_back(0);
int prev = cost[0];
int cur = cost[1];
for (int i=2; i<cost.size(); ++i) {
int temp = cur;
cur = min(prev, cur) + cost[i];
prev = temp;
}
cost.pop_back();
return cur;
}
};
爬楼梯和打家劫舍有很大的区别。前者和后者的区别之处在于:
5. 198 打家劫舍
f(0) = nums[0]
f(1) = max(f(0), f(1))
f(i) = max(f(i-1), f(i-2)+nums[i])
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
int prev = nums[0];
int cur = max(nums[0], nums[1]);
for (int i=2; i<nums.size(); ++i) {
int temp = cur;
cur = max(prev+nums[i], cur);
prev = temp;
}
return cur;
}
};
不能取相邻,本来原本是两个方向,为什么用单个方向来代替也是可以的~~~