diff --git a/notes/src/SUMMARY.md b/notes/src/SUMMARY.md index 527c492..6d50280 100644 --- a/notes/src/SUMMARY.md +++ b/notes/src/SUMMARY.md @@ -151,4 +151,22 @@ - [322. 零钱兑换](./day45/lc322.md) - [279.完全平方数](./day45/lc279.md) - [day 46](./day46.md) + - [139.单词拆分](./day46/lc139.md) +- [day 48](./day48.md) + - [198.打家劫舍](./day48/lc198.md) + - [213.打家劫舍II](./day48/lc213.md) + - [337.打家劫舍III](./day48/lc337.md) +- [day 49](./day49.md) + - [121. 买卖股票的最佳时机](./day49/lc121.md) + - [122.买卖股票的最佳时机II](./day49/lc122.md) +- [day 50](./day50.md) + - [123.买卖股票的最佳时机III](./day50/lc123.md) + - [188.买卖股票的最佳时机IV](./day50/lc188.md) +- [day 51](./day51.md) + - [309.最佳买卖股票时机含冷冻期](./day51/lc309.md) + - [714.买卖股票的最佳时机含手续费](./day51/lc714.md) +- [day 52](./day52.md) + - [300.最长递增子序列](./day52/lc300.md) + - [674. 最长连续递增序列](./day52/lc674.md) + - [718. 最长重复子数组](./day52/lc718.md) - [remains](./remains.md) \ No newline at end of file diff --git a/notes/src/day48.md b/notes/src/day48.md new file mode 100644 index 0000000..c9f8ec8 --- /dev/null +++ b/notes/src/day48.md @@ -0,0 +1,20 @@ +# 第九章 动态规划part09 +● 198.打家劫舍 +● 213.打家劫舍II +● 337.打家劫舍III + + 详细布置 + +今天就是打家劫舍的一天,这个系列不算难,大家可以一口气拿下。 + +## 198.打家劫舍 +视频讲解:https://www.bilibili.com/video/BV1Te411N7SX +https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html + +## 213.打家劫舍II +视频讲解:https://www.bilibili.com/video/BV1oM411B7xq +https://programmercarl.com/0213.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8DII.html + +## 337.打家劫舍III +视频讲解:https://www.bilibili.com/video/BV1H24y1Q7sY +https://programmercarl.com/0337.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8DIII.html diff --git a/notes/src/day48/lc198.md b/notes/src/day48/lc198.md new file mode 100644 index 0000000..c1de1e7 --- /dev/null +++ b/notes/src/day48/lc198.md @@ -0,0 +1,23 @@ +# 198. 打家劫舍 + +这个是抄随想录的 + + +```cpp +class Solution { +public: + int rob(vector& nums) { + if (nums.size() == 0) return 0; + if (nums.size() == 1) return nums[0]; + // dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i] + // dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); + vector dp(nums.size()); + dp[0] = nums[0]; + dp[1] = max(nums[0], nums[1]); + for (int i = 2; i < nums.size(); i++) { + dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); + } + return dp[nums.size() - 1]; + } +}; +``` \ No newline at end of file diff --git a/notes/src/day48/lc213.md b/notes/src/day48/lc213.md new file mode 100644 index 0000000..82d7576 --- /dev/null +++ b/notes/src/day48/lc213.md @@ -0,0 +1,33 @@ +## 213. 打家劫舍 II + +这个是自己写的 + +```cpp +class Solution { +public: + int rob(vector& nums) { + if (nums.size() == 0) return 0; + if (nums.size() == 1) return nums[0]; + // dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i] + // dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); + vector dp(nums.size()); + // skip index 0 first + int res = 0; + dp[0] = 0; + dp[1] = nums[1]; + for (int i = 2; i < nums.size(); i++) { + dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); + } + res = dp[nums.size()-1]; + dp[0] = nums[0]; + dp[1] = max(nums[0], nums[1]); + + for (int i = 2; i < nums.size() - 1; i++) { + dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); + } + + res = max(res,dp[nums.size()-2]); + return res; + } +}; +``` \ No newline at end of file diff --git a/notes/src/day48/lc337.md b/notes/src/day48/lc337.md new file mode 100644 index 0000000..1be40a5 --- /dev/null +++ b/notes/src/day48/lc337.md @@ -0,0 +1,37 @@ +# 337.打家劫舍III + +自己做的 + +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: +// r1 如果偷当前节点,得到的最大值 ; r2 不偷当前节点的最大值 + pair f(TreeNode*root) { + if(!root){return make_pair(0,0);} + auto leftr = f(root->left); + auto rightr = f(root->right); + int takeleft = leftr.first; + int notakeleft = leftr.second; + int takeright = rightr.first; + int notakeright = rightr.second; + int r1 = notakeleft + notakeright + root->val; + int r2 = max(takeleft,notakeleft) + max(takeright,notakeright); + return make_pair(r1, r2); + } + int rob(TreeNode* root) { + auto res = f(root); + return max(res.first, res.second); + } +}; +``` \ No newline at end of file diff --git a/notes/src/day49.md b/notes/src/day49.md new file mode 100644 index 0000000..d15b85a --- /dev/null +++ b/notes/src/day49.md @@ -0,0 +1,20 @@ +# 第九章 动态规划part10 + +● 121. 买卖股票的最佳时机 +● 122.买卖股票的最佳时机II + + 详细布置 + +股票问题是一个动态规划的系列问题,今日安排的题目不多,大家可以慢慢消化。 + +## 121. 买卖股票的最佳时机 +视频讲解:https://www.bilibili.com/video/BV1Xe4y1u77q +https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BA.html + + + + + +## 122.买卖股票的最佳时机II +视频讲解:https://www.bilibili.com/video/BV1D24y1Q7Ls +https://programmercarl.com/0122.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAII%EF%BC%88%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%EF%BC%89.html diff --git a/notes/src/day49/lc121.md b/notes/src/day49/lc121.md new file mode 100644 index 0000000..b9106f9 --- /dev/null +++ b/notes/src/day49/lc121.md @@ -0,0 +1,20 @@ +# 121. 买卖股票的最佳时机 + +一开始这样子没有用动规 + +```cpp +class Solution { +public: + int maxProfit(vector& prices) { + int res = 0; + int cmin = INT_MAX; + for (int i = 0; i < prices.size(); i ++ ) { + cmin = min(cmin, prices[i]); + if (prices[i] > cmin) { + res = max(res, prices[i] - cmin); + } + } + return res; + } +}; +``` \ No newline at end of file diff --git a/notes/src/day49/lc122.md b/notes/src/day49/lc122.md new file mode 100644 index 0000000..7628a72 --- /dev/null +++ b/notes/src/day49/lc122.md @@ -0,0 +1,35 @@ +# 122. 买卖股票的最佳时机 II + +抄了随想录 + +```cpp +class Solution { +public: + int maxProfit(vector& prices) { + int len = prices.size(); + vector> dp(len, vector(2, 0)); + // dp[i][0] 表示第i天持有股票所得现金。 + // dp[i][1] 表示第i天不持有股票所得最多现金 + +// 如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来 + +// 第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0] +// 第i天买入股票,所得现金就是昨天不持有股票的所得现金减去 今天的股票价格 即:dp[i - 1][1] - prices[i] + + +// 再来看看如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来 + +// 第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1] +// 第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0] + dp[0][0] -= prices[0]; + dp[0][1] = 0; + for (int i = 1; i < len; i++) { + dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); // 注意这里是和121. 买卖股票的最佳时机唯一不同的地方。 + dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]); + } + return dp[len - 1][1]; + + + } +}; +``` \ No newline at end of file diff --git a/notes/src/day50.md b/notes/src/day50.md new file mode 100644 index 0000000..fb305aa --- /dev/null +++ b/notes/src/day50.md @@ -0,0 +1,21 @@ +# 第九章 动态规划part11 + +● 123.买卖股票的最佳时机III +● 188.买卖股票的最佳时机IV + + 详细布置 + +## 123.买卖股票的最佳时机III + +这道题一下子就难度上来了,关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。 +视频讲解:https://www.bilibili.com/video/BV1WG411K7AR +https://programmercarl.com/0123.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAIII.html + +## 188.买卖股票的最佳时机IV +本题是123.买卖股票的最佳时机III 的进阶版 +视频讲解:https://www.bilibili.com/video/BV16M411U7XJ +https://programmercarl.com/0188.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAIV.html + + + + diff --git a/notes/src/day50/lc123.md b/notes/src/day50/lc123.md new file mode 100644 index 0000000..0b991e1 --- /dev/null +++ b/notes/src/day50/lc123.md @@ -0,0 +1,30 @@ +# 123.买卖股票的最佳时机III + + +自己写的时候漏掉了`dp[0][3]=-prices[0];`这个条件 + +```cpp +class Solution { +public: + int maxProfit(vector& prices) { +// 一天一共就有五个状态, + +// 没有操作 (其实我们也可以不设置这个状态) +// 第一次持有股票 +// 第一次不持有股票 +// 第二次持有股票 +// 第二次不持有股票 +// dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。 +vector>dp(prices.size(), vector(5,0)); +dp[0][1]=dp[0][3]=-prices[0]; + +for(int i=1;i& prices) { + vector>dp(prices.size(), vector(2*k+1,0)); + for(int j=0;j& v) { + // dp[i][j] 表示第i天的最大现金 + // 0 持有 + // 1 非持有且不在冷冻期 + // 2 非持有且冷冻期(刚出售) + vector>dp(v.size(),vector(3,0)); + dp[0][0]=-v[0]; + for(int i=1;i& v, int fee) { + // dp[i][j] + // 0 持有 + // 1 不持有 + vector>dp(v.size(),vector(2,0)); + dp[0][0]=-v[0]; + for(int i=1;i& v) { + // dp[i] 表示以i结尾的LIS的长度 + int res = 1; + vectordp(v.size(),1); + for(int i = 1;iv[j])dp[i]=max(dp[i],dp[j]+1); + } + res = max(res, dp[i]); + } + return res; + } +}; +``` \ No newline at end of file diff --git a/notes/src/day52/lc674.md b/notes/src/day52/lc674.md new file mode 100644 index 0000000..a6b5df6 --- /dev/null +++ b/notes/src/day52/lc674.md @@ -0,0 +1,20 @@ +# 674. 最长连续递增序列 + + +好像比上一题还简单 + +```cpp +class Solution { +public: + int findLengthOfLCIS(vector& v) { + // dp[i] 表示以i结尾的CLIS的长度 + int res = 1; + vectordp(v.size(),1); + for(int i = 1;iv[i-1])dp[i]=max(dp[i],dp[i-1]+1); + res = max(res, dp[i]); + } + return res; + } +}; +``` \ No newline at end of file diff --git a/notes/src/day52/lc718.md b/notes/src/day52/lc718.md new file mode 100644 index 0000000..1085f54 --- /dev/null +++ b/notes/src/day52/lc718.md @@ -0,0 +1,23 @@ +# 718. 最长重复子数组 + +抄了随想路 + +```cpp +class Solution { +public: + int findLength(vector& nums1, vector& nums2) { + // dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。 (特别注意: “以下标i - 1为结尾的A” 标明一定是 以A[i-1]为结尾的字符串 ) + vector> dp (nums1.size() + 1, vector(nums2.size() + 1, 0)); + int result = 0; + for (int i = 1; i <= nums1.size(); i++) { + for (int j = 1; j <= nums2.size(); j++) { + if (nums1[i - 1] == nums2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } + if (dp[i][j] > result) result = dp[i][j]; + } + } + return result; + } +}; +``` \ No newline at end of file