diff --git a/README.md b/README.md index ad22aeab8e..40cd272f60 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ **这里每一篇题解,都是精品,值得仔细琢磨**。 -我在题目讲解中统一用C++语言,但你会发现下面几乎每篇题解都配有其他语言版本,Java、Python、Go、JavaScript等等,这正是热心小伙们的贡献的代码,当然我也会严格把控代码质量。 +我在题目讲解中统一使用C++,但你会发现下面几乎每篇题解都配有其他语言版本,Java、Python、Go、JavaScript等等,正是这些[热心小伙们](https://github.com/youngyangyang04/leetcode-master/graphs/contributors)的贡献的代码,当然我也会严格把控代码质量。 **所以也欢迎大家参与进来,完善题解的各个语言版本,拥抱开源,让更多小伙伴们收益**。 @@ -133,6 +133,13 @@ 9. [秋招和提前批都越来越提前了....](https://mp.weixin.qq.com/s/SNFiRDx8CKyjhTPlys6ywQ) 10. [你的简历里「专业技能」写的够专业么?](https://mp.weixin.qq.com/s/bp6y-e5FVN28H9qc8J9zrg) 11. [对于秋招,实习生也有烦恼....](https://mp.weixin.qq.com/s/ka07IPryFnfmIjByFFcXDg) +12. [华为提前批已经开始了.....](https://mp.weixin.qq.com/s/OC35QDG8pn5OwLpCxieStw) +13. [大厂新人培养体系应该是什么样的?](https://mp.weixin.qq.com/s/WBaPCosOljB5NEkFL2GhOQ) + +## 杂谈 + +[大半年过去了......](https://mp.weixin.qq.com/s/lubfeistPxBLSQIe5XYg5g) + ## 数组 @@ -161,14 +168,15 @@ 1. [关于哈希表,你该了解这些!](./problems/哈希表理论基础.md) 2. [哈希表:可以拿数组当哈希表来用,但哈希值不要太大](./problems/0242.有效的字母异位词.md) -3. [哈希表:哈希值太大了,还是得用set](./problems/0349.两个数组的交集.md) -4. [哈希表:用set来判断快乐数](./problems/0202.快乐数.md) -5. [哈希表:map等候多时了](./problems/0001.两数之和.md) -6. [哈希表:其实需要哈希的地方都能找到map的身影](./problems/0454.四数相加II.md) -7. [哈希表:这道题目我做过?](./problems/0383.赎金信.md) -8. [哈希表:解决了两数之和,那么能解决三数之和么?](./problems/0015.三数之和.md) -9. [双指针法:一样的道理,能解决四数之和](./problems/0018.四数之和.md) -10. [哈希表:总结篇!(每逢总结必经典)](./problems/哈希表总结.md) +3. [哈希表:查找常用字符](./problems/1002.查找常用字符.md) +4. [哈希表:哈希值太大了,还是得用set](./problems/0349.两个数组的交集.md) +5. [哈希表:用set来判断快乐数](./problems/0202.快乐数.md) +6. [哈希表:map等候多时了](./problems/0001.两数之和.md) +7. [哈希表:其实需要哈希的地方都能找到map的身影](./problems/0454.四数相加II.md) +8. [哈希表:这道题目我做过?](./problems/0383.赎金信.md) +9. [哈希表:解决了两数之和,那么能解决三数之和么?](./problems/0015.三数之和.md) +10. [双指针法:一样的道理,能解决四数之和](./problems/0018.四数之和.md) +11. [哈希表:总结篇!(每逢总结必经典)](./problems/哈希表总结.md) ## 字符串 @@ -444,7 +452,7 @@ # 贡献者 -你可以[点此链接](https://github.com/youngyangyang04/leetcode-master/graphs/contributors)查看LeetCode-Master的所有贡献者。感谢你们补充了LeetCode-Master的其他语言版本,让更多的读者收益于此项目。 +[点此这里](https://github.com/youngyangyang04/leetcode-master/graphs/contributors)查看LeetCode-Master的所有贡献者。感谢他们补充了LeetCode-Master的其他语言版本,让更多的读者收益于此项目。 # 关于作者 @@ -459,7 +467,7 @@ # 公众号 -更多精彩文章持续更新,微信搜索:「代码随想录」第一时间围观,关注后回复:「666」可以获得所有算法专题原创PDF。 +更多精彩文章持续更新,微信搜索:「代码随想录」第一时间围观,关注后回复:666,可以获得我的所有算法专题原创PDF。 **「代码随想录」每天准时为你推送一篇经典面试题目,帮你梳理算法知识体系,轻松学习算法!**,并且公众号里有大量学习资源,也有我自己的学习心得和方法总结,更有上万录友们在这里打卡学习。 diff --git "a/problems/0028.\345\256\236\347\216\260strStr.md" "b/problems/0028.\345\256\236\347\216\260strStr.md" index aaa28d3d70..69f8c9d6f2 100644 --- "a/problems/0028.\345\256\236\347\216\260strStr.md" +++ "b/problems/0028.\345\256\236\347\216\260strStr.md" @@ -651,7 +651,7 @@ class Solution { } ``` -Python: +Python3: ```python // 方法一 diff --git "a/problems/0042.\346\216\245\351\233\250\346\260\264.md" "b/problems/0042.\346\216\245\351\233\250\346\260\264.md" index 55a5c52205..70a4e07c2a 100644 --- "a/problems/0042.\346\216\245\351\233\250\346\260\264.md" +++ "b/problems/0042.\346\216\245\351\233\250\346\260\264.md" @@ -1,4 +1,13 @@ +

+ + + + +

+

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+ +> 这个图就是大厂面试经典题目,接雨水! 最常青藤的一道题,面试官百出不厌! # 42. 接雨水 @@ -355,3 +364,9 @@ public: ## 其他语言版本 + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git "a/problems/0059.\350\236\272\346\227\213\347\237\251\351\230\265II.md" "b/problems/0059.\350\236\272\346\227\213\347\237\251\351\230\265II.md" index 6d8ec99cd1..90b7400597 100644 --- "a/problems/0059.\350\236\272\346\227\213\347\237\251\351\230\265II.md" +++ "b/problems/0059.\350\236\272\346\227\213\347\237\251\351\230\265II.md" @@ -148,8 +148,6 @@ class Solution { // 定义中间位置 int mid = n / 2; - - while (loop > 0) { int i = startX; int j = startY; @@ -182,7 +180,6 @@ class Solution { offset += 2; } - if (n % 2 == 1) { res[mid][mid] = count; } diff --git "a/problems/0102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.md" "b/problems/0102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.md" index b13fdd8df5..8be3ac47f2 100644 --- "a/problems/0102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.md" +++ "b/problems/0102.\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206.md" @@ -34,9 +34,10 @@ 我们之前讲过了三篇关于二叉树的深度优先遍历的文章: -* [二叉树:前中后序递归法](https://mp.weixin.qq.com/s/PwVIfxDlT3kRgMASWAMGhA) -* [二叉树:前中后序迭代法](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg) -* [二叉树:前中后序迭代方式统一写法](https://mp.weixin.qq.com/s/WKg0Ty1_3SZkztpHubZPRg) +* [二叉树:前中后序递归法](https://mp.weixin.qq.com/s/Ww60X5mIKWdMQV4cN3ejOA) +* [二叉树:前中后序迭代法](https://mp.weixin.qq.com/s/OH7aCVJ5-Gi32PkNCoZk4A) +* [二叉树:前中后序迭代方式统一写法](https://mp.weixin.qq.com/s/ATQMPCpBlaAgrqdLDMVPZA) + 接下来我们再来介绍二叉树的另一种遍历方式:层序遍历。 diff --git "a/problems/0129.\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214.md" "b/problems/0129.\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214.md" new file mode 100644 index 0000000000..a54ebf5919 --- /dev/null +++ "b/problems/0129.\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214.md" @@ -0,0 +1,179 @@ + +## 链接 +https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/ + +## 思路 + +本题和[113.路径总和II](https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0113.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8CII.md)是类似的思路,做完这道题,可以顺便把[113.路径总和II](https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0113.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8CII.md) 和 [112.路径总和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0112.路径总和.md) 做了。 + +结合112.路径总和 和 113.路径总和II,我在讲了[二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值?](https://mp.weixin.qq.com/s/6TWAVjxQ34kVqROWgcRFOg),如果大家对二叉树递归函数什么时候需要返回值很迷茫,可以看一下。 + +接下来在看本题,就简单多了,本题其实需要使用回溯,但一些同学可能都不知道自己用了回溯,在[二叉树:以为使用了递归,其实还隐藏着回溯](https://mp.weixin.qq.com/s/ivLkHzWdhjQQD1rQWe6zWA)中,我详细讲解了二叉树的递归中,如何使用了回溯。 + +接下来我们来看题: + +首先思路很明确,就是要遍历整个树把更节点到叶子节点组成的数字相加。 + +那么先按递归三部曲来分析: + +### 递归三部曲 + +如果对递归三部曲不了解的话,可以看这里:[二叉树:前中后递归详解](https://mp.weixin.qq.com/s/PwVIfxDlT3kRgMASWAMGhA) + +* 确定递归函数返回值及其参数 + +这里我们要遍历整个二叉树,且需要要返回值做逻辑处理,所有返回值为void,在[二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值?](https://mp.weixin.qq.com/s/6TWAVjxQ34kVqROWgcRFOg)中,详细讲解了返回值问题。 + +参数只需要把根节点传入,此时还需要定义两个全局遍历,一个是result,记录最终结果,一个是vector path。 + +**为什么用vector类型(就是数组)呢? 因为用vector方便我们做回溯!** + +所以代码如下: + +``` +int result; +vector path; +void traversal(TreeNode* cur) +``` + +* 确定终止条件 + +递归什么时候终止呢? + +当然是遇到叶子节点,此时要收集结果了,通知返回本层递归,因为单条路径的结果使用vector,我们需要一个函数vectorToInt把vector转成int。 + +终止条件代码如下: + +``` +if (!cur->left && !cur->right) { // 遇到了叶子节点 + result += vectorToInt(path); + return; +} +``` + +这里vectorToInt函数就是把数组转成int,代码如下: + +```C++ +int vectorToInt(const vector& vec) { + int sum = 0; + for (int i = 0; i < vec.size(); i++) { + sum = sum * 10 + vec[i]; + } + return sum; +} +``` + + +* 确定递归单层逻辑 + +本题其实采用前中后序都不无所谓, 因为也没有中间几点的处理逻辑。 + +这里主要是当左节点不为空,path收集路径,并递归左孩子,右节点同理。 + +**但别忘了回溯**。 + +如图: + + + + +代码如下: + +```C++ + // 中 +if (cur->left) { // 左 (空节点不遍历) + path.push_back(cur->left->val); + traversal(cur->left); // 递归 + path.pop_back(); // 回溯 +} +if (cur->right) { // 右 (空节点不遍历) + path.push_back(cur->right->val); + traversal(cur->right); // 递归 + path.pop_back(); // 回溯 +} +``` + +这里要注意回溯和递归要永远在一起,一个递归,对应一个回溯,是一对一的关系,有的同学写成如下代码: + +```C++ +if (cur->left) { // 左 (空节点不遍历) + path.push_back(cur->left->val); + traversal(cur->left); // 递归 +} +if (cur->right) { // 右 (空节点不遍历) + path.push_back(cur->right->val); + traversal(cur->right); // 递归 +} +path.pop_back(); // 回溯 +``` +**把回溯放在花括号外面了,世界上最遥远的距离,是你在花括号里,而我在花括号外!** 这就不对了。 + +### 整体C++代码 + +关键逻辑分析完了,整体C++代码如下: + +```C++ +class Solution { +private: + int result; + vector path; + // 把vector转化为int + int vectorToInt(const vector& vec) { + int sum = 0; + for (int i = 0; i < vec.size(); i++) { + sum = sum * 10 + vec[i]; + } + return sum; + } + void traversal(TreeNode* cur) { + if (!cur->left && !cur->right) { // 遇到了叶子节点 + result += vectorToInt(path); + return; + } + + if (cur->left) { // 左 (空节点不遍历) + path.push_back(cur->left->val); // 处理节点 + traversal(cur->left); // 递归 + path.pop_back(); // 回溯,撤销 + } + if (cur->right) { // 右 (空节点不遍历) + path.push_back(cur->right->val); // 处理节点 + traversal(cur->right); // 递归 + path.pop_back(); // 回溯,撤销 + } + return ; + } +public: + int sumNumbers(TreeNode* root) { + path.clear(); + if (root == nullptr) return 0; + path.push_back(root->val); + traversal(root); + return result; + } +}; +``` + +## 总结 + +过于简洁的代码,很容易让初学者忽视了本题中回溯的精髓,甚至作者本身都没有想清楚自己用了回溯。 + +**我这里提供的代码把整个回溯过程充分体现出来,希望可以帮助大家看的明明白白!** + +## 其他语言版本 + +Java: + +Python: + +Go: + +JavaScript: + + + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git "a/problems/0151.\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.md" "b/problems/0151.\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.md" index ffa3446a5c..acdf84fc32 100644 --- "a/problems/0151.\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.md" +++ "b/problems/0151.\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215.md" @@ -300,8 +300,9 @@ class Solution { } ``` +python: -```Python3 +```Python class Solution: #1.去除多余的空格 def trim_spaces(self,s): @@ -349,7 +350,7 @@ class Solution: return ''.join(l) #输出:blue is sky the -''' +``` Go: diff --git "a/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md" "b/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md" index 85b981e516..bcf82b84b8 100644 --- "a/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md" +++ "b/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md" @@ -200,14 +200,6 @@ class MyStack { } } -/** - * Your MyQueue object will be instantiated and called as such: - * MyQueue obj = new MyQueue(); - * obj.push(x); - * int param_2 = obj.pop(); - * int param_3 = obj.peek(); - * boolean param_4 = obj.empty(); - */ ``` 使用两个 Deque 实现 ```java @@ -350,12 +342,6 @@ class MyStack: return False -# Your MyStack object will be instantiated and called as such: -# obj = MyStack() -# obj.push(x) -# param_2 = obj.pop() -# param_3 = obj.top() -# param_4 = obj.empty() ``` Go: diff --git "a/problems/0226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.md" "b/problems/0226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.md" index bb0d6d34ca..bba34766ff 100644 --- "a/problems/0226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.md" +++ "b/problems/0226.\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.md" @@ -7,7 +7,7 @@

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

-## 226.翻转二叉树 +# 226.翻转二叉树 题目地址:https://leetcode-cn.com/problems/invert-binary-tree/ @@ -17,7 +17,7 @@ 这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell,就是因为没在白板上写出翻转二叉树,最后被Google拒绝了。(真假不做判断,权当一个乐子哈) -## 题外话 +# 题外话 这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。 @@ -25,7 +25,7 @@ 如果做过这道题的同学也建议认真看完,相信一定有所收获! -## 思路 +# 思路 我们之前介绍的都是各种方式遍历二叉树,这次要翻转了,感觉还是有点懵逼。 @@ -49,7 +49,9 @@ ## 递归法 -对于二叉树的递归法的前中后序遍历,已经在[二叉树:前中后序递归遍历](https://mp.weixin.qq.com/s/PwVIfxDlT3kRgMASWAMGhA)详细讲解了。 + + +对于二叉树的递归法的前中后序遍历,已经在[二叉树:前中后序递归遍历](https://mp.weixin.qq.com/s/Ww60X5mIKWdMQV4cN3ejOA)详细讲解了。 我们下文以前序遍历为例,通过动画来看一下翻转的过程: @@ -104,7 +106,8 @@ public: ### 深度优先遍历 -[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)中给出了前中后序迭代方式的写法,所以本地可以很轻松的切出如下迭代法的代码: + +[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/OH7aCVJ5-Gi32PkNCoZk4A)中给出了前中后序迭代方式的写法,所以本地可以很轻松的切出如下迭代法的代码: C++代码迭代法(前序遍历) @@ -126,10 +129,10 @@ public: } }; ``` -如果这个代码看不懂的话可以在回顾一下[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)。 +如果这个代码看不懂的话可以在回顾一下[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/OH7aCVJ5-Gi32PkNCoZk4A)。 -我们在[二叉树:前中后序迭代方式的统一写法](https://mp.weixin.qq.com/s/WKg0Ty1_3SZkztpHubZPRg)中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。 +我们在[二叉树:前中后序迭代方式的统一写法](https://mp.weixin.qq.com/s/ATQMPCpBlaAgrqdLDMVPZA)中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。 C++代码如下迭代法(前序遍历) @@ -159,7 +162,7 @@ public: }; ``` -如果上面这个代码看不懂,回顾一下文章[二叉树:前中后序迭代方式的统一写法](https://mp.weixin.qq.com/s/WKg0Ty1_3SZkztpHubZPRg)。 +如果上面这个代码看不懂,回顾一下文章[二叉树:前中后序迭代方式的统一写法](https://mp.weixin.qq.com/s/ATQMPCpBlaAgrqdLDMVPZA)。 ### 广度优先遍历 @@ -185,7 +188,7 @@ public: } }; ``` -如果对以上代码不理解,或者不清楚二叉树的层序遍历,可以看这篇[二叉树:层序遍历登场!](https://mp.weixin.qq.com/s/Gb3BjakIKGNpup2jYtTzog) +如果对以上代码不理解,或者不清楚二叉树的层序遍历,可以看这篇[二叉树:层序遍历登场!](https://mp.weixin.qq.com/s/4-bDKi7SdwfBGRm9FYduiA) ## 总结 @@ -202,7 +205,7 @@ public: ## 其他语言版本 -Java: +### Java: ```Java //DFS递归 @@ -254,9 +257,9 @@ class Solution { } ``` -Python: +### Python -> 递归法:前序遍历 +递归法:前序遍历: ```python class Solution: def invertTree(self, root: TreeNode) -> TreeNode: @@ -268,7 +271,7 @@ class Solution: return root ``` -> 迭代法:深度优先遍历(前序遍历) +迭代法:深度优先遍历(前序遍历): ```python class Solution: def invertTree(self, root: TreeNode) -> TreeNode: @@ -286,7 +289,7 @@ class Solution: return root ``` -> 迭代法:广度优先遍历(层序遍历) +迭代法:广度优先遍历(层序遍历): ```python import collections class Solution: @@ -306,7 +309,8 @@ class Solution: return root ``` -Go: +### Go + ```Go func invertTree(root *TreeNode) *TreeNode { if root ==nil{ @@ -323,7 +327,7 @@ func invertTree(root *TreeNode) *TreeNode { } ``` -JavaScript: +### JavaScript 使用递归版本的前序遍历 ```javascript diff --git "a/problems/0232.\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" "b/problems/0232.\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" index be6e1df6fb..6890fc2bde 100644 --- "a/problems/0232.\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" +++ "b/problems/0232.\347\224\250\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" @@ -385,15 +385,6 @@ func (this *MyQueue) Empty() bool { return len(this.stack) == 0 && len(this.back) == 0 } -/** - * Your MyQueue object will be instantiated and called as such: - * obj := Constructor(); - * obj.Push(x); - * param_2 := obj.Pop(); - * param_3 := obj.Peek(); - * param_4 := obj.Empty(); - */ - ``` javaScript: diff --git "a/problems/0459.\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262.md" "b/problems/0459.\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262.md" index 368489a5e2..f012811d3d 100644 --- "a/problems/0459.\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262.md" +++ "b/problems/0459.\351\207\215\345\244\215\347\232\204\345\255\220\345\255\227\347\254\246\344\270\262.md" @@ -37,7 +37,7 @@ https://leetcode-cn.com/problems/repeated-substring-pattern/ 如果KMP还不够了解,可以看我的B站: -* [帮你把KMP算法学个通透!B站(理论篇)](https://www.bilibili.com/video/BV1PD4y1o7nd/) +* [帮你把KMP算法学个通透!(理论篇)](https://www.bilibili.com/video/BV1PD4y1o7nd/) * [帮你把KMP算法学个通透!(求next数组代码篇)](https://www.bilibili.com/video/BV1M5411j7Xx) diff --git "a/problems/0463.\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277.md" "b/problems/0463.\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277.md" new file mode 100644 index 0000000000..403788547c --- /dev/null +++ "b/problems/0463.\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277.md" @@ -0,0 +1,98 @@ + +## 题目链接 +https://leetcode-cn.com/problems/island-perimeter/ + +## 思路 + +岛屿问题最容易让人想到BFS或者DFS,但是这道题还真的没有必要,别把简单问题搞复杂了。 + +### 解法一: + +遍历每一个空格,遇到岛屿,计算其上下左右的情况,遇到水域或者出界的情况,就可以计算边了。 + +如图: + + + +C++代码如下:(详细注释) + +```C++ +class Solution { +public: + int direction[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; + int islandPerimeter(vector>& grid) { + int result = 0; + for (int i = 0; i < grid.size(); i++) { + for (int j = 0; j < grid[0].size(); j++) { + if (grid[i][j] == 1) { + for (int k = 0; k < 4; k++) { // 上下左右四个方向 + int x = i + direction[k][0]; + int y = j + direction[k][1]; // 计算周边坐标x,y + if (x < 0 // i在边界上 + || x >= grid.size() // i在边界上 + || y < 0 // j在边界上 + || y >= grid[0].size() // j在边界上 + || grid[x][y] == 0) { // x,y位置是水域 + result++; + } + } + } + } + } + return result; + } +}; +``` + +### 解法二: + +计算出总的岛屿数量,因为有一对相邻两个陆地,边的总数就减2,那么在计算出相邻岛屿的数量就可以了。 + +result = 岛屿数量 * 4 - cover * 2; + +如图: + + + +C++代码如下:(详细注释) + +```C++ +class Solution { +public: + int islandPerimeter(vector>& grid) { + int sum = 0; // 陆地数量 + int cover = 0; // 相邻数量 + for (int i = 0; i < grid.size(); i++) { + for (int j = 0; j < grid[0].size(); j++) { + if (grid[i][j] == 1) { + sum++; + // 统计上边相邻陆地 + if(i - 1 >= 0 && grid[i - 1][j] == 1) cover++; + // 统计左边相邻陆地 + if(j - 1 >= 0 && grid[i][j - 1] == 1) cover++; + // 为什么没统计下边和右边? 因为避免重复计算 + } + } + } + return sum * 4 - cover * 2; + } +}; +``` + + +## 其他语言版本 + +Java: + +Python: + +Go: + +JavaScript: + + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git "a/problems/0704.\344\272\214\345\210\206\346\237\245\346\211\276.md" "b/problems/0704.\344\272\214\345\210\206\346\237\245\346\211\276.md" index 931e6e5cea..cce471ae32 100644 --- "a/problems/0704.\344\272\214\345\210\206\346\237\245\346\211\276.md" +++ "b/problems/0704.\344\272\214\345\210\206\346\237\245\346\211\276.md" @@ -139,7 +139,7 @@ public: ## 相关题目推荐 -* [35.搜索插入位置](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q) +* [35.搜索插入位置](./0035.搜索插入位置.md) * 34.在排序数组中查找元素的第一个和最后一个位置 * 69.x 的平方根 * 367.有效的完全平方数 diff --git "a/problems/0707.\350\256\276\350\256\241\351\223\276\350\241\250.md" "b/problems/0707.\350\256\276\350\256\241\351\223\276\350\241\250.md" index b67a36eb7b..8be28f88bc 100644 --- "a/problems/0707.\350\256\276\350\256\241\351\223\276\350\241\250.md" +++ "b/problems/0707.\350\256\276\350\256\241\351\223\276\350\241\250.md" @@ -28,9 +28,9 @@ https://leetcode-cn.com/problems/design-linked-list/ # 思路 -如果对链表的基础知识还不太懂,可以看这篇文章:[关于链表,你该了解这些!](https://mp.weixin.qq.com/s/ntlZbEdKgnFQKZkSUAOSpQ) +如果对链表的基础知识还不太懂,可以看这篇文章:[关于链表,你该了解这些!](https://mp.weixin.qq.com/s/fDGMmLrW7ZHlzkzlf_dZkw) -如果对链表的虚拟头结点不清楚,可以看这篇文章:[链表:听说用虚拟头节点会方便很多?](https://mp.weixin.qq.com/s/slM1CH5Ew9XzK93YOQYSjA) +如果对链表的虚拟头结点不清楚,可以看这篇文章:[链表:听说用虚拟头节点会方便很多?](https://mp.weixin.qq.com/s/L5aanfALdLEwVWGvyXPDqA) 删除链表节点: ![链表-删除节点](https://img-blog.csdnimg.cn/20200806195114541.png) diff --git "a/problems/0941.\346\234\211\346\225\210\347\232\204\345\261\261\350\204\211\346\225\260\347\273\204.md" "b/problems/0941.\346\234\211\346\225\210\347\232\204\345\261\261\350\204\211\346\225\260\347\273\204.md" new file mode 100644 index 0000000000..6dbc3da2f1 --- /dev/null +++ "b/problems/0941.\346\234\211\346\225\210\347\232\204\345\261\261\350\204\211\346\225\260\347\273\204.md" @@ -0,0 +1,43 @@ + +## 题目链接 + +https://leetcode-cn.com/problems/valid-mountain-array/ + +## 思路 + +判断是山峰,主要就是要严格的保存左边到中间,和右边到中间是递增的。 + +这样可以使用两个指针,left和right,让其按照如下规则移动,如图: + + + +**注意这里还是有一些细节,例如如下两点:** + +* 因为left和right是数组下表,移动的过程中注意不要数组越界 +* 如果left或者right没有移动,说明是一个单调递增或者递减的数组,依然不是山峰 + +C++代码如下: + +``` +class Solution { +public: + bool validMountainArray(vector& A) { + if (A.size() < 3) return false; + int left = 0; + int right = A.size() - 1; + + // 注意防止越界 + while (left < A.size() - 1 && A[left] < A[left + 1]) left++; + + // 注意防止越界 + while (right > 0 && A[right] < A[right - 1]) right--; + + // 如果left或者right都在起始位置,说明不是山峰 + if (left == right && left != 0 && right != A.size() - 1) return true; + return false; + } +}; +``` +如果想系统学一学双指针的话, 可以看一下这篇[双指针法:总结篇!](https://mp.weixin.qq.com/s/_p7grwjISfMh0U65uOyCjA) + + diff --git "a/problems/1002.\346\237\245\346\211\276\345\270\270\347\224\250\345\255\227\347\254\246.md" "b/problems/1002.\346\237\245\346\211\276\345\270\270\347\224\250\345\255\227\347\254\246.md" new file mode 100644 index 0000000000..875340c4b8 --- /dev/null +++ "b/problems/1002.\346\237\245\346\211\276\345\270\270\347\224\250\345\255\227\347\254\246.md" @@ -0,0 +1,177 @@ + +

+ + + + +

+

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+ + +# 1002. 查找常用字符 + +https://leetcode-cn.com/problems/find-common-characters/ + +给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。 + +你可以按任意顺序返回答案。 + +【示例一】 +输入:["bella","label","roller"] +输出:["e","l","l"] + +【示例二】 +输入:["cool","lock","cook"] +输出:["c","o"] +  + +# 思路 + +这道题意一起就有点绕,不是那么容易懂,其实就是26个小写字符中有字符 在所有字符串里都出现的话,就输出,重复的也算。 + +例如: + +输入:["ll","ll","ll"] +输出:["l","l"] + +这道题目一眼看上去,就是用哈希法,**“小写字符”,“出现频率”, 这些关键字都是为哈希法量身定做的啊** + +首先可以想到的是暴力解法,一个字符串一个字符串去搜,时间复杂度是O(n^m),n是字符串长度,m是有几个字符串。 + +可以看出这是指数级别的时间复杂度,非常高,而且代码实现也不容易,因为要统计 重复的字符,还要适当的替换或者去重。 + +那我们还是哈希法吧。如果对哈希法不了解,可以看这篇:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/RSUANESA_tkhKhYe3ZR8Jg)。 + +如果对用数组来做哈希法不了解的话,可以看这篇:[把数组当做哈希表来用,很巧妙!](https://mp.weixin.qq.com/s/ffS8jaVFNUWyfn_8T31IdA)。 + +了解了哈希法,理解了数组在哈希法中的应用之后,可以来看解题思路了。 + +整体思路就是统计出搜索字符串里26个字符的出现的频率,然后取每个字符频率最小值,最后转成输出格式就可以了。 + +如图: + +![1002.查找常用字符](https://code-thinking.cdn.bcebos.com/pics/1002.查找常用字符.png) + +先统计第一个字符串所有字符出现的次数,代码如下: + +``` +int hash[26] = {0}; // 用来统计所有字符串里字符出现的最小频率 +for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化 + hash[A[0][i] - 'a']++; +} +``` + +接下来,把其他字符串里字符的出现次数也统计出来一次放在hashOtherStr中。 + +然后hash 和 hashOtherStr 取最小值,这是本题关键所在,此时取最小值,就是 一个字符在所有字符串里出现的最小次数了。 + +代码如下: + +``` +int hashOtherStr[26] = {0}; // 统计除第一个字符串外字符的出现频率 +for (int i = 1; i < A.size(); i++) { + memset(hashOtherStr, 0, 26 * sizeof(int)); + for (int j = 0; j < A[i].size(); j++) { + hashOtherStr[A[i][j] - 'a']++; + } + // 这是关键所在 + for (int k = 0; k < 26; k++) { // 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数 + hash[k] = min(hash[k], hashOtherStr[k]); + } +} +``` +此时hash里统计着字符在所有字符串里出现的最小次数,那么把hash转正题目要求的输出格式就可以了。 + +代码如下: + +``` +// 将hash统计的字符次数,转成输出形式 +for (int i = 0; i < 26; i++) { + while (hash[i] != 0) { // 注意这里是while,多个重复的字符 + string s(1, i + 'a'); // char -> string + result.push_back(s); + hash[i]--; + } +} +``` + +整体C++代码如下: + +```C++ +class Solution { +public: + vector commonChars(vector& A) { + vector result; + if (A.size() == 0) return result; + int hash[26] = {0}; // 用来统计所有字符串里字符出现的最小频率 + for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化 + hash[A[0][i] - 'a']++; + } + + int hashOtherStr[26] = {0}; // 统计除第一个字符串外字符的出现频率 + for (int i = 1; i < A.size(); i++) { + memset(hashOtherStr, 0, 26 * sizeof(int)); + for (int j = 0; j < A[i].size(); j++) { + hashOtherStr[A[i][j] - 'a']++; + } + // 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数 + for (int k = 0; k < 26; k++) { + hash[k] = min(hash[k], hashOtherStr[k]); + } + } + // 将hash统计的字符次数,转成输出形式 + for (int i = 0; i < 26; i++) { + while (hash[i] != 0) { // 注意这里是while,多个重复的字符 + string s(1, i + 'a'); // char -> string + result.push_back(s); + hash[i]--; + } + } + + return result; + } +}; +``` + +## 其他语言版本 + +Java: + +```Java +class Solution { + public List commonChars(String[] A) { + List result = new ArrayList<>(); + if (A.length == 0) return result; + int[] hash= new int[26]; // 用来统计所有字符串里字符出现的最小频率 + for (int i = 0; i < A[0].length(); i++) { // 用第一个字符串给hash初始化 + hash[A[0].charAt(i)- 'a']++; + } + // 统计除第一个字符串外字符的出现频率 + for (int i = 1; i < A.length; i++) { + int[] hashOtherStr= new int[26]; + for (int j = 0; j < A[i].length(); j++) { + hashOtherStr[A[i].charAt(j)- 'a']++; + } + // 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数 + for (int k = 0; k < 26; k++) { + hash[k] = Math.min(hash[k], hashOtherStr[k]); + } + } + // 将hash统计的字符次数,转成输出形式 + for (int i = 0; i < 26; i++) { + while (hash[i] != 0) { // 注意这里是while,多个重复的字符 + char c= (char) (i+'a'); + result.add(String.valueOf(c)); + hash[i]--; + } + } + return result; + } +} +``` + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git "a/problems/1356.\346\240\271\346\215\256\346\225\260\345\255\227\344\272\214\350\277\233\345\210\266\344\270\2131\347\232\204\346\225\260\347\233\256\346\216\222\345\272\217.md" "b/problems/1356.\346\240\271\346\215\256\346\225\260\345\255\227\344\272\214\350\277\233\345\210\266\344\270\2131\347\232\204\346\225\260\347\233\256\346\216\222\345\272\217.md" new file mode 100644 index 0000000000..e8aee05593 --- /dev/null +++ "b/problems/1356.\346\240\271\346\215\256\346\225\260\345\255\227\344\272\214\350\277\233\345\210\266\344\270\2131\347\232\204\346\225\260\347\233\256\346\216\222\345\272\217.md" @@ -0,0 +1,89 @@ + +## 题目链接 +https://leetcode-cn.com/problems/sort-integers-by-the-number-of-1-bits/ + +## 思路 + +这道题其实是考察如何计算一个数的二进制中1的数量。 + +我提供两种方法: + +* 方法一: + +朴实无华挨个计算1的数量,最多就是循环n的二进制位数,32位。 + +```C++ +int bitCount(int n) { + int count = 0; // 计数器 + while (n > 0) { + if((n & 1) == 1) count++; // 当前位是1,count++ + n >>= 1 ; // n向右移位 + } + return count; +} +``` + +* 方法二 + +这种方法,只循环n的二进制中1的个数次,比方法一高效的多 + +```C++ +int bitCount(int n) { + int count = 0; + while (n) { + n &= (n - 1); // 清除最低位的1 + count++; + } + return count; +} +``` +以计算12的二进制1的数量为例,如图所示: + + + +下面我就使用方法二,来做这道题目: + +## C++代码 + +```C++ +class Solution { +private: + static int bitCount(int n) { // 计算n的二进制中1的数量 + int count = 0; + while(n) { + n &= (n -1); // 清除最低位的1 + count++; + } + return count; + } + static bool cmp(int a, int b) { + int bitA = bitCount(a); + int bitB = bitCount(b); + if (bitA == bitB) return a < b; // 如果bit中1数量相同,比较数值大小 + return bitA < bitB; // 否则比较bit中1数量大小 + } +public: + vector sortByBits(vector& arr) { + sort(arr.begin(), arr.end(), cmp); + return arr; + } +}; +``` + +## 其他语言版本 + +Java: + +Python: + +Go: + +JavaScript: + + + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git "a/problems/\344\272\214\345\217\211\346\240\221\347\232\204\347\273\237\344\270\200\350\277\255\344\273\243\346\263\225.md" "b/problems/\344\272\214\345\217\211\346\240\221\347\232\204\347\273\237\344\270\200\350\277\255\344\273\243\346\263\225.md" index 533bdfe7ec..9e24fef6fd 100644 --- "a/problems/\344\272\214\345\217\211\346\240\221\347\232\204\347\273\237\344\270\200\350\277\255\344\273\243\346\263\225.md" +++ "b/problems/\344\272\214\345\217\211\346\240\221\347\232\204\347\273\237\344\270\200\350\277\255\344\273\243\346\263\225.md" @@ -12,9 +12,9 @@ > 统一写法是一种什么感觉 -此时我们在[二叉树:一入递归深似海,从此offer是路人](https://mp.weixin.qq.com/s/PwVIfxDlT3kRgMASWAMGhA)中用递归的方式,实现了二叉树前中后序的遍历。 +此时我们在[二叉树:一入递归深似海,从此offer是路人](https://mp.weixin.qq.com/s/Ww60X5mIKWdMQV4cN3ejOA)中用递归的方式,实现了二叉树前中后序的遍历。 -在[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)中用栈实现了二叉树前后中序的迭代遍历(非递归)。 +在[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/OH7aCVJ5-Gi32PkNCoZk4A)中用栈实现了二叉树前后中序的迭代遍历(非递归)。 之后我们发现**迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。** @@ -24,7 +24,7 @@ **重头戏来了,接下来介绍一下统一写法。** -我们以中序遍历为例,在[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)中提到说使用栈的话,**无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况**。 +我们以中序遍历为例,在[二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/OH7aCVJ5-Gi32PkNCoZk4A)中提到说使用栈的话,**无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况**。 **那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。** @@ -149,14 +149,13 @@ public: -## 其他语言版本 +# 其他语言版本 Java: - 迭代法前序遍历代码如下: - ```java - class Solution { - +迭代法前序遍历代码如下: +```java +class Solution { public List preorderTraversal(TreeNode root) { List result = new LinkedList<>(); Stack st = new Stack<>(); @@ -180,39 +179,39 @@ Java: return result; } } +``` - ``` - 迭代法中序遍历代码如下: - ```java - class Solution { - public List inorderTraversal(TreeNode root) { - List result = new LinkedList<>(); - Stack st = new Stack<>(); - if (root != null) st.push(root); - while (!st.empty()) { - TreeNode node = st.peek(); - if (node != null) { - st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中 - if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈) - st.push(node); // 添加中节点 - st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。 - - if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈) - } else { // 只有遇到空节点的时候,才将下一个节点放进结果集 - st.pop(); // 将空节点弹出 - node = st.peek(); // 重新取出栈中元素 - st.pop(); - result.add(node.val); // 加入到结果集 - } +迭代法中序遍历代码如下: +```java +class Solution { +public List inorderTraversal(TreeNode root) { + List result = new LinkedList<>(); + Stack st = new Stack<>(); + if (root != null) st.push(root); + while (!st.empty()) { + TreeNode node = st.peek(); + if (node != null) { + st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中 + if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈) + st.push(node); // 添加中节点 + st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。 + + if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈) + } else { // 只有遇到空节点的时候,才将下一个节点放进结果集 + st.pop(); // 将空节点弹出 + node = st.peek(); // 重新取出栈中元素 + st.pop(); + result.add(node.val); // 加入到结果集 } - return result; } + return result; +} } - ``` - 迭代法后序遍历代码如下: - ```java - class Solution { +``` +迭代法后序遍历代码如下: +```java +class Solution { public List postorderTraversal(TreeNode root) { List result = new LinkedList<>(); Stack st = new Stack<>(); @@ -236,11 +235,11 @@ Java: return result; } } +``` - ``` Python: -> 迭代法前序遍历 +迭代法前序遍历: ```python class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: @@ -263,7 +262,7 @@ class Solution: return result ``` -> 迭代法中序遍历 +迭代法中序遍历: ```python class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: @@ -288,7 +287,7 @@ class Solution: return result ``` -> 迭代法后序遍历 +迭代法后序遍历: ```python class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: diff --git "a/problems/\344\272\214\345\217\211\346\240\221\347\232\204\350\277\255\344\273\243\351\201\215\345\216\206.md" "b/problems/\344\272\214\345\217\211\346\240\221\347\232\204\350\277\255\344\273\243\351\201\215\345\216\206.md" index 30b921ff4b..20397773e3 100644 --- "a/problems/\344\272\214\345\217\211\346\240\221\347\232\204\350\277\255\344\273\243\351\201\215\345\216\206.md" +++ "b/problems/\344\272\214\345\217\211\346\240\221\347\232\204\350\277\255\344\273\243\351\201\215\345\216\206.md" @@ -19,7 +19,7 @@ 为什么可以用迭代法(非递归的方式)来实现二叉树的前后中序遍历呢? -我们在[栈与队列:匹配问题都是栈的强项](https://mp.weixin.qq.com/s/eynAEbUbZoAWrk0ZlEugqg)中提到了,**递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中**,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。 +我们在[栈与队列:匹配问题都是栈的强项](https://mp.weixin.qq.com/s/1-x6r1wGA9mqIHW5LrMvBg)中提到了,**递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中**,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。 此时大家应该知道我们用栈也可以是实现二叉树的前后中序遍历了。 @@ -138,7 +138,7 @@ public: ``` -## 总结 +# 总结 此时我们用迭代法写出了二叉树的前后中序遍历,大家可以看出前序和中序是完全两种代码风格,并不想递归写法那样代码稍做调整,就可以实现前后中序。 @@ -153,7 +153,7 @@ public: -## 其他语言版本 +# 其他语言版本 Java: @@ -233,7 +233,8 @@ class Solution { Python: -```python3 + +```python # 前序遍历-迭代-LC144_二叉树的前序遍历 class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: diff --git "a/problems/\345\211\215\345\272\217/\345\205\263\344\272\216\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\357\274\214\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204\351\203\275\345\234\250\350\277\231\351\207\214\357\274\201.md" "b/problems/\345\211\215\345\272\217/\345\205\263\344\272\216\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\357\274\214\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204\351\203\275\345\234\250\350\277\231\351\207\214\357\274\201.md" index 4ca9eedeb1..d6471b9929 100644 --- "a/problems/\345\211\215\345\272\217/\345\205\263\344\272\216\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\357\274\214\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204\351\203\275\345\234\250\350\277\231\351\207\214\357\274\201.md" +++ "b/problems/\345\211\215\345\272\217/\345\205\263\344\272\216\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\357\274\214\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204\351\203\275\345\234\250\350\277\231\351\207\214\357\274\201.md" @@ -7,12 +7,19 @@

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+相信每一位录友都接触过时间复杂度,但又对时间复杂度的认识处于一种朦胧的状态,所以是时候对时间复杂度来一个深度的剖析了。 -Carl大胆断言:这可能是你见过对时间复杂度分析最通透的一篇文章了。 +本篇从如下六点进行分析: -相信每一位录友都接触过时间复杂度,「代码随想录」已经也讲了一百多道经典题目了,是时候对时间复杂度来一个深度的剖析了,很早之前就写过一篇,当时文章还没有人看,Carl感觉有价值的东西值得让更多的人看到,哈哈。 +* 究竟什么是时间复杂度 +* 什么是大O +* 不同数据规模的差异 +* 复杂表达式的化简 +* O(logn)中的log是以什么为底? +* 举一个例子 -所以重新整理的时间复杂度文章,正式和大家见面啦! + +这可能是你见过对时间复杂度分析最通透的一篇文章。 ## 究竟什么是时间复杂度 @@ -151,7 +158,7 @@ O(2 * n^2 + 10 * n + 1000) < O(3 * n^2),所以说最后省略掉常数项系 **当然这不是这道题目的最优解,我仅仅是用这道题目来讲解一下时间复杂度**。 -# 总结 +## 总结 本篇讲解了什么是时间复杂度,复杂度是用来干什么,以及数据规模对时间复杂度的影响。 @@ -161,12 +168,6 @@ O(2 * n^2 + 10 * n + 1000) < O(3 * n^2),所以说最后省略掉常数项系 相信看完本篇,大家对时间复杂度的认识会深刻很多! -如果感觉「代码随想录」很不错,赶快推荐给身边的朋友同学们吧,他们发现和「代码随想录」相见恨晚! - - - - - ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git "a/problems/\345\211\221\346\214\207Offer58-II.\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262.md" "b/problems/\345\211\221\346\214\207Offer58-II.\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262.md" index 1701086e45..3c3eaef0a4 100644 --- "a/problems/\345\211\221\346\214\207Offer58-II.\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262.md" +++ "b/problems/\345\211\221\346\214\207Offer58-II.\345\267\246\346\227\213\350\275\254\345\255\227\347\254\246\344\270\262.md" @@ -118,6 +118,8 @@ class Solution { } ``` +python: + ```python # 方法一:可以使用切片方法 class Solution: