买卖股票的最佳时机
输入: [7,1,5,3,6,4]输出: 5解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
class Solution {public:int maxProfit(vector<int>& prices) {const int n = prices.size();if(n == 0) return 0;int dp[n][2];for(int i = 0; i < n; i++){if(i - 1 == -1){dp[i][0] = 0;dp[i][1] = -prices[i];continue;}dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);dp[i][1] = max(dp[i - 1][1], -prices[i]);}return dp[n - 1][0];}};dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])max( 选择 rest , 选择 sell )解释:今天我没有持有股票,有两种可能:要么是我昨天就没有持有,然后今天选择 rest,所以我今天还是没有持有;要么是我昨天持有股票,但是今天我 sell 了,所以我今天没有持有股票了。dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])max( 选择 rest , 选择 buy )解释:今天我持有着股票,有两种可能:要么我昨天就持有着股票,然后今天选择 rest,所以我今天还持有着股票;要么我昨天本没有持有,但今天我选择 buy,所以今天我就持有股票了。
打家劫舍
输入: [1,2,3,1]输出: 4解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。
简洁写法
class Solution {public:int rob(vector<int>& nums) {const int n = nums.size();if(n == 0) return 0;int dp[n + 1];dp[0] = 0;dp[1] = nums[0];for(int i = 2; i <= n; i++){dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1]);}return dp[n];}};
我自己写的
class Solution {public:int rob(vector<int>& nums) {const int n = nums.size();if(n == 0) return 0;int dp[n][2];//0代表没偷,1代表偷了dp[0][0] = 0;dp[0][1] = nums[0];int ans = nums[0];for(int i = 1; i < n; i++){dp[i][1] = dp[i - 1][0] + nums[i];dp[i][0] = max(dp[i - 1][1], dp[i - 1][0]);ans = max(ans, max(dp[i][1], dp[i][0]));}return ans;}};
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
class Solution {public:bool isSubsequence(string s, string t) {int flag = 0;if(s.size() == 0) return true;for(int i = 0;i < t.size(); i++){if(t[i] == s[flag]) {flag++;if(flag == s.size())return true;}}return false;}};
花费最少代价爬楼梯
数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始)。每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。示例 1:输入: cost = [10, 15, 20]输出: 15解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。
class Solution {public:int minCostClimbingStairs(vector<int>& cost) {const int n = cost.size();vector<int> dp(n + 1);//dp[i]的含义是到达i层之前所花费的代价dp[0] = 0;dp[1] = 0;for(int i = 2; i <= n; i++){dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[n];}};
三步问题
三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。
class Solution {public:int waysToStep(int n) {vector<long long> dp(n + 1);if(n <= 2) return n;if(n == 3) return 4;dp[1] = 1, dp[2] = 2, dp[3] = 4;for(int i = 4; i <= n; i++){dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % (1000000007);}return dp[n];}};
最大连续子列和
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。示例1:输入: nums = [-2,1,-3,4,-1,2,1,-5,4]输出: 6解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
class Solution {public:int maxSubArray(vector<int>& nums) {int len = nums.size();vector<int> dp(len);dp[0] = nums[0];int maxnum = dp[0];for(int i = 1; i < len; i++){dp[i] = max(nums[i], dp[i - 1] + nums[i]);if(dp[i] > maxnum) maxnum = dp[i];}return maxnum;}};
按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。输入: [2,7,9,3,1]输出: 12解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
class Solution {public:int massage(vector<int>& nums) {int len = nums.size();if(len == 0) return 0;if(len == 1) return nums[0];vector<int>dp(len);dp[0] = nums[0];dp[1] = max(nums[0], nums[1]);for(int i = 2; i < len; i++){dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);}return dp[len - 1];}};
