From 5e0cb67b8a18debf47d788ce41fd949736390998 Mon Sep 17 00:00:00 2001 From: ironartisan Date: Tue, 10 Aug 2021 20:28:49 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A00116.=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E6=AF=8F=E4=B8=AA=E8=8A=82=E7=82=B9=E7=9A=84=E4=B8=8B=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=8F=B3=E4=BE=A7=E8=8A=82=E7=82=B9=E6=8C=87=E9=92=88?= =?UTF-8?q?java=E5=92=8Cpython3=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...个节点的下一个右侧节点指针.md | 88 ++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/problems/0116.填充每个节点的下一个右侧节点指针.md b/problems/0116.填充每个节点的下一个右侧节点指针.md index 6feb1ca9..b139067d 100644 --- a/problems/0116.填充每个节点的下一个右侧节点指针.md +++ b/problems/0116.填充每个节点的下一个右侧节点指针.md @@ -130,15 +130,97 @@ public: ## Java ```java - +// 递归法 +class Solution { + public void traversal(Node cur) { + if(cur == null) return; + if(cur.left != null) cur.left.next = cur.right; + if(cur.right != null){ + if(cur.next != null) cur.right.next = cur.next.left; + else cur.right.next = null; + } + traversal(cur.left); + traversal(cur.right); + } + public Node connect(Node root) { + traversal(root); + return root; + } +} +``` +```java +// 迭代法 +class Solution { + public Node connect(Node root) { + if(root == null) return root; + Queue que = new LinkedList(); + que.offer(root); + Node nodePre = null; + Node node = null; + while(!que.isEmpty()){ + int size = que.size(); + for(int i=0; i 'Node': + def traversal(cur: 'Node') -> 'Node': + if not cur: return [] + if cur.left: cur.left.next = cur.right # 操作1 + if cur.right: + if cur.next: + cur.right.next = cur.next.left # 操作2 + else: + cur.right.next = None + traversal(cur.left) # 左 + traversal(cur.right) # 右 + traversal(root) + return root +``` +```python +# 迭代法 +class Solution: + def connect(self, root: 'Node') -> 'Node': + if not root: return + res = [] + queue = [root] + while queue: + size = len(queue) + for i in range(size): # 开始每一层的遍历 + if i==0: + nodePre = queue.pop(0) # 记录一层的头结点 + node = nodePre + else: + node = queue.pop(0) + nodePre.next = node # 本层前一个节点next指向本节点 + nodePre = nodePre.next + if node.left: queue.append(node.left) + if node.right: queue.append(node.right) + nodePre.next = None # 本层最后一个节点指向None + return root ``` - ## Go ```go From 1f393f5ddea9ff15db6a5100ee53a09be678a295 Mon Sep 17 00:00:00 2001 From: youngyangyang04 <826123027@qq.com> Date: Tue, 10 Aug 2021 22:20:48 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改98.验证二叉搜索树中的语法错误表述 (应为:节点10大于左节点5,小于右节点15) --- problems/0005.最长回文子串.md | 12 +++++----- problems/0015.三数之和.md | 4 ++-- problems/0018.四数之和.md | 2 +- ...0019.删除链表的倒数第N个节点.md | 2 +- problems/0020.有效的括号.md | 2 +- .../0024.两两交换链表中的节点.md | 2 +- problems/0027.移除元素.md | 4 ++-- problems/0028.实现strStr.md | 12 +++++----- problems/0031.下一个排列.md | 2 +- ...元素的第一个和最后一个位置.md | 6 ++--- problems/0035.搜索插入位置.md | 4 ++-- problems/0037.解数独.md | 6 ++--- problems/0039.组合总和.md | 10 ++++---- problems/0040.组合总和II.md | 10 ++++---- problems/0042.接雨水.md | 16 ++++++------- problems/0045.跳跃游戏II.md | 4 ++-- problems/0046.全排列.md | 2 +- problems/0051.N皇后.md | 2 +- problems/0053.最大子序和.md | 6 ++--- .../0053.最大子序和(动态规划).md | 2 +- problems/0055.跳跃游戏.md | 2 +- problems/0056.合并区间.md | 4 ++-- problems/0059.螺旋矩阵II.md | 2 +- problems/0062.不同路径.md | 10 ++++---- problems/0063.不同路径II.md | 6 ++--- problems/0070.爬楼梯.md | 6 ++--- problems/0072.编辑距离.md | 8 +++---- problems/0077.组合.md | 4 ++-- problems/0078.子集.md | 2 +- problems/0084.柱状图中最大的矩形.md | 8 +++---- problems/0090.子集II.md | 2 +- problems/0093.复原IP地址.md | 2 +- problems/0096.不同的二叉搜索树.md | 4 ++-- problems/0098.验证二叉搜索树.md | 12 +++++----- problems/0100.相同的树.md | 10 ++++---- problems/0101.对称二叉树.md | 12 +++++----- problems/0102.二叉树的层序遍历.md | 20 ++++++++-------- ...序与后序遍历序列构造二叉树.md | 14 +++++------ ...将有序数组转换为二叉搜索树.md | 4 ++-- problems/0110.平衡二叉树.md | 18 +++++++------- problems/0111.二叉树的最小深度.md | 8 +++---- problems/0112.路径总和.md | 12 +++++----- problems/0115.不同的子序列.md | 6 ++--- ...个节点的下一个右侧节点指针.md | 6 ++--- problems/0121.买卖股票的最佳时机.md | 8 +++---- .../0122.买卖股票的最佳时机II.md | 4 ++-- ...票的最佳时机II(动态规划).md | 4 ++-- .../0123.买卖股票的最佳时机III.md | 4 ++-- .../0129.求根到叶子节点数字之和.md | 8 +++---- problems/0131.分割回文串.md | 12 +++++----- problems/0132.分割回文串II.md | 10 ++++---- problems/0134.加油站.md | 6 ++--- problems/0135.分发糖果.md | 6 ++--- problems/0139.单词拆分.md | 6 ++--- problems/0141.环形链表.md | 2 +- problems/0142.环形链表II.md | 2 +- problems/0143.重排链表.md | 6 ++--- problems/0150.逆波兰表达式求值.md | 2 +- problems/0151.翻转字符串里的单词.md | 6 ++--- .../0188.买卖股票的最佳时机IV.md | 6 ++--- problems/0189.旋转数组.md | 2 +- problems/0198.打家劫舍.md | 6 ++--- problems/0202.快乐数.md | 2 +- problems/0203.移除链表元素.md | 4 ++-- problems/0205.同构字符串.md | 2 +- problems/0206.翻转链表.md | 4 ++-- problems/0209.长度最小的子数组.md | 4 ++-- problems/0213.打家劫舍II.md | 2 +- problems/0216.组合总和III.md | 6 ++--- .../0222.完全二叉树的节点个数.md | 8 +++---- problems/0225.用队列实现栈.md | 4 ++-- problems/0226.翻转二叉树.md | 12 +++++----- problems/0232.用栈实现队列.md | 2 +- problems/0234.回文链表.md | 6 ++--- ...35.二叉搜索树的最近公共祖先.md | 8 +++---- .../0236.二叉树的最近公共祖先.md | 6 ++--- problems/0239.滑动窗口最大值.md | 4 ++-- problems/0242.有效的字母异位词.md | 2 +- problems/0257.二叉树的所有路径.md | 20 ++++++++-------- problems/0279.完全平方数.md | 6 ++--- problems/0283.移动零.md | 2 +- problems/0300.最长上升子序列.md | 4 ++-- ...09.最佳买卖股票时机含冷冻期.md | 4 ++-- problems/0322.零钱兑换.md | 4 ++-- problems/0332.重新安排行程.md | 4 ++-- problems/0337.打家劫舍III.md | 12 +++++----- problems/0343.整数拆分.md | 6 ++--- problems/0344.反转字符串.md | 8 +++---- problems/0347.前K个高频元素.md | 2 +- problems/0349.两个数组的交集.md | 2 +- problems/0376.摆动序列.md | 2 +- problems/0377.组合总和Ⅳ.md | 2 +- problems/0383.赎金信.md | 4 ++-- problems/0392.判断子序列.md | 2 +- problems/0404.左叶子之和.md | 8 +++---- problems/0406.根据身高重建队列.md | 4 ++-- problems/0416.分割等和子集.md | 6 ++--- problems/0435.无重叠区间.md | 4 ++-- .../0450.删除二叉搜索树中的节点.md | 8 +++---- .../0452.用最少数量的箭引爆气球.md | 2 +- problems/0454.四数相加II.md | 2 +- problems/0455.分发饼干.md | 4 ++-- problems/0459.重复的子字符串.md | 4 ++-- problems/0463.岛屿的周长.md | 4 ++-- problems/0474.一和零.md | 4 ++-- problems/0491.递增子序列.md | 4 ++-- problems/0494.目标和.md | 6 ++--- problems/0496.下一个更大元素I.md | 8 +++---- problems/0501.二叉搜索树中的众数.md | 12 +++++----- problems/0503.下一个更大元素II.md | 4 ++-- problems/0509.斐波那契数.md | 6 ++--- problems/0513.找树左下角的值.md | 12 +++++----- problems/0516.最长回文子序列.md | 8 +++---- problems/0518.零钱兑换II.md | 4 ++-- .../0530.二叉搜索树的最小绝对差.md | 6 ++--- ...38.把二叉搜索树转换为累加树.md | 4 ++-- problems/0541.反转字符串II.md | 4 ++-- .../0583.两个字符串的删除操作.md | 4 ++-- problems/0617.合并二叉树.md | 12 +++++----- problems/0647.回文子串.md | 10 ++++---- problems/0649.Dota2参议院.md | 2 +- problems/0654.最大二叉树.md | 6 ++--- problems/0657.机器人能否返回原点.md | 2 +- problems/0669.修剪二叉搜索树.md | 8 +++---- .../0673.最长递增子序列的个数.md | 12 +++++----- problems/0674.最长连续递增序列.md | 6 ++--- problems/0684.冗余连接.md | 4 ++-- problems/0685.冗余连接II.md | 6 ++--- problems/0700.二叉搜索树中的搜索.md | 4 ++-- .../0701.二叉搜索树中的插入操作.md | 6 ++--- problems/0704.二分查找.md | 4 ++-- problems/0707.设计链表.md | 2 +- ...买卖股票的最佳时机含手续费.md | 6 ++--- ...佳时机含手续费(动态规划).md | 2 +- problems/0718.最长重复子数组.md | 6 ++--- problems/0724.寻找数组的中心索引.md | 2 +- problems/0738.单调递增的数字.md | 4 ++-- problems/0739.每日温度.md | 4 ++-- problems/0746.使用最小花费爬楼梯.md | 6 ++--- problems/0763.划分字母区间.md | 2 +- problems/0841.钥匙和房间.md | 4 ++-- problems/0844.比较含退格的字符串.md | 6 ++--- problems/0860.柠檬水找零.md | 2 +- problems/0922.按奇偶排序数组II.md | 6 ++--- problems/0925.长按键入.md | 2 +- problems/0968.监控二叉树.md | 4 ++-- problems/0977.有序数组的平方.md | 4 ++-- problems/1002.查找常用字符.md | 2 +- ...1005.K次取反后最大化的数组和.md | 2 +- problems/1035.不相交的线.md | 2 +- ...除字符串中的所有相邻重复项.md | 4 ++-- .../1049.最后一块石头的重量II.md | 4 ++-- problems/1143.最长公共子序列.md | 4 ++-- problems/1207.独一无二的出现次数.md | 2 +- ...据数字二进制下1的数目排序.md | 6 ++--- ...65.有多少小于当前数字的数字.md | 6 ++--- problems/1382.将二叉搜索树变平衡.md | 2 +- ...时了,此时的n究竟是多大?.md | 10 ++++---- ...编辑距离,卡尔做了三步铺垫.md | 6 ++--- problems/二叉树中递归带着回溯.md | 10 ++++---- problems/二叉树的统一迭代法.md | 6 ++--- problems/二叉树的迭代遍历.md | 6 ++--- problems/二叉树的递归遍历.md | 6 ++--- ...时了,此时的n究竟是多大?.md | 10 ++++---- ...代码模式,什么又是ACM模式?.md | 8 +++---- problems/前序/代码风格.md | 2 +- ...间复杂度,可能有几个疑问?.md | 4 ++-- ...了解自己代码的内存消耗么?.md | 2 +- ...上的代码想在本地编译运行?.md | 2 +- ...算法的时间与空间复杂度分析.md | 14 +++++------ ...一讲递归算法的时间复杂度!.md | 10 ++++---- problems/剑指Offer05.替换空格.md | 2 +- .../剑指Offer58-II.左旋转字符串.md | 2 +- .../动态规划-股票问题总结篇.md | 24 +++++++++---------- .../20200927二叉树周末总结.md | 8 +++---- .../20201003二叉树周末总结.md | 14 +++++------ .../周总结/20201224贪心周末总结.md | 2 +- .../周总结/20210107动规周末总结.md | 6 ++--- .../周总结/20210121动规周末总结.md | 6 ++--- .../周总结/20210128动规周末总结.md | 2 +- .../周总结/20210204动规周末总结.md | 12 +++++----- .../周总结/20210225动规周末总结.md | 16 ++++++------- .../周总结/20210304动规周末总结.md | 4 ++-- .../二叉树阶段总结系列一.md | 12 +++++----- ...溯算法去重问题的另一种写法.md | 10 ++++---- problems/数组理论基础.md | 2 +- ...高重建队列(vector原理讲解).md | 6 ++--- problems/背包理论基础01背包-1.md | 2 +- problems/背包理论基础01背包-2.md | 2 +- .../背包问题理论基础多重背包.md | 4 ++-- .../背包问题理论基础完全背包.md | 8 +++---- problems/面试题02.07.链表相交.md | 2 +- 192 files changed, 552 insertions(+), 552 deletions(-) diff --git a/problems/0005.最长回文子串.md b/problems/0005.最长回文子串.md index def649a7..0f4cb2f6 100644 --- a/problems/0005.最长回文子串.md +++ b/problems/0005.最长回文子串.md @@ -67,7 +67,7 @@ 以上三种情况分析完了,那么递归公式如下: -```C++ +```CPP if (s[i] == s[j]) { if (j - i <= 1) { // 情况一 和 情况二 dp[i][j] = true; @@ -81,7 +81,7 @@ if (s[i] == s[j]) { 在得到[i,j]区间是否是回文子串的时候,直接保存最长回文子串的左边界和右边界,代码如下: -```C++ +```CPP if (s[i] == s[j]) { if (j - i <= 1) { // 情况一 和 情况二 dp[i][j] = true; @@ -120,7 +120,7 @@ dp[i + 1][j - 1] 在 dp[i][j]的左下角,如图: 代码如下: -```C++ +```CPP for (int i = s.size() - 1; i >= 0; i--) { // 注意遍历顺序 for (int j = i; j < s.size(); j++) { if (s[i] == s[j]) { @@ -150,7 +150,7 @@ for (int i = s.size() - 1; i >= 0; i--) { // 注意遍历顺序 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: string longestPalindrome(string s) { @@ -181,7 +181,7 @@ public: ``` 以上代码是为了凸显情况一二三,当然是可以简洁一下的,如下: -```C++ +```CPP class Solution { public: string longestPalindrome(string s) { @@ -226,7 +226,7 @@ public: **这两种情况可以放在一起计算,但分别计算思路更清晰,我倾向于分别计算**,代码如下: -```C++ +```CPP class Solution { public: int left = 0; diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index b4cdbd1e..9a3a8d5b 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -46,7 +46,7 @@ https://leetcode-cn.com/problems/3sum/ 大家可以尝试使用哈希法写一写,就知道其困难的程度了。 哈希法C++代码: -```C++ +```CPP class Solution { public: vector> threeSum(vector& nums) { @@ -107,7 +107,7 @@ public: C++代码代码如下: -```C++ +```CPP class Solution { public: vector> threeSum(vector& nums) { diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 1958b188..75cd9e8e 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -67,7 +67,7 @@ https://leetcode-cn.com/problems/4sum/ C++代码 -```C++ +```CPP class Solution { public: vector> fourSum(vector& nums, int target) { diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index 02939249..3e1a682c 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -58,7 +58,7 @@ 此时不难写出如下C++代码: -```C++ +```CPP class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index 39358bef..a26aa308 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -108,7 +108,7 @@ cd a/b/c/../../ 实现C++代码如下: -```C++ +```CPP class Solution { public: bool isValid(string s) { diff --git a/problems/0024.两两交换链表中的节点.md b/problems/0024.两两交换链表中的节点.md index 0047d186..91e566dd 100644 --- a/problems/0024.两两交换链表中的节点.md +++ b/problems/0024.两两交换链表中的节点.md @@ -43,7 +43,7 @@ https://leetcode-cn.com/problems/swap-nodes-in-pairs/ 对应的C++代码实现如下: (注释中详细和如上图中的三步做对应) -```C++ +```CPP class Solution { public: ListNode* swapPairs(ListNode* head) { diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index ecf91d41..3819d6a5 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -48,7 +48,7 @@ 代码如下: -```C++ +```CPP // 时间复杂度:O(n^2) // 空间复杂度:O(1) class Solution { @@ -85,7 +85,7 @@ public: 后序都会一一介绍到,本题代码如下: -```C++ +```CPP // 时间复杂度:O(n) // 空间复杂度:O(1) class Solution { diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index dadee4ff..4fb418f0 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -315,7 +315,7 @@ next[i] = j; 最后整体构建next数组的函数代码如下: -```C++ +```CPP void getNext(int* next, const string& s){     int j = -1;     next[0] = j; @@ -386,7 +386,7 @@ if (j == (t.size() - 1) ) { 那么使用next数组,用模式串匹配文本串的整体代码如下: -```C++ +```CPP int j = -1; // 因为next数组里记录的起始位置为-1 for (int i = 0; i < s.size(); i++) { // 注意i就从0开始     while(j >= 0 && s[i] != t[j + 1]) { // 不匹配 @@ -405,7 +405,7 @@ for (int i = 0; i < s.size(); i++) { // 注意i就从0开始 # 前缀表统一减一 C++代码实现 -```C++ +```CPP class Solution { public:     void getNext(int* next, const string& s) { @@ -457,7 +457,7 @@ public: 我给出的getNext的实现为:(前缀表统一减一) -```C++ +```CPP void getNext(int* next, const string& s) {     int j = -1;     next[0] = j; @@ -479,7 +479,7 @@ void getNext(int* next, const string& s) { 那么前缀表不减一来构建next数组,代码如下: -```C++ +```CPP void getNext(int* next, const string& s) { int j = 0; next[0] = 0; @@ -502,7 +502,7 @@ void getNext(int* next, const string& s) { 实现代码如下: -```C++ +```CPP class Solution { public: void getNext(int* next, const string& s) { diff --git a/problems/0031.下一个排列.md b/problems/0031.下一个排列.md index 5edc7321..10ac9df4 100644 --- a/problems/0031.下一个排列.md +++ b/problems/0031.下一个排列.md @@ -75,7 +75,7 @@ 对应的C++代码如下: -```C++ +```CPP class Solution { public: void nextPermutation(vector& nums) { diff --git a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md index 2a31994d..f83de1a8 100644 --- a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md +++ b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md @@ -64,7 +64,7 @@ 可以写出如下代码 -```C++ +```CPP // 二分查找,寻找target的右边界(不包括target) // 如果rightBorder为没有被赋值(即target在数组范围的左边,例如数组[3,3],target为2),为了处理情况一 int getRightBorder(vector& nums, int target) { @@ -86,7 +86,7 @@ int getRightBorder(vector& nums, int target) { ## 寻找左边界 -```C++ +```CPP // 二分查找,寻找target的左边界leftBorder(不包括target) // 如果leftBorder没有被赋值(即target在数组范围的右边,例如数组[3,3],target为4),为了处理情况一 int getLeftBorder(vector& nums, int target) { @@ -110,7 +110,7 @@ int getLeftBorder(vector& nums, int target) { 左右边界计算完之后,看一下主体代码,这里把上面讨论的三种情况,都覆盖了 -```C++ +```CPP class Solution { public: vector searchRange(vector& nums, int target) { diff --git a/problems/0035.搜索插入位置.md b/problems/0035.搜索插入位置.md index 01604558..4ad8a80c 100644 --- a/problems/0035.搜索插入位置.md +++ b/problems/0035.搜索插入位置.md @@ -116,7 +116,7 @@ public: **大家要仔细看注释,思考为什么要写while(left <= right), 为什么要写right = middle - 1**。 -```C++ +```CPP class Solution { public: int searchInsert(vector& nums, int target) { @@ -158,7 +158,7 @@ public: **大家要仔细看注释,思考为什么要写while (left < right), 为什么要写right = middle**。 -```C++ +```CPP class Solution { public: int searchInsert(vector& nums, int target) { diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md index 7617d989..64be7013 100644 --- a/problems/0037.解数独.md +++ b/problems/0037.解数独.md @@ -90,7 +90,7 @@ bool backtracking(vector>& board) 代码如下:(**详细看注释**) -```C++ +```CPP bool backtracking(vector>& board) { for (int i = 0; i < board.size(); i++) { // 遍历行 for (int j = 0; j < board[0].size(); j++) { // 遍历列 @@ -125,7 +125,7 @@ bool backtracking(vector>& board) { 代码如下: -```C++ +```CPP bool isValid(int row, int col, char val, vector>& board) { for (int i = 0; i < 9; i++) { // 判断行里是否重复 if (board[row][i] == val) { @@ -154,7 +154,7 @@ bool isValid(int row, int col, char val, vector>& board) { ## C++代码 -```C++ +```CPP class Solution { private: bool backtracking(vector>& board) { diff --git a/problems/0039.组合总和.md b/problems/0039.组合总和.md index 56a4c737..0c452e22 100644 --- a/problems/0039.组合总和.md +++ b/problems/0039.组合总和.md @@ -73,7 +73,7 @@ candidates 中的数字可以无限制重复被选取。 代码如下: -```C++ +```CPP vector> result; vector path; void backtracking(vector& candidates, int target, int sum, int startIndex) @@ -89,7 +89,7 @@ void backtracking(vector& candidates, int target, int sum, int startIndex) sum等于target的时候,需要收集结果,代码如下: -```C++ +```CPP if (sum > target) { return; } @@ -107,7 +107,7 @@ if (sum == target) { 如何重复选取呢,看代码,注释部分: -```C++ +```CPP for (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; path.push_back(candidates[i]); @@ -119,7 +119,7 @@ for (int i = startIndex; i < candidates.size(); i++) { 按照[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)中给出的模板,不难写出如下C++完整代码: -```C++ +```CPP // 版本一 class Solution { private: @@ -179,7 +179,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; 整体代码如下:(注意注释的部分) -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0040.组合总和II.md b/problems/0040.组合总和II.md index e4d58f54..5ea11ca7 100644 --- a/problems/0040.组合总和II.md +++ b/problems/0040.组合总和II.md @@ -90,7 +90,7 @@ candidates 中的每个数字在每个组合中只能使用一次。 代码如下: -```C++ +```CPP vector> result; // 存放组合集合 vector path; // 符合条件的组合 void backtracking(vector& candidates, int target, int sum, int startIndex, vector& used) { @@ -102,7 +102,7 @@ void backtracking(vector& candidates, int target, int sum, int startIndex, 代码如下: -```C++ +```CPP if (sum > target) { // 这个条件其实可以省略 return; } @@ -137,7 +137,7 @@ if (sum == target) { 那么单层搜索的逻辑代码如下: -```C++ +```CPP for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) { // used[i - 1] == true,说明同一树支candidates[i - 1]使用过 // used[i - 1] == false,说明同一树层candidates[i - 1]使用过 @@ -161,7 +161,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; 回溯三部曲分析完了,整体C++代码如下: -```C++ +```CPP class Solution { private: vector> result; @@ -206,7 +206,7 @@ public: 这里直接用startIndex来去重也是可以的, 就不用used数组了。 -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0042.接雨水.md b/problems/0042.接雨水.md index 54086dc7..235776a0 100644 --- a/problems/0042.接雨水.md +++ b/problems/0042.接雨水.md @@ -77,7 +77,7 @@ 一样的方法,只要从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了。 首先从头遍历所有的列,并且**要注意第一个柱子和最后一个柱子不接雨水**,代码如下: -```C++ +```CPP for (int i = 0; i < height.size(); i++) { // 第一个柱子和最后一个柱子不接雨水 if (i == 0 || i == height.size() - 1) continue; @@ -86,7 +86,7 @@ for (int i = 0; i < height.size(); i++) { 在for循环中求左右两边最高柱子,代码如下: -```C++ +```CPP int rHeight = height[i]; // 记录右边柱子的最高高度 int lHeight = height[i]; // 记录左边柱子的最高高度 for (int r = i + 1; r < height.size(); r++) { @@ -99,14 +99,14 @@ for (int l = i - 1; l >= 0; l--) { 最后,计算该列的雨水高度,代码如下: -```C++ +```CPP int h = min(lHeight, rHeight) - height[i]; if (h > 0) sum += h; // 注意只有h大于零的时候,在统计到总和中 ``` 整体代码如下: -```C++ +```CPP class Solution { public: int trap(vector& height) { @@ -152,7 +152,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int trap(vector& height) { @@ -287,7 +287,7 @@ if (height[i] == height[st.top()]) { // 例如 5 5 1 7 这种情况 求当前凹槽雨水的体积代码如下: -```C++ +```CPP while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是while,持续跟新栈顶元素 int mid = st.top(); st.pop(); @@ -301,7 +301,7 @@ while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是while, 关键部分讲完了,整体代码如下: -```C++ +```CPP class Solution { public: int trap(vector& height) { @@ -335,7 +335,7 @@ public: 以上代码冗余了一些,但是思路是清晰的,下面我将代码精简一下,如下: -```C++ +```CPP class Solution { public: int trap(vector& height) { diff --git a/problems/0045.跳跃游戏II.md b/problems/0045.跳跃游戏II.md index fe93cc3a..d946315b 100644 --- a/problems/0045.跳跃游戏II.md +++ b/problems/0045.跳跃游戏II.md @@ -63,7 +63,7 @@ C++代码如下:(详细注释) -```C++ +```CPP // 版本一 class Solution { public: @@ -106,7 +106,7 @@ public: 代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0046.全排列.md b/problems/0046.全排列.md index 70f1cf53..c0626fb7 100644 --- a/problems/0046.全排列.md +++ b/problems/0046.全排列.md @@ -106,7 +106,7 @@ for (int i = 0; i < nums.size(); i++) { 整体C++代码如下: -```C++ +```CPP class Solution { public: vector> result; diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md index ce04258d..387e75c3 100644 --- a/problems/0051.N皇后.md +++ b/problems/0051.N皇后.md @@ -171,7 +171,7 @@ bool isValid(int row, int col, vector& chessboard, int n) { ## C++代码 -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0053.最大子序和.md b/problems/0053.最大子序和.md index cf4d19ec..cba7d6c7 100644 --- a/problems/0053.最大子序和.md +++ b/problems/0053.最大子序和.md @@ -25,7 +25,7 @@ 时间复杂度:O(n^2) 空间复杂度:O(1) -```C++ +```CPP class Solution { public: int maxSubArray(vector& nums) { @@ -81,7 +81,7 @@ if (count > result) result = count; 那么不难写出如下C++代码(关键地方已经注释) -```C++ +```CPP class Solution { public: int maxSubArray(vector& nums) { @@ -109,7 +109,7 @@ public: 那么先给出我的dp代码如下,有时间的录友可以提前做一做: -```C++ +```CPP class Solution { public: int maxSubArray(vector& nums) { diff --git a/problems/0053.最大子序和(动态规划).md b/problems/0053.最大子序和(动态规划).md index da81f8a3..0932c77f 100644 --- a/problems/0053.最大子序和(动态规划).md +++ b/problems/0053.最大子序和(动态规划).md @@ -65,7 +65,7 @@ dp[0]应该是多少呢? 以上动规五部曲分析完毕,完整代码如下: -```C++ +```CPP class Solution { public: int maxSubArray(vector& nums) { diff --git a/problems/0055.跳跃游戏.md b/problems/0055.跳跃游戏.md index 9019c810..0b1c1d36 100644 --- a/problems/0055.跳跃游戏.md +++ b/problems/0055.跳跃游戏.md @@ -58,7 +58,7 @@ i每次移动只能在cover的范围内移动,每移动一个元素,cover得 C++代码如下: -```C++ +```CPP class Solution { public: bool canJump(vector& nums) { diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 804b827b..99c870c6 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -56,7 +56,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: // 按照区间左边界从小到大排序 @@ -92,7 +92,7 @@ public: 当然以上代码有冗余一些,可以优化一下,如下:(思路是一样的) -```C++ +```CPP class Solution { public: vector> merge(vector>& intervals) { diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index 15186e78..e46dae6d 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -66,7 +66,7 @@ 整体C++代码如下: -```C++ +```CPP class Solution { public: vector> generateMatrix(int n) { diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index 629c6eb1..84c84075 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -59,7 +59,7 @@ 此时问题就可以转化为求二叉树叶子节点的个数,代码如下: -```C++ +```CPP class Solution { private: int dfs(int i, int j, int m, int n) { @@ -128,7 +128,7 @@ for (int j = 0; j < n; j++) dp[0][j] = 1; 以上动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int uniquePaths(int m, int n) { @@ -149,7 +149,7 @@ public: 其实用一个一维数组(也可以理解是滚动数组)就可以了,但是不利于理解,可以优化点空间,建议先理解了二维,在理解一维,C++代码如下: -```C++ +```CPP class Solution { public: int uniquePaths(int m, int n) { @@ -187,7 +187,7 @@ public: 例如如下代码是不行的。 -```C++ +```CPP class Solution { public: int uniquePaths(int m, int n) { @@ -204,7 +204,7 @@ public: 需要在计算分子的时候,不断除以分母,代码如下: -```C++ +```CPP class Solution { public: int uniquePaths(int m, int n) { diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index 74fa2e1a..3df1b301 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -97,7 +97,7 @@ for (int j = 0; j < n; j++) dp[0][j] = 1; 所以本题初始化代码为: -```C++ +```CPP vector> dp(m, vector(n, 0)); for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1; for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1; @@ -111,7 +111,7 @@ for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1; 代码如下: -```C++ +```CPP for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { if (obstacleGrid[i][j] == 1) continue; @@ -135,7 +135,7 @@ for (int i = 1; i < m; i++) { 动规五部分分析完毕,对应C++代码如下: -```C++ +```CPP class Solution { public: int uniquePathsWithObstacles(vector>& obstacleGrid) { diff --git a/problems/0070.爬楼梯.md b/problems/0070.爬楼梯.md index fe401dd6..bb9a757c 100644 --- a/problems/0070.爬楼梯.md +++ b/problems/0070.爬楼梯.md @@ -109,7 +109,7 @@ dp[i]: 爬到第i层楼梯,有dp[i]种方法 以上五部分析完之后,C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -130,7 +130,7 @@ public: 当然依然也可以,优化一下空间复杂度,代码如下: -```C++ +```CPP // 版本二 class Solution { public: @@ -163,7 +163,7 @@ public: 这里我先给出我的实现代码: -```C++ +```CPP class Solution { public: int climbStairs(int n) { diff --git a/problems/0072.编辑距离.md b/problems/0072.编辑距离.md index efc0a823..d7b6438d 100644 --- a/problems/0072.编辑距离.md +++ b/problems/0072.编辑距离.md @@ -123,7 +123,7 @@ if (word1[i - 1] != word2[j - 1]) 递归公式代码如下: -```C++ +```CPP if (word1[i - 1] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } @@ -151,7 +151,7 @@ dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最 所以C++代码如下: -```C++ +```CPP for (int i = 0; i <= word1.size(); i++) dp[i][0] = i; for (int j = 0; j <= word2.size(); j++) dp[0][j] = j; ``` @@ -175,7 +175,7 @@ for (int j = 0; j <= word2.size(); j++) dp[0][j] = j; 代码如下: -```C++ +```CPP for (int i = 1; i <= word1.size(); i++) { for (int j = 1; j <= word2.size(); j++) { if (word1[i - 1] == word2[j - 1]) { @@ -198,7 +198,7 @@ for (int i = 1; i <= word1.size(); i++) { 以上动规五部分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int minDistance(string word1, string word2) { diff --git a/problems/0077.组合.md b/problems/0077.组合.md index fc3fc0ae..d88a5711 100644 --- a/problems/0077.组合.md +++ b/problems/0077.组合.md @@ -173,7 +173,7 @@ for循环每次从startIndex开始遍历,然后用path保存取到的节点i 代码如下: -```C++ +```CPP for (int i = startIndex; i <= n; i++) { // 控制树的横向遍历 path.push_back(i); // 处理节点 backtracking(n, k, i + 1); // 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始 @@ -188,7 +188,7 @@ backtracking的下面部分就是回溯的操作了,撤销本次处理的结 关键地方都讲完了,组合问题C++完整代码如下: -```C++ +```CPP class Solution { private: vector> result; // 存放符合条件结果的集合 diff --git a/problems/0078.子集.md b/problems/0078.子集.md index 51f33550..ca49f97b 100644 --- a/problems/0078.子集.md +++ b/problems/0078.子集.md @@ -120,7 +120,7 @@ void backtracking(参数) { 可以写出如下回溯算法C++代码: -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0084.柱状图中最大的矩形.md b/problems/0084.柱状图中最大的矩形.md index d5d8c92a..f0f58c0f 100644 --- a/problems/0084.柱状图中最大的矩形.md +++ b/problems/0084.柱状图中最大的矩形.md @@ -23,7 +23,7 @@ ## 双指针解法 -```C++ +```CPP class Solution { public: int largestRectangleArea(vector& heights) { @@ -56,7 +56,7 @@ public: 所以需要循环查找,也就是下面在寻找的过程中使用了while,详细请看下面注释,整理思路在题解:[42. 接雨水](https://mp.weixin.qq.com/s/QogENxhotboct9wn7GgYUw)中已经介绍了。 -```C++ +```CPP class Solution { public: int largestRectangleArea(vector& heights) { @@ -125,7 +125,7 @@ public: C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -164,7 +164,7 @@ public: 代码精简之后: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0090.子集II.md b/problems/0090.子集II.md index 1ebf9f2b..5c19adc0 100644 --- a/problems/0090.子集II.md +++ b/problems/0090.子集II.md @@ -124,7 +124,7 @@ public: 代码如下: -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md index ced57db1..9a95af22 100644 --- a/problems/0093.复原IP地址.md +++ b/problems/0093.复原IP地址.md @@ -183,7 +183,7 @@ void backtracking(参数) { 可以写出如下回溯算法C++代码: -```C++ +```CPP class Solution { private: vector result;// 记录结果 diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md index 22188800..7cbe4fec 100644 --- a/problems/0096.不同的二叉搜索树.md +++ b/problems/0096.不同的二叉搜索树.md @@ -103,7 +103,7 @@ j相当于是头结点的元素,从1遍历到i为止。 代码如下: -```C++ +```CPP for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { dp[i] += dp[j - 1] * dp[i - j]; @@ -123,7 +123,7 @@ n为5时候的dp数组状态如图: 综上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int numTrees(int n) { diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index 567b9784..d6db901e 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -32,7 +32,7 @@ 可以递归中序遍历将二叉搜索树转变成一个数组,代码如下: -```C++ +```CPP vector vec; void traversal(TreeNode* root) { if (root == NULL) return; @@ -44,7 +44,7 @@ void traversal(TreeNode* root) { 然后只要比较一下,这个数组是否是有序的,**注意二叉搜索树中不能有重复元素**。 -```C++ +```CPP traversal(root); for (int i = 1; i < vec.size(); i++) { // 注意要小于等于,搜索树里不能有相同元素 @@ -55,7 +55,7 @@ return true; 整体代码如下: -```C++ +```CPP class Solution { private: vector vec; @@ -163,7 +163,7 @@ return left && right; 整体代码如下: -```C++ +```CPP class Solution { public: long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值 @@ -189,7 +189,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: TreeNode* pre = NULL; // 用来记录前一个节点 @@ -214,7 +214,7 @@ public: 迭代法中序遍历稍加改动就可以了,代码如下: -```C++ +```CPP class Solution { public: bool isValidBST(TreeNode* root) { diff --git a/problems/0100.相同的树.md b/problems/0100.相同的树.md index 5e37c9bd..e4eb412a 100644 --- a/problems/0100.相同的树.md +++ b/problems/0100.相同的树.md @@ -61,7 +61,7 @@ bool compare(TreeNode* tree1, TreeNode* tree2) 此时tree1、tree2节点不为空,且数值也不相同的情况我们也处理了。 代码如下: -```C++ +```CPP if (tree1 == NULL && tree2 != NULL) return false; else if (tree1 != NULL && tree2 == NULL) return false; else if (tree1 == NULL && tree2 == NULL) return true; @@ -77,7 +77,7 @@ else if (tree1->val != tree2->val) return false; // 注意这里我没有 代码如下: -```C++ +```CPP bool left = compare(tree1->left, tree2->left); // 左子树:左、 右子树:左 bool right = compare(tree1->right, tree2->right); // 左子树:右、 右子树:右 bool isSame = left && right; // 左子树:中、 右子树:中(逻辑处理) @@ -85,7 +85,7 @@ return isSame; ``` 最后递归的C++整体代码如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* tree1, TreeNode* tree2) { @@ -119,7 +119,7 @@ public: ## 递归 -```C++ +```CPP class Solution { public: bool compare(TreeNode* left, TreeNode* right) { @@ -138,7 +138,7 @@ public: ## 迭代法 -```C++ +```CPP class Solution { public: diff --git a/problems/0101.对称二叉树.md b/problems/0101.对称二叉树.md index 404fa283..e091844b 100644 --- a/problems/0101.对称二叉树.md +++ b/problems/0101.对称二叉树.md @@ -73,7 +73,7 @@ bool compare(TreeNode* left, TreeNode* right) 此时左右节点不为空,且数值也不相同的情况我们也处理了。 代码如下: -```C++ +```CPP if (left == NULL && right != NULL) return false; else if (left != NULL && right == NULL) return false; else if (left == NULL && right == NULL) return true; @@ -93,7 +93,7 @@ else if (left->val != right->val) return false; // 注意这里我没有 代码如下: -```C++ +```CPP bool outside = compare(left->left, right->right); // 左子树:左、 右子树:右 bool inside = compare(left->right, right->left); // 左子树:右、 右子树:左 bool isSame = outside && inside; // 左子树:中、 右子树:中(逻辑处理) @@ -104,7 +104,7 @@ return isSame; 最后递归的C++整体代码如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* left, TreeNode* right) { @@ -137,7 +137,7 @@ public: **盲目的照着抄,结果就是:发现这是一道“简单题”,稀里糊涂的就过了,但是真正的每一步判断逻辑未必想到清楚。** 当然我可以把如上代码整理如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* left, TreeNode* right) { @@ -177,7 +177,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: bool isSymmetric(TreeNode* root) { @@ -212,7 +212,7 @@ public: 只要把队列原封不动的改成栈就可以了,我下面也给出了代码。 -```C++ +```CPP class Solution { public: bool isSymmetric(TreeNode* root) { diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md index b27f7408..c38cc796 100644 --- a/problems/0102.二叉树的层序遍历.md +++ b/problems/0102.二叉树的层序遍历.md @@ -60,7 +60,7 @@ C++代码: -```C++ +```CPP class Solution { public: vector> levelOrder(TreeNode* root) { @@ -245,7 +245,7 @@ var levelOrder = function(root) { C++代码: -```C++ +```CPP class Solution { public: vector> levelOrderBottom(TreeNode* root) { @@ -422,7 +422,7 @@ var levelOrderBottom = function(root) { C++代码: -```C++ +```CPP class Solution { public: vector rightSideView(TreeNode* root) { @@ -599,7 +599,7 @@ var rightSideView = function(root) { C++代码: -```C++ +```CPP class Solution { public: vector averageOfLevels(TreeNode* root) { @@ -794,7 +794,7 @@ var averageOfLevels = function(root) { C++代码: -```C++ +```CPP class Solution { public: vector> levelOrder(Node* root) { @@ -1003,7 +1003,7 @@ var levelOrder = function(root) { C++代码: -```C++ +```CPP class Solution { public: vector largestValues(TreeNode* root) { @@ -1147,7 +1147,7 @@ struct Node { C++代码: -```C++ +```CPP class Solution { public: Node* connect(Node* root) { @@ -1269,7 +1269,7 @@ func connect(root *Node) *Node { C++代码: -```C++ +```CPP class Solution { public: Node* connect(Node* root) { @@ -1451,7 +1451,7 @@ func connect(root *Node) *Node { C++代码如下: -```C++ +```CPP class Solution { public: int maxDepth(TreeNode* root) { @@ -1491,7 +1491,7 @@ JavaScript: 代码如下:(详细注释) -```C++ +```CPP class Solution { public: int minDepth(TreeNode* root) { diff --git a/problems/0106.从中序与后序遍历序列构造二叉树.md b/problems/0106.从中序与后序遍历序列构造二叉树.md index 50055290..4cfe2858 100644 --- a/problems/0106.从中序与后序遍历序列构造二叉树.md +++ b/problems/0106.从中序与后序遍历序列构造二叉树.md @@ -59,7 +59,7 @@ 不难写出如下代码:(先把框架写出来) -```C++ +```CPP TreeNode* traversal (vector& inorder, vector& postorder) { // 第一步 @@ -155,7 +155,7 @@ root->right = traversal(rightInorder, rightPostorder); ### C++完整代码 -```C++ +```CPP class Solution { private: TreeNode* traversal (vector& inorder, vector& postorder) { @@ -209,7 +209,7 @@ public: 加了日志的代码如下:(加了日志的代码不要在leetcode上提交,容易超时) -```C++ +```CPP class Solution { private: TreeNode* traversal (vector& inorder, vector& postorder) { @@ -277,7 +277,7 @@ public: 下面给出用下表索引写出的代码版本:(思路是一样的,只不过不用重复定义vector了,每次用下表索引来分割) ### C++优化版本 -```C++ +```CPP class Solution { private: // 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd) @@ -325,7 +325,7 @@ public: 那么这个版本写出来依然要打日志进行调试,打日志的版本如下:(**该版本不要在leetcode上提交,容易超时**) -```C++ +```CPP class Solution { private: TreeNode* traversal (vector& inorder, int inorderBegin, int inorderEnd, vector& postorder, int postorderBegin, int postorderEnd) { @@ -419,7 +419,7 @@ public: 带日志的版本C++代码如下: (**带日志的版本仅用于调试,不要在leetcode上提交,会超时**) -```C++ +```CPP class Solution { private: TreeNode* traversal (vector& inorder, int inorderBegin, int inorderEnd, vector& preorder, int preorderBegin, int preorderEnd) { @@ -493,7 +493,7 @@ public: 105.从前序与中序遍历序列构造二叉树,最后版本,C++代码: -```C++ +```CPP class Solution { private: TreeNode* traversal (vector& inorder, int inorderBegin, int inorderEnd, vector& preorder, int preorderBegin, int preorderEnd) { diff --git a/problems/0108.将有序数组转换为二叉搜索树.md b/problems/0108.将有序数组转换为二叉搜索树.md index cba8a446..9e67a677 100644 --- a/problems/0108.将有序数组转换为二叉搜索树.md +++ b/problems/0108.将有序数组转换为二叉搜索树.md @@ -122,7 +122,7 @@ return root; * 递归整体代码如下: -```C++ +```CPP class Solution { private: TreeNode* traversal(vector& nums, int left, int right) { @@ -150,7 +150,7 @@ public: 模拟的就是不断分割的过程,C++代码如下:(我已经详细注释) -```C++ +```CPP class Solution { public: TreeNode* sortedArrayToBST(vector& nums) { diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md index f85b03c3..55d3c2e7 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -57,7 +57,7 @@ 在[104.二叉树的最大深度](https://mp.weixin.qq.com/s/jRaRcRerhEHepQbt-aKstw)中,如果真正求取二叉树的最大深度,代码应该写成如下:(前序遍历) -```C++ +```CPP class Solution { public: int result; @@ -91,7 +91,7 @@ public: 注意以上代码是为了把细节体现出来,简化一下代码如下: -```C++ +```CPP class Solution { public: int result; @@ -161,7 +161,7 @@ if (node == NULL) { 代码如下: -```C++ +```CPP int leftDepth = depth(node->left); // 左 if (leftDepth == -1) return -1; int rightDepth = depth(node->right); // 右 @@ -179,7 +179,7 @@ return result; 代码精简之后如下: -```C++ +```CPP int leftDepth = getDepth(node->left); if (leftDepth == -1) return -1; int rightDepth = getDepth(node->right); @@ -191,7 +191,7 @@ return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth); getDepth整体代码如下: -```C++ +```CPP int getDepth(TreeNode* node) { if (node == NULL) { return 0; @@ -206,7 +206,7 @@ int getDepth(TreeNode* node) { 最后本题整体递归代码如下: -```C++ +```CPP class Solution { public: // 返回以该节点为根节点的二叉树的高度,如果不是二叉搜索树了则返回-1 @@ -236,7 +236,7 @@ public: 代码如下: -```C++ +```CPP // cur节点的最大深度,就是cur的高度 int getDepth(TreeNode* cur) { stack st; @@ -267,7 +267,7 @@ int getDepth(TreeNode* cur) { 然后再用栈来模拟前序遍历,遍历每一个节点的时候,再去判断左右孩子的高度是否符合,代码如下: -```C++ +```CPP bool isBalanced(TreeNode* root) { stack st; if (root == NULL) return true; @@ -287,7 +287,7 @@ bool isBalanced(TreeNode* root) { 整体代码如下: -```C++ +```CPP class Solution { private: int getDepth(TreeNode* cur) { diff --git a/problems/0111.二叉树的最小深度.md b/problems/0111.二叉树的最小深度.md index 2f3605c7..b4d0e32b 100644 --- a/problems/0111.二叉树的最小深度.md +++ b/problems/0111.二叉树的最小深度.md @@ -87,7 +87,7 @@ return result; 代码如下: -```C++ +```CPP int leftDepth = getDepth(node->left); // 左 int rightDepth = getDepth(node->right); // 右 // 中 @@ -106,7 +106,7 @@ return result; 遍历的顺序为后序(左右中),可以看出:**求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。** 整体递归代码如下: -```C++ +```CPP class Solution { public: int getDepth(TreeNode* node) { @@ -134,7 +134,7 @@ public: 精简之后代码如下: -```C++ +```CPP class Solution { public: int minDepth(TreeNode* root) { @@ -162,7 +162,7 @@ public: 代码如下:(详细注释) -```C++ +```CPP class Solution { public: diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index 5d8e81d9..b59180ac 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -91,7 +91,7 @@ if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找 代码如下: -```C++ +```CPP if (cur->left) { // 左 (空节点不遍历) // 遇到叶子节点返回true,则直接返回true if (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑 @@ -109,7 +109,7 @@ return false; 为了把回溯的过程体现出来,可以改为如下代码: -```C++ +```CPP if (cur->left) { // 左 count -= cur->left->val; // 递归,处理节点; if (traversal(cur->left, count)) return true; @@ -126,7 +126,7 @@ return false; 整体代码如下: -```C++ +```CPP class Solution { private: bool traversal(TreeNode* cur, int count) { @@ -156,7 +156,7 @@ public: 以上代码精简之后如下: -```C++ +```CPP class Solution { public: bool hasPathSum(TreeNode* root, int sum) { @@ -186,7 +186,7 @@ C++就我们用pair结构来存放这个栈里的元素。 如下代码是使用栈模拟的前序遍历,如下:(详细注释) -```C++ +```CPP class Solution { public: @@ -243,7 +243,7 @@ public: 为了尽可能的把细节体现出来,我写出如下代码(**这份代码并不简洁,但是逻辑非常清晰**) -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0115.不同的子序列.md b/problems/0115.不同的子序列.md index 61c74722..e964e95d 100644 --- a/problems/0115.不同的子序列.md +++ b/problems/0115.不同的子序列.md @@ -82,7 +82,7 @@ dp[0][0]应该是1,空字符串s,可以删除0个元素,变成空字符串 初始化分析完毕,代码如下: -```C++ +```CPP vector> dp(s.size() + 1, vector(t.size() + 1)); for (int i = 0; i <= s.size(); i++) dp[i][0] = 1; for (int j = 1; j <= t.size(); j++) dp[0][j] = 0; // 其实这行代码可以和dp数组初始化的时候放在一起,但我为了凸显初始化的逻辑,所以还是加上了。 @@ -97,7 +97,7 @@ for (int j = 1; j <= t.size(); j++) dp[0][j] = 0; // 其实这行代码可以和 代码如下: -```C++ +```CPP for (int i = 1; i <= s.size(); i++) { for (int j = 1; j <= t.size(); j++) { if (s[i - 1] == t[j - 1]) { @@ -120,7 +120,7 @@ for (int i = 1; i <= s.size(); i++) { 动规五部曲分析完毕,代码如下: -```C++ +```CPP class Solution { public: int numDistinct(string s, string t) { diff --git a/problems/0116.填充每个节点的下一个右侧节点指针.md b/problems/0116.填充每个节点的下一个右侧节点指针.md index 5e7acebc..f96351aa 100644 --- a/problems/0116.填充每个节点的下一个右侧节点指针.md +++ b/problems/0116.填充每个节点的下一个右侧节点指针.md @@ -52,7 +52,7 @@ struct Node { 图中cur节点为元素4,那么搭线的逻辑代码:(**注意注释中操作1和操作2和图中的对应关系**) -```C++ +```CPP if (cur->left) cur->left->next = cur->right; // 操作1 if (cur->right) { if (cur->next) cur->right->next = cur->next->left; // 操作2 @@ -63,7 +63,7 @@ if (cur->right) { 理解到这里,使用前序遍历,那么不难写出如下代码: -```C++ +```CPP class Solution { private: void traversal(Node* cur) { @@ -93,7 +93,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: Node* connect(Node* root) { diff --git a/problems/0121.买卖股票的最佳时机.md b/problems/0121.买卖股票的最佳时机.md index 5418cdf4..6d068c22 100644 --- a/problems/0121.买卖股票的最佳时机.md +++ b/problems/0121.买卖股票的最佳时机.md @@ -33,7 +33,7 @@ 这道题目最直观的想法,就是暴力,找最优间距了。 -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -59,7 +59,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -139,7 +139,7 @@ dp[5][1]就是最终结果。 以上分析完毕,C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -169,7 +169,7 @@ dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]); 那么我们只需要记录 当前天的dp状态和前一天的dp状态就可以了,可以使用滚动数组来节省空间,代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0122.买卖股票的最佳时机II.md b/problems/0122.买卖股票的最佳时机II.md index b73f28b9..53737532 100644 --- a/problems/0122.买卖股票的最佳时机II.md +++ b/problems/0122.买卖股票的最佳时机II.md @@ -80,7 +80,7 @@ 对应C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -99,7 +99,7 @@ public: 动态规划将在下一个系列详细讲解,本题解先给出我的C++代码(带详细注释),感兴趣的同学可以自己先学习一下。 -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { diff --git a/problems/0122.买卖股票的最佳时机II(动态规划).md b/problems/0122.买卖股票的最佳时机II(动态规划).md index 82608b43..7492ee04 100644 --- a/problems/0122.买卖股票的最佳时机II(动态规划).md +++ b/problems/0122.买卖股票的最佳时机II(动态规划).md @@ -74,7 +74,7 @@ 代码如下:(注意代码中的注释,标记了和121.买卖股票的最佳时机唯一不同的地方) -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -106,7 +106,7 @@ dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); 这里我依然给出滚动数组的版本,C++代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0123.买卖股票的最佳时机III.md b/problems/0123.买卖股票的最佳时机III.md index e18a142e..0c92a5a2 100644 --- a/problems/0123.买卖股票的最佳时机III.md +++ b/problems/0123.买卖股票的最佳时机III.md @@ -127,7 +127,7 @@ dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]); 以上五部都分析完了,不难写出如下代码: -```C++ +```CPP // 版本一 class Solution { public: @@ -153,7 +153,7 @@ public: 当然,大家可以看到力扣官方题解里的一种优化空间写法,我这里给出对应的C++版本: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0129.求根到叶子节点数字之和.md b/problems/0129.求根到叶子节点数字之和.md index f83ed3e8..b37270e2 100644 --- a/problems/0129.求根到叶子节点数字之和.md +++ b/problems/0129.求根到叶子节点数字之和.md @@ -52,7 +52,7 @@ if (!cur->left && !cur->right) { // 遇到了叶子节点 这里vectorToInt函数就是把数组转成int,代码如下: -```C++ +```CPP int vectorToInt(const vector& vec) { int sum = 0; for (int i = 0; i < vec.size(); i++) { @@ -78,7 +78,7 @@ int vectorToInt(const vector& vec) { 代码如下: -```C++ +```CPP // 中 if (cur->left) { // 左 (空节点不遍历) path.push_back(cur->left->val); @@ -94,7 +94,7 @@ if (cur->right) { // 右 (空节点不遍历) 这里要注意回溯和递归要永远在一起,一个递归,对应一个回溯,是一对一的关系,有的同学写成如下代码: -```C++ +```CPP if (cur->left) { // 左 (空节点不遍历) path.push_back(cur->left->val); traversal(cur->left); // 递归 @@ -111,7 +111,7 @@ path.pop_back(); // 回溯 关键逻辑分析完了,整体C++代码如下: -```C++ +```CPP class Solution { private: int result; diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md index 5bcd38e0..6fe2758b 100644 --- a/problems/0131.分割回文串.md +++ b/problems/0131.分割回文串.md @@ -70,7 +70,7 @@ 代码如下: -```C++ +```CPP vector> result; vector path; // 放已经回文的子串 void backtracking (const string& s, int startIndex) { @@ -88,7 +88,7 @@ void backtracking (const string& s, int startIndex) { 所以终止条件代码如下: -```C++ +```CPP void backtracking (const string& s, int startIndex) { // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了 if (startIndex >= s.size()) { @@ -108,7 +108,7 @@ void backtracking (const string& s, int startIndex) { 代码如下: -```C++ +```CPP for (int i = startIndex; i < s.size(); i++) { if (isPalindrome(s, startIndex, i)) { // 是回文子串 // 获取[startIndex,i]在s中的子串 @@ -132,7 +132,7 @@ for (int i = startIndex; i < s.size(); i++) { 那么判断回文的C++代码如下: -```C++ +```CPP bool isPalindrome(const string& s, int start, int end) { for (int i = start, j = end; i < j; i++, j--) { if (s[i] != s[j]) { @@ -151,7 +151,7 @@ for (int i = startIndex; i < s.size(); i++) { 根据Carl给出的回溯算法模板: -```C++ +```CPP void backtracking(参数) { if (终止条件) { 存放结果; @@ -169,7 +169,7 @@ void backtracking(参数) { 不难写出如下代码: -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/0132.分割回文串II.md b/problems/0132.分割回文串II.md index d2b5fed4..80784301 100644 --- a/problems/0132.分割回文串II.md +++ b/problems/0132.分割回文串II.md @@ -101,7 +101,7 @@ dp[i]: 范围是[0, i]的回文子串,最少分割次数是dp[i]。 代码如下: -```C++ +```CPP vector dp(s.size(), INT_MAX); dp[0] = 0; ``` @@ -109,7 +109,7 @@ dp[0] = 0; 其实也可以这样初始化,更具dp[i]的定义,dp[i]的最大值其实就是i,也就是把每个字符分割出来。 所以初始化代码也可以为: -```C++ +```CPP vector dp(s.size()); for (int i = 0; i < s.size(); i++) dp[i] = i; ``` @@ -122,7 +122,7 @@ j是在[0,i]之间,所以遍历i的for循环一定在外层,这里遍历j 代码如下: -```C++ +```CPP for (int i = 1; i < s.size(); i++) { if (isPalindromic[0][i]) { // 判断是不是回文子串 dp[i] = 0; @@ -149,7 +149,7 @@ for (int i = 1; i < s.size(); i++) { 代码如下: -```C++ +```CPP vector> isPalindromic(s.size(), vector(s.size(), false)); for (int i = s.size() - 1; i >= 0; i--) { for (int j = i; j < s.size(); j++) { @@ -168,7 +168,7 @@ for (int i = s.size() - 1; i >= 0; i--) { 以上分析完毕,代码如下: -```C++ +```CPP class Solution { public: int minCut(string s) { diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index 0200e9d8..e270c059 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -65,7 +65,7 @@ cost = [3,4,3] C++代码如下: -```C++ +```CPP class Solution { public: int canCompleteCircuit(vector& gas, vector& cost) { @@ -99,7 +99,7 @@ C++暴力解法在leetcode上提交也可以过。 C++代码如下: -```C++ +```CPP class Solution { public: int canCompleteCircuit(vector& gas, vector& cost) { @@ -160,7 +160,7 @@ i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i C++代码如下: -```C++ +```CPP class Solution { public: int canCompleteCircuit(vector& gas, vector& cost) { diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index c9f11126..3865e14b 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -47,7 +47,7 @@ 代码如下: -```C++ +```CPP // 从前向后 for (int i = 1; i < ratings.size(); i++) { if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1; @@ -80,7 +80,7 @@ for (int i = 1; i < ratings.size(); i++) { 所以该过程代码如下: -```C++ +```CPP // 从后向前 for (int i = ratings.size() - 2; i >= 0; i--) { if (ratings[i] > ratings[i + 1] ) { @@ -90,7 +90,7 @@ for (int i = ratings.size() - 2; i >= 0; i--) { ``` 整体代码如下: -```C++ +```CPP class Solution { public: int candy(vector& ratings) { diff --git a/problems/0139.单词拆分.md b/problems/0139.单词拆分.md index 391655bb..0c19a614 100644 --- a/problems/0139.单词拆分.md +++ b/problems/0139.单词拆分.md @@ -45,7 +45,7 @@ 那么这里我也给出回溯法C++代码: -```C++ +```CPP class Solution { private: bool backtracking (const string& s, const unordered_set& wordSet, int startIndex) { @@ -86,7 +86,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { private: bool backtracking (const string& s, @@ -190,7 +190,7 @@ dp[s.size()]就是最终结果。 动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: bool wordBreak(string s, vector& wordDict) { diff --git a/problems/0141.环形链表.md b/problems/0141.环形链表.md index e6ac68b5..78bcfd43 100644 --- a/problems/0141.环形链表.md +++ b/problems/0141.环形链表.md @@ -45,7 +45,7 @@ fast和slow各自再走一步, fast和slow就相遇了 C++代码如下 -```C++ +```CPP class Solution { public: bool hasCycle(ListNode *head) { diff --git a/problems/0142.环形链表II.md b/problems/0142.环形链表II.md index 03f5b208..91e14e27 100644 --- a/problems/0142.环形链表II.md +++ b/problems/0142.环形链表II.md @@ -109,7 +109,7 @@ fast指针走过的节点数:` x + y + n (y + z)`,n为fast指针在环内走 代码如下: -```C++ +```CPP /** * Definition for singly-linked list. * struct ListNode { diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md index 76dbf20b..62232051 100644 --- a/problems/0143.重排链表.md +++ b/problems/0143.重排链表.md @@ -24,7 +24,7 @@ 代码如下: -```C++ +```CPP class Solution { public: void reorderList(ListNode* head) { @@ -63,7 +63,7 @@ public: 把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表。这种方法比操作数组容易一些,不用双指针模拟一前一后了 -```C++ +```CPP class Solution { public: void reorderList(ListNode* head) { @@ -108,7 +108,7 @@ public: 代码如下: -```C++ +```CPP class Solution { private: // 反转链表 diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index d7a2a0fc..2b294337 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -80,7 +80,7 @@ https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/ C++代码如下: -```C++ +```CPP class Solution { public: int evalRPN(vector& tokens) { diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index 3d316054..3f4d00b2 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -61,7 +61,7 @@ https://leetcode-cn.com/problems/reverse-words-in-a-string/ 思路很明确了,我们说一说代码的实现细节,就拿移除多余空格来说,一些同学会上来写如下代码: -```C++ +```CPP void removeExtraSpaces(string& s) { for (int i = s.size() - 1; i > 0; i--) { if (s[i] == s[i - 1] && s[i] == ' ') { @@ -93,7 +93,7 @@ erase操作上面还套了一个for循环,那么以上代码移除冗余空格 那么使用双指针来移除冗余空格代码如下: fastIndex走的快,slowIndex走的慢,最后slowIndex就标记着移除多余空格后新字符串的长度。 -```C++ +```CPP void removeExtraSpaces(string& s) { int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针 // 去掉字符串前面的空格 @@ -141,7 +141,7 @@ void reverse(string& s, int start, int end) { 本题C++整体代码 -```C++ +```CPP // 版本一 class Solution { public: diff --git a/problems/0188.买卖股票的最佳时机IV.md b/problems/0188.买卖股票的最佳时机IV.md index c7b77021..9fe7a919 100644 --- a/problems/0188.买卖股票的最佳时机IV.md +++ b/problems/0188.买卖股票的最佳时机IV.md @@ -84,7 +84,7 @@ vector> dp(prices.size(), vector(2 * k + 1, 0)); 同理可以类比剩下的状态,代码如下: -```C++ +```CPP for (int j = 0; j < 2 * k - 1; j += 2) { dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]); dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]); @@ -117,7 +117,7 @@ for (int j = 0; j < 2 * k - 1; j += 2) { 代码如下: -```C++ +```CPP for (int j = 1; j < 2 * k; j += 2) { dp[0][j] = -prices[0]; } @@ -139,7 +139,7 @@ for (int j = 1; j < 2 * k; j += 2) { 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(int k, vector& prices) { diff --git a/problems/0189.旋转数组.md b/problems/0189.旋转数组.md index 0b64cc87..be46bf4c 100644 --- a/problems/0189.旋转数组.md +++ b/problems/0189.旋转数组.md @@ -69,7 +69,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: void rotate(vector& nums, int k) { diff --git a/problems/0198.打家劫舍.md b/problems/0198.打家劫舍.md index aa2d5563..93b56dae 100644 --- a/problems/0198.打家劫舍.md +++ b/problems/0198.打家劫舍.md @@ -59,7 +59,7 @@ 代码如下: -```C++ +```CPP vector dp(nums.size()); dp[0] = nums[0]; dp[1] = max(nums[0], nums[1]); @@ -70,7 +70,7 @@ dp[1] = max(nums[0], nums[1]); dp[i] 是根据dp[i - 2] 和 dp[i - 1] 推导出来的,那么一定是从前到后遍历! 代码如下: -```C++ +```CPP for (int i = 2; i < nums.size(); i++) { dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); } @@ -86,7 +86,7 @@ for (int i = 2; i < nums.size(); i++) { 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int rob(vector& nums) { diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md index f6c2d5dc..1c630b6a 100644 --- a/problems/0202.快乐数.md +++ b/problems/0202.快乐数.md @@ -46,7 +46,7 @@ https://leetcode-cn.com/problems/happy-number/ C++代码如下: -```C++ +```CPP class Solution { public: // 取数值各个位上的单数之和 diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index 406efe88..a2c6e90d 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -89,7 +89,7 @@ https://leetcode-cn.com/problems/remove-linked-list-elements/ **直接使用原来的链表来进行移除节点操作:** -```C++ +```CPP class Solution { public: ListNode* removeElements(ListNode* head, int val) { @@ -118,7 +118,7 @@ public: **设置一个虚拟头结点在进行移除节点操作:** -```C++ +```CPP class Solution { public: ListNode* removeElements(ListNode* head, int val) { diff --git a/problems/0205.同构字符串.md b/problems/0205.同构字符串.md index 4daea839..d5077e03 100644 --- a/problems/0205.同构字符串.md +++ b/problems/0205.同构字符串.md @@ -39,7 +39,7 @@ C++代码 如下: -```C++ +```CPP class Solution { public: bool isIsomorphic(string s, string t) { diff --git a/problems/0206.翻转链表.md b/problems/0206.翻转链表.md index 397a26c9..8bb359bd 100644 --- a/problems/0206.翻转链表.md +++ b/problems/0206.翻转链表.md @@ -48,7 +48,7 @@ https://leetcode-cn.com/problems/reverse-linked-list/ # C++代码 ## 双指针法 -```C++ +```CPP class Solution { public: ListNode* reverseList(ListNode* head) { @@ -74,7 +74,7 @@ public: 关键是初始化的地方,可能有的同学会不理解, 可以看到双指针法中初始化 cur = head,pre = NULL,在递归法中可以从如下代码看出初始化的逻辑也是一样的,只不过写法变了。 具体可以看代码(已经详细注释),**双指针法写出来之后,理解如下递归写法就不难了,代码逻辑都是一样的。** -```C++ +```CPP class Solution { public: ListNode* reverse(ListNode* pre,ListNode* cur){ diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index ed3a7a9b..3a31b918 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -26,7 +26,7 @@ 代码如下: -```C++ +```CPP class Solution { public: int minSubArrayLen(int s, vector& nums) { @@ -86,7 +86,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { public: int minSubArrayLen(int s, vector& nums) { diff --git a/problems/0213.打家劫舍II.md b/problems/0213.打家劫舍II.md index ec69c3ea..e828d17a 100644 --- a/problems/0213.打家劫舍II.md +++ b/problems/0213.打家劫舍II.md @@ -59,7 +59,7 @@ 代码如下: -```C++ +```CPP // 注意注释中的情况二情况三,以及把198.打家劫舍的代码抽离出来了 class Solution { public: diff --git a/problems/0216.组合总和III.md b/problems/0216.组合总和III.md index c71d0589..c9cfa973 100644 --- a/problems/0216.组合总和III.md +++ b/problems/0216.组合总和III.md @@ -94,7 +94,7 @@ void backtracking(int targetSum, int k, int sum, int startIndex) 所以 终止代码如下: -```C++ +```CPP if (path.size() == k) { if (sum == targetSum) result.push_back(path); return; // 如果path.size() == k 但sum != targetSum 直接返回 @@ -112,7 +112,7 @@ if (path.size() == k) { 代码如下: -```C++ +```CPP for (int i = startIndex; i <= 9; i++) { sum += i; path.push_back(i); @@ -126,7 +126,7 @@ for (int i = startIndex; i <= 9; i++) { 参照[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)中的模板,不难写出如下C++代码: -```C++ +```CPP class Solution { private: vector> result; // 存放结果集 diff --git a/problems/0222.完全二叉树的节点个数.md b/problems/0222.完全二叉树的节点个数.md index 59e6e819..0d3a818e 100644 --- a/problems/0222.完全二叉树的节点个数.md +++ b/problems/0222.完全二叉树的节点个数.md @@ -77,7 +77,7 @@ return treeNum; 所以整体C++代码如下: -```C++ +```CPP // 版本一 class Solution { private: @@ -96,7 +96,7 @@ public: ``` 代码精简之后C++代码如下: -```C++ +```CPP // 版本二 class Solution { public: @@ -119,7 +119,7 @@ public: 那么只要模板少做改动,加一个变量result,统计节点数量就可以了 -```C++ +```CPP class Solution { public: int countNodes(TreeNode* root) { @@ -163,7 +163,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { public: int countNodes(TreeNode* root) { diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index 03172c24..b327c17b 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -65,7 +65,7 @@ queue.empty(); 详细如代码注释所示: -```C++ +```CPP class MyStack { public: queue que1; @@ -118,7 +118,7 @@ public: C++优化代码 -```C++ +```CPP class MyStack { public: queue que; diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md index 31983de2..6eb6f301 100644 --- a/problems/0226.翻转二叉树.md +++ b/problems/0226.翻转二叉树.md @@ -89,7 +89,7 @@ invertTree(root->right); 基于这递归三步法,代码基本写完,C++代码如下: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -111,7 +111,7 @@ public: C++代码迭代法(前序遍历) -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -136,7 +136,7 @@ public: C++代码如下迭代法(前序遍历) -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -168,7 +168,7 @@ public: 也就是层序遍历,层数遍历也是可以翻转这棵树的,因为层序遍历也可以把每个节点的左右孩子都翻转一遍,代码如下: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -196,7 +196,7 @@ public: 如果非要使用递归中序的方式写,也可以,如下代码就可以避免节点左右孩子翻转两次的情况: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -215,7 +215,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index 66e82746..0df82d35 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -67,7 +67,7 @@ queue.empty(); C++代码如下: -```C++ +```CPP class MyQueue { public: stack stIn; diff --git a/problems/0234.回文链表.md b/problems/0234.回文链表.md index fbb79e64..6a24b1d0 100644 --- a/problems/0234.回文链表.md +++ b/problems/0234.回文链表.md @@ -30,7 +30,7 @@ 代码也比较简单。如下: -```C++ +```CPP class Solution { public: bool isPalindrome(ListNode* head) { @@ -51,7 +51,7 @@ public: 上面代码可以在优化,就是先求出链表长度,然后给定vector的初始长度,这样避免vector每次添加节点重新开辟空间 -```C++ +```CPP class Solution { public: bool isPalindrome(ListNode* head) { @@ -95,7 +95,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: bool isPalindrome(ListNode* head) { diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index af910987..fe875067 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -93,7 +93,7 @@ if (cur == NULL) return cur; 代码如下: -```C++ +```CPP if (cur->val > p->val && cur->val > q->val) { TreeNode* left = traversal(cur->left, p, q); if (left != NULL) { @@ -147,7 +147,7 @@ return cur; 那么整体递归代码如下: -```C++ +```CPP class Solution { private: TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) { @@ -177,7 +177,7 @@ public: 精简后代码如下: -```C++ +```CPP class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { @@ -198,7 +198,7 @@ public: 迭代代码如下: -```C++ +```CPP class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md index a1045d8a..0885e20f 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -150,7 +150,7 @@ TreeNode* right = lowestCommonAncestor(root->right, p, q); 代码如下: -```C++ +```CPP if (left == NULL && right != NULL) return right; else if (left != NULL && right == NULL) return left; else { // (left == NULL && right == NULL) @@ -167,7 +167,7 @@ else { // (left == NULL && right == NULL) 整体代码如下: -```C++ +```CPP class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { @@ -188,7 +188,7 @@ public: 稍加精简,代码如下: -```C++ +```CPP class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 9658ae36..3c12a985 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -108,7 +108,7 @@ public: 基于刚刚说过的单调队列pop和push的规则,代码不难实现,如下: -```C++ +```CPP class MyQueue { //单调队列(从大到小) public: deque que; // 使用deque来实现单调队列 @@ -140,7 +140,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { private: class MyQueue { //单调队列(从大到小) diff --git a/problems/0242.有效的字母异位词.md b/problems/0242.有效的字母异位词.md index e89bf82c..b215a88a 100644 --- a/problems/0242.有效的字母异位词.md +++ b/problems/0242.有效的字母异位词.md @@ -61,7 +61,7 @@ https://leetcode-cn.com/problems/valid-anagram/ C++ 代码如下: -```C++ +```CPP class Solution { public: bool isAnagram(string s, string t) { diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index 0486f8ed..84315507 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -77,7 +77,7 @@ if (cur->left == NULL && cur->right == NULL) { 这里我们先使用vector结构的path容器来记录路径,那么终止处理逻辑如下: -```C++ +```CPP if (cur->left == NULL && cur->right == NULL) { // 遇到叶子节点 string sPath; for (int i = 0; i < path.size() - 1; i++) { // 将path里记录的路径转为string格式 @@ -113,7 +113,7 @@ if (cur->right) { 那么回溯要怎么回溯呢,一些同学会这么写,如下: -```C++ +```CPP if (cur->left) { traversal(cur->left, path, result); } @@ -129,7 +129,7 @@ path.pop_back(); 那么代码应该这么写: -```C++ +```CPP if (cur->left) { traversal(cur->left, path, result); path.pop_back(); // 回溯 @@ -142,7 +142,7 @@ if (cur->right) { 那么本题整体代码如下: -```C++ +```CPP class Solution { private: @@ -183,7 +183,7 @@ public: 那么如上代码可以精简成如下代码: -```C++ +```CPP class Solution { private: @@ -217,20 +217,20 @@ public: 为了把这份精简代码的回溯过程展现出来,大家可以试一试把: -```C++ +```CPP if (cur->left) traversal(cur->left, path + "->", result); // 左 回溯就隐藏在这里 ``` 改成如下代码: -```C++ +```CPP path += "->"; traversal(cur->left, path, result); // 左 ``` 即: -```C++ +```CPP if (cur->left) { path += "->"; traversal(cur->left, path, result); // 左 @@ -245,7 +245,7 @@ if (cur->right) { 如果想把回溯加上,就要 在上面代码的基础上,加上回溯,就可以AC了。 -```C++ +```CPP if (cur->left) { path += "->"; traversal(cur->left, path, result); // 左 @@ -276,7 +276,7 @@ if (cur->right) { C++代码如下: -```C++ +```CPP class Solution { public: vector binaryTreePaths(TreeNode* root) { diff --git a/problems/0279.完全平方数.md b/problems/0279.完全平方数.md index b5d9189b..199259ac 100644 --- a/problems/0279.完全平方数.md +++ b/problems/0279.完全平方数.md @@ -76,7 +76,7 @@ dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。 我这里先给出外层遍历背包,里层遍历物品的代码: -```C++ +```CPP vector dp(n + 1, INT_MAX); dp[0] = 0; for (int i = 0; i <= n; i++) { // 遍历背包 @@ -106,7 +106,7 @@ dp[5] = min(dp[4] + 1, dp[1] + 1) = 2 以上动规五部曲分析完毕C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -125,7 +125,7 @@ public: 同样我在给出先遍历物品,在遍历背包的代码,一样的可以AC的。 -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0283.移动零.md b/problems/0283.移动零.md index 29cf31d9..af7142fa 100644 --- a/problems/0283.移动零.md +++ b/problems/0283.移动零.md @@ -42,7 +42,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: void moveZeroes(vector& nums) { diff --git a/problems/0300.最长上升子序列.md b/problems/0300.最长上升子序列.md index 7706a112..57edd13e 100644 --- a/problems/0300.最长上升子序列.md +++ b/problems/0300.最长上升子序列.md @@ -60,7 +60,7 @@ dp[i] 是有0到i-1各个位置的最长升序子序列 推导而来,那么遍 j其实就是0到i-1,遍历i的循环里外层,遍历j则在内层,代码如下: -```C++ +```CPP for (int i = 1; i < nums.size(); i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1); @@ -80,7 +80,7 @@ for (int i = 1; i < nums.size(); i++) { 以上五部分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int lengthOfLIS(vector& nums) { diff --git a/problems/0309.最佳买卖股票时机含冷冻期.md b/problems/0309.最佳买卖股票时机含冷冻期.md index 7f81f4ba..3b1b6500 100644 --- a/problems/0309.最佳买卖股票时机含冷冻期.md +++ b/problems/0309.最佳买卖股票时机含冷冻期.md @@ -95,7 +95,7 @@ p[i][3] = dp[i - 1][2]; 综上分析,递推代码如下: -```C++ +```CPP dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]; dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]); dp[i][2] = dp[i - 1][0] + prices[i]; @@ -129,7 +129,7 @@ dp[i][3] = dp[i - 1][2]; 代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { diff --git a/problems/0322.零钱兑换.md b/problems/0322.零钱兑换.md index 72f25a35..758bd5b8 100644 --- a/problems/0322.零钱兑换.md +++ b/problems/0322.零钱兑换.md @@ -112,7 +112,7 @@ dp[amount]为最终结果。 ## C++代码 以上分析完毕,C++ 代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -134,7 +134,7 @@ public: 对于遍历方式遍历背包放在外循环,遍历物品放在内循环也是可以的,我就直接给出代码了 -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index 90c33828..8a28899b 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -178,7 +178,7 @@ if (result.size() == ticketNum + 1) { 遍历过程如下: -```C++ +```CPP for (pair& target : targets[result[result.size() - 1]]) { if (target.second > 0 ) { // 记录到达机场是否飞过了 result.push_back(target.first); @@ -194,7 +194,7 @@ for (pair& target : targets[result[result.size() - 1]]) { 分析完毕,此时完整C++代码如下: -```C++ +```CPP class Solution { private: // unordered_map<出发机场, map<到达机场, 航班次数>> targets diff --git a/problems/0337.打家劫舍III.md b/problems/0337.打家劫舍III.md index 98dc1f8f..44e60fb3 100644 --- a/problems/0337.打家劫舍III.md +++ b/problems/0337.打家劫舍III.md @@ -35,7 +35,7 @@ 代码如下: -```C++ +```CPP class Solution { public: int rob(TreeNode* root) { @@ -65,7 +65,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: unordered_map umap; // 记录计算过的结果 @@ -103,7 +103,7 @@ public: 参数为当前节点,代码如下: -```C++ +```CPP vector robTree(TreeNode* cur) { ``` @@ -138,7 +138,7 @@ if (cur == NULL) return vector{0, 0}; 代码如下: -```C++ +```CPP // 下标0:不偷,下标1:偷 vector left = robTree(cur->left); // 左 vector right = robTree(cur->right); // 右 @@ -156,7 +156,7 @@ vector right = robTree(cur->right); // 右 代码如下: -```C++ +```CPP vector left = robTree(cur->left); // 左 vector right = robTree(cur->right); // 右 @@ -179,7 +179,7 @@ return {val2, val1}; 递归三部曲与动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int rob(TreeNode* root) { diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index e558d399..a9c55a85 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -105,7 +105,7 @@ for (int i = 3; i <= n ; i++) { 以上动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int integerBreak(int n) { @@ -132,7 +132,7 @@ public: 给出我的C++代码如下: -```C++ +```CPP class Solution { public: int integerBreak(int n) { @@ -158,7 +158,7 @@ public: 其实这道题目的递推公式并不好想,而且初始化的地方也很有讲究,我在写本题的时候一开始写的代码是这样的: -```C++ +```CPP class Solution { public: int integerBreak(int n) { diff --git a/problems/0344.反转字符串.md b/problems/0344.反转字符串.md index af8198ee..4f96f839 100644 --- a/problems/0344.反转字符串.md +++ b/problems/0344.反转字符串.md @@ -74,7 +74,7 @@ https://leetcode-cn.com/problems/reverse-string/ 不难写出如下C++代码: -```C++ +```CPP void reverseString(vector& s) { for (int i = 0, j = s.size() - 1; i < s.size()/2; i++, j--) { swap(s[i],s[j]); @@ -90,7 +90,7 @@ swap可以有两种实现。 一种就是常见的交换数值: -```C++ +```CPP int tmp = s[i]; s[i] = s[j]; s[j] = tmp; @@ -99,7 +99,7 @@ s[j] = tmp; 一种就是通过位运算: -```C++ +```CPP s[i] ^= s[j]; s[j] ^= s[i]; s[i] ^= s[j]; @@ -120,7 +120,7 @@ s[i] ^= s[j]; C++代码如下: -```C++ +```CPP class Solution { public: void reverseString(vector& s) { diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md index 93f1060b..680de3bd 100644 --- a/problems/0347.前K个高频元素.md +++ b/problems/0347.前K个高频元素.md @@ -76,7 +76,7 @@ https://leetcode-cn.com/problems/top-k-frequent-elements/ 我们来看一下C++代码: -```C++ +```CPP // 时间复杂度:O(nlogk) // 空间复杂度:O(n) class Solution { diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md index 80dca17d..29c1c144 100644 --- a/problems/0349.两个数组的交集.md +++ b/problems/0349.两个数组的交集.md @@ -54,7 +54,7 @@ std::set和std::multiset底层实现都是红黑树,std::unordered_set的底 C++代码如下: -```C++ +```CPP class Solution { public: vector intersection(vector& nums1, vector& nums2) { diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md index fefb5497..0ccc405a 100644 --- a/problems/0376.摆动序列.md +++ b/problems/0376.摆动序列.md @@ -70,7 +70,7 @@ C++代码如下(和上图是对应的逻辑): -```C++ +```CPP class Solution { public: int wiggleMaxLength(vector& nums) { diff --git a/problems/0377.组合总和Ⅳ.md b/problems/0377.组合总和Ⅳ.md index 4130d12f..3f735727 100644 --- a/problems/0377.组合总和Ⅳ.md +++ b/problems/0377.组合总和Ⅳ.md @@ -107,7 +107,7 @@ dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int combinationSum4(vector& nums, int target) { diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md index dafbaf09..f2c1685a 100644 --- a/problems/0383.赎金信.md +++ b/problems/0383.赎金信.md @@ -40,7 +40,7 @@ canConstruct("aa", "aab") -> true 那么第一个思路其实就是暴力枚举了,两层for循环,不断去寻找,代码如下: -```C++ +```CPP // 时间复杂度: O(n^2) // 空间复杂度:O(1) class Solution { @@ -79,7 +79,7 @@ public: 代码如下: -```C++ +```CPP // 时间复杂度: O(n) // 空间复杂度:O(1) class Solution { diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md index 7e4d66b7..bcf3462b 100644 --- a/problems/0392.判断子序列.md +++ b/problems/0392.判断子序列.md @@ -107,7 +107,7 @@ dp[i][j]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字 动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: bool isSubsequence(string s, string t) { diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index aad59368..84ec2310 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -65,7 +65,7 @@ if (root == NULL) return 0; 代码如下: -```C++ +```CPP int leftValue = sumOfLeftLeaves(root->left); // 左 int rightValue = sumOfLeftLeaves(root->right); // 右 // 中 @@ -81,7 +81,7 @@ return sum; 整体递归代码如下: -```C++ +```CPP class Solution { public: int sumOfLeftLeaves(TreeNode* root) { @@ -102,7 +102,7 @@ public: 以上代码精简之后如下: -```C++ +```CPP class Solution { public: int sumOfLeftLeaves(TreeNode* root) { @@ -123,7 +123,7 @@ public: 判断条件都是一样的,代码如下: -```C++ +```CPP class Solution { public: diff --git a/problems/0406.根据身高重建队列.md b/problems/0406.根据身高重建队列.md index 7bc4e76c..e9b9a738 100644 --- a/problems/0406.根据身高重建队列.md +++ b/problems/0406.根据身高重建队列.md @@ -99,7 +99,7 @@ C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -127,7 +127,7 @@ public: 改成链表之后,C++代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index 03225fb6..0f1f094a 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -106,7 +106,7 @@ 代码如下: -```C++ +```CPP // 题目中说:每个数组中的元素不会超过 100,数组的大小不会超过 200 // 总和不会大于20000,背包最大只需要其中一半,所以10001大小就可以了 vector dp(10001, 0); @@ -118,7 +118,7 @@ vector dp(10001, 0); 代码如下: -```C++ +```CPP // 开始 01背包 for(int i = 0; i < nums.size(); i++) { for(int j = target; j >= nums[i]; j--) { // 每一个元素一定是不可重复放入,所以从大到小遍历 @@ -141,7 +141,7 @@ dp[i]的数值一定是小于等于i的。 综上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: bool canPartition(vector& nums) { diff --git a/problems/0435.无重叠区间.md b/problems/0435.无重叠区间.md index 39a88287..70d0ff3a 100644 --- a/problems/0435.无重叠区间.md +++ b/problems/0435.无重叠区间.md @@ -126,7 +126,7 @@ public: 把[452.用最少数量的箭引爆气球](https://mp.weixin.qq.com/s/HxVAJ6INMfNKiGwI88-RFw)代码稍做修改,就可以AC本题。 -```C++ +```CPP class Solution { public: // 按照区间右边界排序 @@ -152,7 +152,7 @@ public: ``` 这里按照 左区间遍历,或者按照右边界遍历,都可以AC,具体原因我还没有仔细看,后面有空再补充。 -```C++ +```CPP class Solution { public: // 按照区间左边界排序 diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index 13a1f0e4..96c49468 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -78,7 +78,7 @@ if (root == nullptr) return root; 代码如下: -```C++ +```CPP if (root->val == key) { // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点 // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点 @@ -111,7 +111,7 @@ return root; **整体代码如下:(注释中:情况1,2,3,4,5和上面分析严格对应)** -```C++ +```CPP class Solution { public: TreeNode* deleteNode(TreeNode* root, int key) { @@ -156,7 +156,7 @@ public: 代码如下:(关键部分已经注释) -```C++ +```CPP class Solution { public: TreeNode* deleteNode(TreeNode* root, int key) { @@ -186,7 +186,7 @@ public: 代码如下: -```C++ +```CPP class Solution { private: // 将目标节点(删除节点)的左子树放到 目标节点的右子树的最左面节点的左孩子位置上 diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index f6c7783b..589105b2 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -84,7 +84,7 @@ C++代码如下: -```C++ +```CPP class Solution { private: static bool cmp(const vector& a, const vector& b) { diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index 23d50c2d..eafee43e 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -53,7 +53,7 @@ D = [ 0, 2] C++代码: -```C++ +```CPP class Solution { public: int fourSumCount(vector& A, vector& B, vector& C, vector& D) { diff --git a/problems/0455.分发饼干.md b/problems/0455.分发饼干.md index d1a93c27..19268942 100644 --- a/problems/0455.分发饼干.md +++ b/problems/0455.分发饼干.md @@ -59,7 +59,7 @@ C++代码整体如下: -```C++ +```CPP // 时间复杂度:O(nlogn) // 空间复杂度:O(1) class Solution { @@ -88,7 +88,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int findContentChildren(vector& g, vector& s) { diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index c6cb0840..3b735942 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -70,7 +70,7 @@ next[len - 1] = 7,next[len - 1] + 1 = 8,8就是此时字符串asdfasdfasdf C++代码如下:(这里使用了前缀表统一减一的实现方式) -```C++ +```CPP class Solution { public: void getNext (int* next, const string& s){ @@ -104,7 +104,7 @@ public: 前缀表(不减一)的C++代码实现 -```C++ +```CPP class Solution { public: void getNext (int* next, const string& s){ diff --git a/problems/0463.岛屿的周长.md b/problems/0463.岛屿的周长.md index d19ce6cc..15255d3e 100644 --- a/problems/0463.岛屿的周长.md +++ b/problems/0463.岛屿的周长.md @@ -16,7 +16,7 @@ https://leetcode-cn.com/problems/island-perimeter/ C++代码如下:(详细注释) -```C++ +```CPP class Solution { public: int direction[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; @@ -56,7 +56,7 @@ result = 岛屿数量 * 4 - cover * 2; C++代码如下:(详细注释) -```C++ +```CPP class Solution { public: int islandPerimeter(vector>& grid) { diff --git a/problems/0474.一和零.md b/problems/0474.一和零.md index 76cf29f7..90d1227a 100644 --- a/problems/0474.一和零.md +++ b/problems/0474.一和零.md @@ -95,7 +95,7 @@ dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。 那么本题也是,物品就是strs里的字符串,背包容量就是题目描述中的m和n。 代码如下: -```C++ +```CPP for (string str : strs) { // 遍历物品 int oneNum = 0, zeroNum = 0; for (char c : str) { @@ -126,7 +126,7 @@ for (string str : strs) { // 遍历物品 以上动规五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int findMaxForm(vector& strs, int m, int n) { diff --git a/problems/0491.递增子序列.md b/problems/0491.递增子序列.md index c3a1d631..ed712f34 100644 --- a/problems/0491.递增子序列.md +++ b/problems/0491.递增子序列.md @@ -105,7 +105,7 @@ for (int i = startIndex; i < nums.size(); i++) { 最后整体C++代码如下: -```C++ +```CPP // 版本一 class Solution { private: @@ -150,7 +150,7 @@ public: 那么优化后的代码如下: -```C++ +```CPP // 版本二 class Solution { private: diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index 3bd8536c..77b3c76d 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -67,7 +67,7 @@ target是固定的,sum是固定的,left就可以求出来。 我也把代码给出来吧,大家可以了解一下,回溯的解法,以下是本题转变为组合总和问题的回溯法代码: -```C++ +```CPP class Solution { private: vector> result; @@ -124,7 +124,7 @@ x = (S + sum) / 2 这么担心就对了,例如sum 是5,S是2的话其实就是无解的,所以: -```C++ +```CPP if ((S + sum) % 2 == 1) return 0; // 此时没有方案 ``` @@ -194,7 +194,7 @@ dp数组状态变化如下: C++代码如下: -```C++ +```CPP class Solution { public: int findTargetSumWays(vector& nums, int S) { diff --git a/problems/0496.下一个更大元素I.md b/problems/0496.下一个更大元素I.md index a6c0e3bc..bbc21d24 100644 --- a/problems/0496.下一个更大元素I.md +++ b/problems/0496.下一个更大元素I.md @@ -64,7 +64,7 @@ C++中,当我们要使用集合来解决哈希问题的时候,优先使用un 那么预处理代码如下: -```C++ +```CPP unordered_map umap; // key:下表元素,value:下表 for (int i = 0; i < nums1.size(); i++) { umap[nums1[i]] = i; @@ -100,7 +100,7 @@ for (int i = 0; i < nums1.size(); i++) { 代码如下: -```C++ +```CPP while (!st.empty() && nums2[i] > nums2[st.top()]) { if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素 int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下表 @@ -114,7 +114,7 @@ st.push(i); 以上分析完毕,C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -152,7 +152,7 @@ public: 针对版本一,进行代码精简后,代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0501.二叉搜索树中的众数.md b/problems/0501.二叉搜索树中的众数.md index 3804f424..f29fd08a 100644 --- a/problems/0501.二叉搜索树中的众数.md +++ b/problems/0501.二叉搜索树中的众数.md @@ -53,7 +53,7 @@ 这里采用前序遍历,代码如下: -```C++ +```CPP // map key:元素,value:出现频率 void searchBST(TreeNode* cur, unordered_map& map) { // 前序遍历 if (cur == NULL) return ; @@ -87,7 +87,7 @@ sort(vec.begin(), vec.end(), cmp); // 给频率排个序 代码如下: -```C++ +```CPP result.push_back(vec[0].first); for (int i = 1; i < vec.size(); i++) { // 取最高的放到result数组中 @@ -100,7 +100,7 @@ return result; 整体C++代码如下: -```C++ +```CPP class Solution { private: @@ -145,7 +145,7 @@ public: 中序遍历代码如下: -```C++ +```CPP void searchBST(TreeNode* cur) { if (cur == NULL) return ; searchBST(cur->left); // 左 @@ -217,7 +217,7 @@ if (count > maxCount) { // 如果计数大于最大值 关键代码都讲完了,完整代码如下:(**只需要遍历一遍二叉搜索树,就求出了众数的集合**) -```C++ +```CPP class Solution { private: int maxCount; // 最大频率 @@ -279,7 +279,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: vector findMode(TreeNode* root) { diff --git a/problems/0503.下一个更大元素II.md b/problems/0503.下一个更大元素II.md index c9c76046..13c2cb29 100644 --- a/problems/0503.下一个更大元素II.md +++ b/problems/0503.下一个更大元素II.md @@ -32,7 +32,7 @@ 代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -69,7 +69,7 @@ resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于多了 代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0509.斐波那契数.md b/problems/0509.斐波那契数.md index 7a672de5..3b3d5056 100644 --- a/problems/0509.斐波那契数.md +++ b/problems/0509.斐波那契数.md @@ -88,7 +88,7 @@ dp[1] = 1; 以上我们用动规的方法分析完了,C++代码如下: -```C++ +```CPP class Solution { public: int fib(int N) { @@ -110,7 +110,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int fib(int N) { @@ -137,7 +137,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int fib(int N) { diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md index 45648e2f..bca7e074 100644 --- a/problems/0513.找树左下角的值.md +++ b/problems/0513.找树左下角的值.md @@ -55,7 +55,7 @@ 代码如下: -```C++ +```CPP int maxLen = INT_MIN; // 全局变量 记录最大深度 int maxleftValue; // 全局变量 最大深度最左节点的数值 void traversal(TreeNode* root, int leftLen) @@ -77,7 +77,7 @@ void traversal(TreeNode* root, int leftLen) 代码如下: -```C++ +```CPP if (root->left == NULL && root->right == NULL) { if (leftLen > maxLen) { maxLen = leftLen; // 更新最大深度 @@ -91,7 +91,7 @@ if (root->left == NULL && root->right == NULL) { 在找最大深度的时候,递归的过程中依然要使用回溯,代码如下: -```C++ +```CPP // 中 if (root->left) { // 左 leftLen++; // 深度加一 @@ -108,7 +108,7 @@ return; 完整代码如下: -```C++ +```CPP class Solution { public: int maxLen = INT_MIN; @@ -142,7 +142,7 @@ public: 当然回溯的地方可以精简,精简代码如下: -```C++ +```CPP class Solution { public: int maxLen = INT_MIN; @@ -183,7 +183,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int findBottomLeftValue(TreeNode* root) { diff --git a/problems/0516.最长回文子序列.md b/problems/0516.最长回文子序列.md index 9ec48145..54cea10e 100644 --- a/problems/0516.最长回文子序列.md +++ b/problems/0516.最长回文子序列.md @@ -69,7 +69,7 @@ 代码如下: -```C++ +```CPP if (s[i] == s[j]) { dp[i][j] = dp[i + 1][j - 1] + 2; } else { @@ -85,7 +85,7 @@ if (s[i] == s[j]) { 其他情况dp[i][j]初始为0就行,这样递推公式:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); 中dp[i][j]才不会被初始值覆盖。 -```C++ +```CPP vector> dp(s.size(), vector(s.size(), 0)); for (int i = 0; i < s.size(); i++) dp[i][i] = 1; ``` @@ -102,7 +102,7 @@ for (int i = 0; i < s.size(); i++) dp[i][i] = 1; 代码如下: -```C++ +```CPP for (int i = s.size() - 1; i >= 0; i--) { for (int j = i + 1; j < s.size(); j++) { if (s[i] == s[j]) { @@ -124,7 +124,7 @@ for (int i = s.size() - 1; i >= 0; i--) { 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int longestPalindromeSubseq(string s) { diff --git a/problems/0518.零钱兑换II.md b/problems/0518.零钱兑换II.md index 3e372fab..ea2b1777 100644 --- a/problems/0518.零钱兑换II.md +++ b/problems/0518.零钱兑换II.md @@ -111,7 +111,7 @@ dp[j] (考虑coins[i]的组合总和) 就是所有的dp[j - coins[i]](不 代码如下: -```C++ +```CPP for (int i = 0; i < coins.size(); i++) { // 遍历物品 for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量 dp[j] += dp[j - coins[i]]; @@ -151,7 +151,7 @@ for (int j = 0; j <= amount; j++) { // 遍历背包容量 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int change(int amount, vector& coins) { diff --git a/problems/0530.二叉搜索树的最小绝对差.md b/problems/0530.二叉搜索树的最小绝对差.md index 5a061734..04c03b3f 100644 --- a/problems/0530.二叉搜索树的最小绝对差.md +++ b/problems/0530.二叉搜索树的最小绝对差.md @@ -39,7 +39,7 @@ 代码如下: -```C++ +```CPP class Solution { private: vector vec; @@ -75,7 +75,7 @@ public: 代码如下: -```C++ +```CPP class Solution { private: int result = INT_MAX; @@ -105,7 +105,7 @@ public: 下面我给出其中的一种中序遍历的迭代法,代码如下: -```C++ +```CPP class Solution { public: int getMinimumDifference(TreeNode* root) { diff --git a/problems/0538.把二叉搜索树转换为累加树.md b/problems/0538.把二叉搜索树转换为累加树.md index fd1999ec..d22cb4bc 100644 --- a/problems/0538.把二叉搜索树转换为累加树.md +++ b/problems/0538.把二叉搜索树转换为累加树.md @@ -107,7 +107,7 @@ traversal(cur->left); // 左 递归法整体代码如下: -```C++ +```CPP class Solution { private: int pre; // 记录前一个节点的数值 @@ -133,7 +133,7 @@ public: 这里我给出其中的一种,代码如下: -```C++ +```CPP class Solution { private: int pre; // 记录前一个节点的数值 diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index 20e15254..ab1ef16a 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -46,7 +46,7 @@ https://leetcode-cn.com/problems/reverse-string-ii/ 使用C++库函数reverse的版本如下: -```C++ +```CPP class Solution { public: string reverseStr(string s, int k) { @@ -69,7 +69,7 @@ public: 下面我实现的reverse函数区间是左闭右闭区间,代码如下: -```C++ +```CPP class Solution { public: void reverse(string& s, int start, int end) { diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md index 926fda31..f6c13039 100644 --- a/problems/0583.两个字符串的删除操作.md +++ b/problems/0583.两个字符串的删除操作.md @@ -56,7 +56,7 @@ dp[i][0]:word2为空字符串,以i-1为结尾的字符串word2要删除多 dp[0][j]的话同理,所以代码如下: -```C++ +```CPP vector> dp(word1.size() + 1, vector(word2.size() + 1)); for (int i = 0; i <= word1.size(); i++) dp[i][0] = i; for (int j = 0; j <= word2.size(); j++) dp[0][j] = j; @@ -78,7 +78,7 @@ for (int j = 0; j <= word2.size(); j++) dp[0][j] = j; 以上分析完毕,代码如下: -```C++ +```CPP class Solution { public: int minDistance(string word1, string word2) { diff --git a/problems/0617.合并二叉树.md b/problems/0617.合并二叉树.md index 57d61ab3..b24a934b 100644 --- a/problems/0617.合并二叉树.md +++ b/problems/0617.合并二叉树.md @@ -90,7 +90,7 @@ return t1; 此时前序遍历,完整代码就写出来了,如下: -```C++ +```CPP class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { @@ -107,7 +107,7 @@ public: 那么中序遍历也是可以的,代码如下: -```C++ +```CPP class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { @@ -124,7 +124,7 @@ public: 后序遍历依然可以,代码如下: -```C++ +```CPP class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { @@ -145,7 +145,7 @@ public: 不修改输入树的结构,前序遍历,代码如下: -```C++ +```CPP class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { @@ -169,7 +169,7 @@ public: 本题我们也使用队列,模拟的层序遍历,代码如下: -```C++ +```CPP class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { @@ -216,7 +216,7 @@ public: 如下代码中,想要更改二叉树的值,应该传入指向指针的指针。 代码如下:(前序遍历) -```C++ +```CPP class Solution { public: void process(TreeNode** t1, TreeNode** t2) { diff --git a/problems/0647.回文子串.md b/problems/0647.回文子串.md index 22d8d0be..f81801b7 100644 --- a/problems/0647.回文子串.md +++ b/problems/0647.回文子串.md @@ -61,7 +61,7 @@ 以上三种情况分析完了,那么递归公式如下: -```C++ +```CPP if (s[i] == s[j]) { if (j - i <= 1) { // 情况一 和 情况二 result++; @@ -101,7 +101,7 @@ dp[i + 1][j - 1] 在 dp[i][j]的左下角,如图: 代码如下: -```C++ +```CPP for (int i = s.size() - 1; i >= 0; i--) { // 注意遍历顺序 for (int j = i; j < s.size(); j++) { if (s[i] == s[j]) { @@ -129,7 +129,7 @@ for (int i = s.size() - 1; i >= 0; i--) { // 注意遍历顺序 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int countSubstrings(string s) { @@ -154,7 +154,7 @@ public: ``` 以上代码是为了凸显情况一二三,当然是可以简洁一下的,如下: -```C++ +```CPP class Solution { public: int countSubstrings(string s) { @@ -192,7 +192,7 @@ public: **这两种情况可以放在一起计算,但分别计算思路更清晰,我倾向于分别计算**,代码如下: -```C++ +```CPP class Solution { public: int countSubstrings(string s) { diff --git a/problems/0649.Dota2参议院.md b/problems/0649.Dota2参议院.md index 5015ab61..b73686c4 100644 --- a/problems/0649.Dota2参议院.md +++ b/problems/0649.Dota2参议院.md @@ -78,7 +78,7 @@ Dota2 参议院由来自两派的参议员组成。现在参议院希望对一 C++代码如下: -```C++ +```CPP class Solution { public: string predictPartyVictory(string senate) { diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md index 361c4a1f..8c310a21 100644 --- a/problems/0654.最大二叉树.md +++ b/problems/0654.最大二叉树.md @@ -107,7 +107,7 @@ if (maxValueIndex < (nums.size() - 1)) { ``` 这样我们就分析完了,整体代码如下:(详细注释) -```C++ +```CPP class Solution { public: TreeNode* constructMaximumBinaryTree(vector& nums) { @@ -147,7 +147,7 @@ public: 优化后代码如下: -```C++ +```CPP class Solution { private: // 在左闭右开区间[left, right),构造二叉树 @@ -182,7 +182,7 @@ public: 可以发现上面的代码看上去简洁一些,**主要是因为第二版其实是允许空节点进入递归,所以不用在递归的时候加判断节点是否为空** 第一版递归过程:(加了if判断,为了不让空节点进入递归) -```C++ +```CPP if (maxValueIndex > 0) { // 这里加了判断是为了不让空节点进入递归 vector newVec(nums.begin(), nums.begin() + maxValueIndex); diff --git a/problems/0657.机器人能否返回原点.md b/problems/0657.机器人能否返回原点.md index 796cd579..480e830f 100644 --- a/problems/0657.机器人能否返回原点.md +++ b/problems/0657.机器人能否返回原点.md @@ -48,7 +48,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: bool judgeCircle(string moves) { diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index 0dc48f87..3b315350 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -32,7 +32,7 @@ 不难写出如下代码: -```C++ +```CPP class Solution { public: TreeNode* trimBST(TreeNode* root, int low, int high) { @@ -145,7 +145,7 @@ root->left = trimBST(root->left, low, high); 最后整体代码如下: -```C++ +```CPP class Solution { public: TreeNode* trimBST(TreeNode* root, int low, int high) { @@ -167,7 +167,7 @@ public: 精简之后代码如下: -```C++ +```CPP class Solution { public: TreeNode* trimBST(TreeNode* root, int low, int high) { @@ -195,7 +195,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: TreeNode* trimBST(TreeNode* root, int L, int R) { diff --git a/problems/0673.最长递增子序列的个数.md b/problems/0673.最长递增子序列的个数.md index bc56b8c9..ce3e8639 100644 --- a/problems/0673.最长递增子序列的个数.md +++ b/problems/0673.最长递增子序列的个数.md @@ -58,7 +58,7 @@ if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1); 代码如下: -```C++ +```CPP if (nums[i] > nums[j]) { if (dp[j] + 1 > dp[i]) { count[i] = count[j]; @@ -71,7 +71,7 @@ if (nums[i] > nums[j]) { 当然也可以这么写: -```C++ +```CPP if (nums[i] > nums[j]) { if (dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; // 更新dp[i]放在这里,就不用max了 @@ -88,7 +88,7 @@ if (nums[i] > nums[j]) { 代码如下: -```C++ +```CPP for (int i = 1; i < nums.size(); i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { @@ -131,7 +131,7 @@ dp[i] 是由0到i-1各个位置的最长升序子序列 推导而来,那么遍 j其实就是0到i-1,遍历i的循环里外层,遍历j则在内层,代码如下: -```C++ +```CPP for (int i = 1; i < nums.size(); i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { @@ -152,7 +152,7 @@ for (int i = 1; i < nums.size(); i++) { 代码如下: -```C++ +```CPP for (int i = 1; i < nums.size(); i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { @@ -184,7 +184,7 @@ for (int i = 0; i < nums.size(); i++) { 以上分析完毕,C++整体代码如下: -```C++ +```CPP class Solution { public: int findNumberOfLIS(vector& nums) { diff --git a/problems/0674.最长连续递增序列.md b/problems/0674.最长连续递增序列.md index b8fc738a..0fe1c49a 100644 --- a/problems/0674.最长连续递增序列.md +++ b/problems/0674.最长连续递增序列.md @@ -73,7 +73,7 @@ 本文在确定递推公式的时候也说明了为什么本题只需要一层for循环,代码如下: -```C++ +```CPP for (int i = 0; i < nums.size() - 1; i++) { if (nums[i + 1] > nums[i]) { // 连续记录 dp[i + 1] = dp[i] + 1; // 递推公式 @@ -91,7 +91,7 @@ for (int i = 0; i < nums.size() - 1; i++) { 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int findLengthOfLCIS(vector& nums) { @@ -118,7 +118,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: int findLengthOfLCIS(vector& nums) { diff --git a/problems/0684.冗余连接.md b/problems/0684.冗余连接.md index 20e80806..c9eb33c4 100644 --- a/problems/0684.冗余连接.md +++ b/problems/0684.冗余连接.md @@ -37,7 +37,7 @@ 这里整理出我的并查集模板如下: -```C++ +```CPP int n = 1005; // 节点数量3 到 1000 int father[1005]; @@ -88,7 +88,7 @@ bool same(int u, int v) { 并查集C++代码如下: -```C++ +```CPP class Solution { private: int n = 1005; // 节点数量3 到 1000 diff --git a/problems/0685.冗余连接II.md b/problems/0685.冗余连接II.md index cde55a6e..e282e620 100644 --- a/problems/0685.冗余连接II.md +++ b/problems/0685.冗余连接II.md @@ -58,7 +58,7 @@ 首先先计算节点的入度,代码如下: -```C++ +```CPP int inDegree[N] = {0}; // 记录节点入度 n = edges.size(); // 边的数量 for (int i = 0; i < n; i++) { @@ -70,7 +70,7 @@ for (int i = 0; i < n; i++) { 代码如下: -```C++ +```CPP vector vec; // 记录入度为2的边(如果有的话就两条边) // 找入度为2的节点所对应的边,注意要倒叙,因为优先返回最后出现在二维数组中的答案 for (int i = n - 1; i >= 0; i--) { @@ -112,7 +112,7 @@ vector getRemoveEdge(const vector>& edges) 本题C++代码如下:(详细注释了) -```C++ +```CPP class Solution { private: static const int N = 1010; // 如题:二维数组大小的在3到1000范围内 diff --git a/problems/0700.二叉搜索树中的搜索.md b/problems/0700.二叉搜索树中的搜索.md index 3bcf231c..68d30e3f 100644 --- a/problems/0700.二叉搜索树中的搜索.md +++ b/problems/0700.二叉搜索树中的搜索.md @@ -79,7 +79,7 @@ return NULL; 整体代码如下: -```C++ +```CPP class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { @@ -109,7 +109,7 @@ public: 所以迭代法代码如下: -```C++ +```CPP class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md index 68907056..fdaba43e 100644 --- a/problems/0701.二叉搜索树中的插入操作.md +++ b/problems/0701.二叉搜索树中的插入操作.md @@ -96,7 +96,7 @@ return root; 整体代码如下: -```C++ +```CPP class Solution { public: TreeNode* insertIntoBST(TreeNode* root, int val) { @@ -126,7 +126,7 @@ void traversal(TreeNode* cur, int val) 代码如下: -```C++ +```CPP class Solution { private: TreeNode* parent; @@ -172,7 +172,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: TreeNode* insertIntoBST(TreeNode* root, int val) { diff --git a/problems/0704.二分查找.md b/problems/0704.二分查找.md index 02c231bc..2efbd7c4 100644 --- a/problems/0704.二分查找.md +++ b/problems/0704.二分查找.md @@ -63,7 +63,7 @@ 代码如下:(详细注释) -```C++ +```CPP // 版本一 class Solution { public: @@ -102,7 +102,7 @@ public: 代码如下:(详细注释) -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 90f6bcf9..0aa038e8 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -56,7 +56,7 @@ https://leetcode-cn.com/problems/design-linked-list/ ## 代码 -```C++ +```CPP class MyLinkedList { public: // 定义链表节点结构体 diff --git a/problems/0714.买卖股票的最佳时机含手续费.md b/problems/0714.买卖股票的最佳时机含手续费.md index 450976a4..6dc95a2d 100644 --- a/problems/0714.买卖股票的最佳时机含手续费.md +++ b/problems/0714.买卖股票的最佳时机含手续费.md @@ -60,7 +60,7 @@ 贪心算法C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices, int fee) { @@ -101,7 +101,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices, int fee) { @@ -126,7 +126,7 @@ public: C++ 代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices, int fee) { diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md index c75d596e..53952a7f 100644 --- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md +++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md @@ -72,7 +72,7 @@ dp[i][1] 表示第i天不持有股票所得最多现金 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices, int fee) { diff --git a/problems/0718.最长重复子数组.md b/problems/0718.最长重复子数组.md index b60585e3..2fe38f0a 100644 --- a/problems/0718.最长重复子数组.md +++ b/problems/0718.最长重复子数组.md @@ -74,7 +74,7 @@ dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最 代码如下: -```C++ +```CPP for (int i = 1; i <= A.size(); i++) { for (int j = 1; j <= B.size(); j++) { if (A[i - 1] == B[j - 1]) { @@ -94,7 +94,7 @@ for (int i = 1; i <= A.size(); i++) { 以上五部曲分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int findLength(vector& A, vector& B) { @@ -128,7 +128,7 @@ public: **此时遍历B数组的时候,就要从后向前遍历,这样避免重复覆盖**。 -```C++ +```CPP class Solution { public: int findLength(vector& A, vector& B) { diff --git a/problems/0724.寻找数组的中心索引.md b/problems/0724.寻找数组的中心索引.md index 45a9c05c..3ed68d47 100644 --- a/problems/0724.寻找数组的中心索引.md +++ b/problems/0724.寻找数组的中心索引.md @@ -43,7 +43,7 @@ * 判断leftSum和rightSum是否相同 C++代码如下: -```C++ +```CPP class Solution { public: int pivotIndex(vector& nums) { diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index 169fe2ca..7cb24236 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -34,7 +34,7 @@ 题意很简单,那么首先想的就是暴力解法了,来我替大家暴力一波,结果自然是超时! 代码如下: -```C++ +```CPP class Solution { private: bool checkNum(int num) { @@ -87,7 +87,7 @@ public: C++代码如下: -```C++ +```CPP class Solution { public: int monotoneIncreasingDigits(int N) { diff --git a/problems/0739.每日温度.md b/problems/0739.每日温度.md index a023de35..ddcbe428 100644 --- a/problems/0739.每日温度.md +++ b/problems/0739.每日温度.md @@ -117,7 +117,7 @@ T[4]弹出之后, T[5] > T[3] (当前遍历的元素T[i]大于栈顶元素T[ C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -148,7 +148,7 @@ public: 精简代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index f039c502..9b691c5f 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -98,7 +98,7 @@ dp[1] = cost[1]; 以上分析完毕,整体C++代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -120,7 +120,7 @@ public: 还可以优化空间复杂度,因为dp[i]就是由前两位推出来的,那么也不用dp数组了,C++代码如下: -```C++ +```CPP // 版本二 class Solution { public: @@ -165,7 +165,7 @@ public: 所以代码这么写: -```C++ +```CPP class Solution { public: int minCostClimbingStairs(vector& cost) { diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index 40b241fe..ccf654d4 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -47,7 +47,7 @@ 明白原理之后,代码并不复杂,如下: -```C++ +```CPP class Solution { public: vector partitionLabels(string S) { diff --git a/problems/0841.钥匙和房间.md b/problems/0841.钥匙和房间.md index de49df3a..bd7c99c9 100644 --- a/problems/0841.钥匙和房间.md +++ b/problems/0841.钥匙和房间.md @@ -54,7 +54,7 @@ BFS C++代码代码如下: -```C++ +```CPP class Solution { bool bfs(const vector>& rooms) { vector visited(rooms.size(), 0); // 标记房间是否被访问过 @@ -89,7 +89,7 @@ public: DFS C++代码如下: -```C++ +```CPP class Solution { private: void dfs(int key, const vector>& rooms, vector& visited) { diff --git a/problems/0844.比较含退格的字符串.md b/problems/0844.比较含退格的字符串.md index ac94ea36..32232c4a 100644 --- a/problems/0844.比较含退格的字符串.md +++ b/problems/0844.比较含退格的字符串.md @@ -50,7 +50,7 @@ 代码如下: -```C++ +```CPP class Solution { public: bool backspaceCompare(string S, string T) { @@ -78,7 +78,7 @@ public: 当然以上代码,大家可以发现有重复的逻辑处理S,处理T,可以把这块公共逻辑抽离出来,代码精简如下: -```C++ +```CPP class Solution { private: string getString(const string& S) { @@ -115,7 +115,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: bool backspaceCompare(string S, string T) { diff --git a/problems/0860.柠檬水找零.md b/problems/0860.柠檬水找零.md index d5b87d82..792bee9a 100644 --- a/problems/0860.柠檬水找零.md +++ b/problems/0860.柠檬水找零.md @@ -82,7 +82,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: bool lemonadeChange(vector& bills) { diff --git a/problems/0922.按奇偶排序数组II.md b/problems/0922.按奇偶排序数组II.md index 4f4394ec..92db204d 100644 --- a/problems/0922.按奇偶排序数组II.md +++ b/problems/0922.按奇偶排序数组II.md @@ -32,7 +32,7 @@ 其实这道题可以用很朴实的方法,时间复杂度就就是O(n)了,C++代码如下: -```C++ +```CPP class Solution { public: vector sortArrayByParityII(vector& A) { @@ -64,7 +64,7 @@ public: 以上代码我是建了两个辅助数组,而且A数组还相当于遍历了两次,用辅助数组的好处就是思路清晰,优化一下就是不用这两个辅助树,代码如下: -```C++ +```CPP class Solution { public: vector sortArrayByParityII(vector& A) { @@ -93,7 +93,7 @@ public: 当然还可以在原数组上修改,连result数组都不用了。 -```C++ +```CPP class Solution { public: vector sortArrayByParityII(vector& A) { diff --git a/problems/0925.长按键入.md b/problems/0925.长按键入.md index be799163..4d3543f4 100644 --- a/problems/0925.长按键入.md +++ b/problems/0925.长按键入.md @@ -59,7 +59,7 @@ 上面的逻辑想清楚了,不难写出如下C++代码: -```C++ +```CPP class Solution { public: bool isLongPressedName(string name, string typed) { diff --git a/problems/0968.监控二叉树.md b/problems/0968.监控二叉树.md index 67bc9faa..380ca8f8 100644 --- a/problems/0968.监控二叉树.md +++ b/problems/0968.监控二叉树.md @@ -216,7 +216,7 @@ int minCameraCover(TreeNode* root) { ## C++代码 -```C++ +```CPP // 版本一 class Solution { private: @@ -270,7 +270,7 @@ public: 在以上代码的基础上,再进行精简,代码如下: -```C++ +```CPP // 版本二 class Solution { private: diff --git a/problems/0977.有序数组的平方.md b/problems/0977.有序数组的平方.md index 2f72acb7..9e71ec0d 100644 --- a/problems/0977.有序数组的平方.md +++ b/problems/0977.有序数组的平方.md @@ -29,7 +29,7 @@ https://leetcode-cn.com/problems/squares-of-a-sorted-array/ 最直观的相反,莫过于:每个数平方之后,排个序,美滋滋,代码如下: -```C++ +```CPP class Solution { public: vector sortedSquares(vector& A) { @@ -64,7 +64,7 @@ public: 不难写出如下代码: -```C++ +```CPP class Solution { public: vector sortedSquares(vector& A) { diff --git a/problems/1002.查找常用字符.md b/problems/1002.查找常用字符.md index faf2bea4..82dbf4cf 100644 --- a/problems/1002.查找常用字符.md +++ b/problems/1002.查找常用字符.md @@ -97,7 +97,7 @@ for (int i = 0; i < 26; i++) { 整体C++代码如下: -```C++ +```CPP class Solution { public: vector commonChars(vector& A) { diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 344aa681..a689fbf7 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -61,7 +61,7 @@ 对应C++代码如下: -```C++ +```CPP class Solution { static bool cmp(int a, int b) { return abs(a) > abs(b); diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index 9d30052a..3172cfc7 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -45,7 +45,7 @@ 本题代码如下: -```C++ +```CPP class Solution { public: int maxUncrossedLines(vector& A, vector& B) { diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index d42856cb..c4ae85c9 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -69,7 +69,7 @@ https://leetcode-cn.com/problems/remove-all-adjacent-duplicates-in-string/ C++代码 : -```C++ +```CPP class Solution { public: string removeDuplicates(string S) { @@ -97,7 +97,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: string removeDuplicates(string S) { diff --git a/problems/1049.最后一块石头的重量II.md b/problems/1049.最后一块石头的重量II.md index 06ca872b..7b71eae4 100644 --- a/problems/1049.最后一块石头的重量II.md +++ b/problems/1049.最后一块石头的重量II.md @@ -93,7 +93,7 @@ vector dp(15001, 0); 代码如下: -```C++ +```CPP for (int i = 0; i < stones.size(); i++) { // 遍历物品 for (int j = target; j >= stones[i]; j--) { // 遍历背包 dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]); @@ -119,7 +119,7 @@ for (int i = 0; i < stones.size(); i++) { // 遍历物品 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int lastStoneWeightII(vector& stones) { diff --git a/problems/1143.最长公共子序列.md b/problems/1143.最长公共子序列.md index fc38f34a..c0468d08 100644 --- a/problems/1143.最长公共子序列.md +++ b/problems/1143.最长公共子序列.md @@ -65,7 +65,7 @@ dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符 代码如下: -```C++ +```CPP if (text1[i - 1] == text2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { @@ -107,7 +107,7 @@ vector> dp(text1.size() + 1, vector(text2.size() + 1, 0)); 以上分析完毕,C++代码如下: -```C++ +```CPP class Solution { public: int longestCommonSubsequence(string text1, string text2) { diff --git a/problems/1207.独一无二的出现次数.md b/problems/1207.独一无二的出现次数.md index 84ddfa5c..1c09ee8a 100644 --- a/problems/1207.独一无二的出现次数.md +++ b/problems/1207.独一无二的出现次数.md @@ -53,7 +53,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: bool uniqueOccurrences(vector& arr) { diff --git a/problems/1356.根据数字二进制下1的数目排序.md b/problems/1356.根据数字二进制下1的数目排序.md index 2e7e8aae..300aa0e2 100644 --- a/problems/1356.根据数字二进制下1的数目排序.md +++ b/problems/1356.根据数字二进制下1的数目排序.md @@ -68,7 +68,7 @@ sort(vec.begin(), vec.end()); // 从小到大排序之后,元素下标就是 这里就需要一个技巧了,**在构造数组hash的时候,从后向前遍历,这样hash里存放的就是相同元素最左面的数值和下标了**。 代码如下: -```C++ +```CPP int hash[101]; for (int i = vec.size() - 1; i >= 0; i--) { // 从后向前,记录 vec[i] 对应的下标 hash[vec[i]] = i; @@ -79,7 +79,7 @@ for (int i = vec.size() - 1; i >= 0; i--) { // 从后向前,记录 vec[i] 对 代码如下: -```C++ +```CPP // 此时hash里保存的每一个元素数值 对应的 小于这个数值的个数 for (int i = 0; i < nums.size(); i++) { vec[i] = hash[nums[i]]; @@ -92,7 +92,7 @@ for (int i = 0; i < nums.size(); i++) { 关键地方讲完了,整体C++代码如下: -```C++ +```CPP class Solution { public: vector smallerNumbersThanCurrent(vector& nums) { diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 4a5f08a0..156efea6 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -69,7 +69,7 @@ sort(vec.begin(), vec.end()); // 从小到大排序之后,元素下标就是 这里就需要一个技巧了,**在构造数组hash的时候,从后向前遍历,这样hash里存放的就是相同元素最左面的数值和下标了**。 代码如下: -```C++ +```CPP int hash[101]; for (int i = vec.size() - 1; i >= 0; i--) { // 从后向前,记录 vec[i] 对应的下标 hash[vec[i]] = i; @@ -80,7 +80,7 @@ for (int i = vec.size() - 1; i >= 0; i--) { // 从后向前,记录 vec[i] 对 代码如下: -```C++ +```CPP // 此时hash里保存的每一个元素数值 对应的 小于这个数值的个数 for (int i = 0; i < nums.size(); i++) { vec[i] = hash[nums[i]]; @@ -93,7 +93,7 @@ for (int i = 0; i < nums.size(); i++) { 关键地方讲完了,整体C++代码如下: -```C++ +```CPP class Solution { public: vector smallerNumbersThanCurrent(vector& nums) { diff --git a/problems/1382.将二叉搜索树变平衡.md b/problems/1382.将二叉搜索树变平衡.md index 683f482f..b9d4fb65 100644 --- a/problems/1382.将二叉搜索树变平衡.md +++ b/problems/1382.将二叉搜索树变平衡.md @@ -42,7 +42,7 @@ 代码如下: -```C++ +```CPP class Solution { private: vector vec; diff --git a/problems/O(n)的算法居然超时了,此时的n究竟是多大?.md b/problems/O(n)的算法居然超时了,此时的n究竟是多大?.md index 319e0950..6897c01f 100644 --- a/problems/O(n)的算法居然超时了,此时的n究竟是多大?.md +++ b/problems/O(n)的算法居然超时了,此时的n究竟是多大?.md @@ -67,7 +67,7 @@ 实现三个函数,时间复杂度分别是 O(n) , O(n^2), O(nlogn),使用加法运算来统一测试。 -```C++ +```CPP // O(n) void function1(long long n) { long long k = 0; @@ -78,7 +78,7 @@ void function1(long long n) { ``` -```C++ +```CPP // O(n^2) void function2(long long n) { long long k = 0; @@ -91,7 +91,7 @@ void function2(long long n) { } ``` -```C++ +```CPP // O(nlogn) void function3(long long n) { long long k = 0; @@ -105,7 +105,7 @@ void function3(long long n) { ``` 来看一下这三个函数随着n的规模变化,耗时会产生多大的变化,先测function1 ,就把 function2 和 function3 注释掉 -```C++ +```CPP int main() { long long n; // 数据规模 while (1) { @@ -154,7 +154,7 @@ O(nlogn)的算法,1s内大概计算机可以运行 2 * (10^7)次计算,符 # 完整测试代码 -```C++ +```CPP #include #include #include diff --git a/problems/为了绝杀编辑距离,卡尔做了三步铺垫.md b/problems/为了绝杀编辑距离,卡尔做了三步铺垫.md index aa818a5d..4a0ef0d2 100644 --- a/problems/为了绝杀编辑距离,卡尔做了三步铺垫.md +++ b/problems/为了绝杀编辑距离,卡尔做了三步铺垫.md @@ -58,7 +58,7 @@ else dp[i][j] = dp[i][j - 1]; 状态转移方程: -```C++ +```CPP if (s[i - 1] == t[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; } else { @@ -89,7 +89,7 @@ if (s[i - 1] == t[j - 1]) { 那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1}); 状态转移方程: -```C++ +```CPP if (word1[i - 1] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { @@ -150,7 +150,7 @@ if (word1[i - 1] != word2[j - 1]),此时就需要编辑了,如何编辑呢 递归公式代码如下: -```C++ +```CPP if (word1[i - 1] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } diff --git a/problems/二叉树中递归带着回溯.md b/problems/二叉树中递归带着回溯.md index 61e590d5..0f768e0f 100644 --- a/problems/二叉树中递归带着回溯.md +++ b/problems/二叉树中递归带着回溯.md @@ -19,7 +19,7 @@ 那么如下我再给出求100. 相同的树 的代码,如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* tree1, TreeNode* tree2) { @@ -52,7 +52,7 @@ public: 如下的代码充分的体现出回溯:(257. 二叉树的所有路径) -```C++ +```CPP class Solution { private: @@ -120,13 +120,13 @@ public: 为了把这份精简代码的回溯过程展现出来,大家可以试一试把: -```C++ +```CPP if (cur->left) traversal(cur->left, path + "->", result); // 左 回溯就隐藏在这里 ``` 改成如下代码: -```C++ +```CPP path += "->"; traversal(cur->left, path, result); // 左 ``` @@ -149,7 +149,7 @@ if (cur->right) { 如果想把回溯加上,就要 在上面代码的基础上,加上回溯,就可以AC了。 -```C++ +```CPP if (cur->left) { path += "->"; traversal(cur->left, path, result); // 左 diff --git a/problems/二叉树的统一迭代法.md b/problems/二叉树的统一迭代法.md index 6119bc69..d105f4b8 100644 --- a/problems/二叉树的统一迭代法.md +++ b/problems/二叉树的统一迭代法.md @@ -34,7 +34,7 @@ 中序遍历代码如下:(详细注释) -```C++ +```CPP class Solution { public: vector inorderTraversal(TreeNode* root) { @@ -77,7 +77,7 @@ public: 迭代法前序遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**) -```C++ +```CPP class Solution { public: vector preorderTraversal(TreeNode* root) { @@ -108,7 +108,7 @@ public: 后续遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**) -```C++ +```CPP class Solution { public: vector postorderTraversal(TreeNode* root) { diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index d4dadd7c..faa580e0 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -37,7 +37,7 @@ 不难写出如下代码: (**注意代码中空节点不入栈**) -```C++ +```CPP class Solution { public: vector preorderTraversal(TreeNode* root) { @@ -84,7 +84,7 @@ public: **中序遍历,可以写出如下代码:** -```C++ +```CPP class Solution { public: vector inorderTraversal(TreeNode* root) { @@ -116,7 +116,7 @@ public: **所以后序遍历只需要前序遍历的代码稍作修改就可以了,代码如下:** -```C++ +```CPP class Solution { public: vector postorderTraversal(TreeNode* root) { diff --git a/problems/二叉树的递归遍历.md b/problems/二叉树的递归遍历.md index 6d91e115..223cf722 100644 --- a/problems/二叉树的递归遍历.md +++ b/problems/二叉树的递归遍历.md @@ -58,7 +58,7 @@ traversal(cur->right, vec); // 右 前序遍历: -```C++ +```CPP class Solution { public: void traversal(TreeNode* cur, vector& vec) { @@ -79,7 +79,7 @@ public: 中序遍历: -```C++ +```CPP void traversal(TreeNode* cur, vector& vec) { if (cur == NULL) return; traversal(cur->left, vec); // 左 @@ -90,7 +90,7 @@ void traversal(TreeNode* cur, vector& vec) { 后序遍历: -```C++ +```CPP void traversal(TreeNode* cur, vector& vec) { if (cur == NULL) return; traversal(cur->left, vec); // 左 diff --git a/problems/前序/On的算法居然超时了,此时的n究竟是多大?.md b/problems/前序/On的算法居然超时了,此时的n究竟是多大?.md index 5c438120..d9cc8d45 100644 --- a/problems/前序/On的算法居然超时了,此时的n究竟是多大?.md +++ b/problems/前序/On的算法居然超时了,此时的n究竟是多大?.md @@ -67,7 +67,7 @@ 实现三个函数,时间复杂度分别是 O(n) , O(n^2), O(nlogn),使用加法运算来统一测试。 -```C++ +```CPP // O(n) void function1(long long n) { long long k = 0; @@ -78,7 +78,7 @@ void function1(long long n) { ``` -```C++ +```CPP // O(n^2) void function2(long long n) { long long k = 0; @@ -91,7 +91,7 @@ void function2(long long n) { } ``` -```C++ +```CPP // O(nlogn) void function3(long long n) { long long k = 0; @@ -105,7 +105,7 @@ void function3(long long n) { ``` 来看一下这三个函数随着n的规模变化,耗时会产生多大的变化,先测function1 ,就把 function2 和 function3 注释掉 -```C++ +```CPP int main() { long long n; // 数据规模 while (1) { @@ -154,7 +154,7 @@ O(nlogn)的算法,1s内大概计算机可以运行 2 * (10^7)次计算,符 # 完整测试代码 -```C++ +```CPP #include #include #include diff --git a/problems/前序/什么是核心代码模式,什么又是ACM模式?.md b/problems/前序/什么是核心代码模式,什么又是ACM模式?.md index 29e45f9a..3c5fb4e4 100644 --- a/problems/前序/什么是核心代码模式,什么又是ACM模式?.md +++ b/problems/前序/什么是核心代码模式,什么又是ACM模式?.md @@ -13,7 +13,7 @@ 而力扣上是核心代码模式,就是把要处理的数据都已经放入容器里,可以直接写逻辑,例如这样: -```C++ +```CPP class Solution { public: int minimumTotal(vector>& triangle) { @@ -55,7 +55,7 @@ public: 这道题如果要是力扣上的核心代码模式,OJ应该直接给出如下代码: -```C++ +```CPP class Solution { public: int getDays(vector& work, vector& gym) { @@ -72,7 +72,7 @@ ACM模式要求写出来的代码是直接可以本地运行的,所以我们 拿本题来说,为了让代码可以运行,需要include这些库函数: -```C++ +```CPP #include #include using namespace std; @@ -87,7 +87,7 @@ using namespace std; 完整代码如下: -```C++ +```CPP #include #include using namespace std; diff --git a/problems/前序/代码风格.md b/problems/前序/代码风格.md index 4c240080..a71ac420 100644 --- a/problems/前序/代码风格.md +++ b/problems/前序/代码风格.md @@ -108,7 +108,7 @@ while (n) { ``` 以下是我刚写的力扣283.移动零的代码,大家可以看一下整体风格,注意空格的细节! -```C++ +```CPP class Solution { public: void moveZeroes(vector& nums) { diff --git a/problems/前序/关于空间复杂度,可能有几个疑问?.md b/problems/前序/关于空间复杂度,可能有几个疑问?.md index 8ff891b4..0f25f378 100644 --- a/problems/前序/关于空间复杂度,可能有几个疑问?.md +++ b/problems/前序/关于空间复杂度,可能有几个疑问?.md @@ -42,7 +42,7 @@ 来看一下例子,什么时候的空间复杂度是O(1)呢,C++代码如下: -```C++ +```CPP int j = 0; for (int i = 0; i < n; i++) { j++; @@ -54,7 +54,7 @@ for (int i = 0; i < n; i++) { 什么时候的空间复杂度是O(n)? 当消耗空间和输入参数n保持线性增长,这样的空间复杂度为O(n),来看一下这段C++代码 -```C++ +```CPP int* a = new int(n); for (int i = 0; i < n; i++) { a[i] = i; diff --git a/problems/前序/刷了这么多题,你了解自己代码的内存消耗么?.md b/problems/前序/刷了这么多题,你了解自己代码的内存消耗么?.md index b7b6dd4d..3fccfb22 100644 --- a/problems/前序/刷了这么多题,你了解自己代码的内存消耗么?.md +++ b/problems/前序/刷了这么多题,你了解自己代码的内存消耗么?.md @@ -77,7 +77,7 @@ 可以看一下这段C++代码输出的各个数据类型大小是多少? -```C++ +```CPP struct node{ int num; char cha; diff --git a/problems/前序/力扣上的代码想在本地编译运行?.md b/problems/前序/力扣上的代码想在本地编译运行?.md index 7105db84..a0fcbcd8 100644 --- a/problems/前序/力扣上的代码想在本地编译运行?.md +++ b/problems/前序/力扣上的代码想在本地编译运行?.md @@ -27,7 +27,7 @@ 力扣746. 使用最小花费爬楼梯,完整的可以在直接本地运行的C++代码如下: -```C++ +```CPP #include #include using namespace std; diff --git a/problems/前序/递归算法的时间与空间复杂度分析.md b/problems/前序/递归算法的时间与空间复杂度分析.md index 03323d3a..b6c79f25 100644 --- a/problems/前序/递归算法的时间与空间复杂度分析.md +++ b/problems/前序/递归算法的时间与空间复杂度分析.md @@ -18,7 +18,7 @@ 先来看一下求斐波那契数的递归写法。 -```C++ +```CPP int fibonacci(int i) { if(i <= 0) return 0; if(i == 1) return 1; @@ -50,7 +50,7 @@ int fibonacci(int i) { 以下为C++代码,来测一下,让我们输入n的时候,这段递归求斐波那契代码的耗时。 -```C++ +```CPP #include #include #include @@ -99,7 +99,7 @@ int main() 其实罪魁祸首就是这里的两次递归,导致了时间复杂度以指数上升。 -```C++ +```CPP return fibonacci(i-1) + fibonacci(i-2); ``` @@ -107,7 +107,7 @@ return fibonacci(i-1) + fibonacci(i-2); 来看一下如下代码: -```C++ +```CPP // 版本二 int fibonacci(int first, int second, int n) { if (n <= 0) { @@ -138,7 +138,7 @@ int fibonacci(int first, int second, int n) { 此时再来测一下耗时情况验证一下: -```C++ +```CPP #include #include #include @@ -208,7 +208,7 @@ int main() 那么每次递归的空间复杂度是O(1), 调用栈深度为n,所以这段递归代码的空间复杂度就是O(n)。 -```C++ +```CPP int fibonacci(int i) { if(i <= 0) return 0; if(i == 1) return 1; @@ -227,7 +227,7 @@ int fibonacci(int i) { 带大家再分析一段二分查找的递归实现。 -```C++ +```CPP int binary_search( int arr[], int l, int r, int x) { if (r >= l) { int mid = l + (r - l) / 2; diff --git a/problems/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.md b/problems/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.md index cb3d6a4b..b3aef43c 100644 --- a/problems/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.md +++ b/problems/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.md @@ -27,7 +27,7 @@ 想一下这么简单的一道题目,代码应该如何写呢。最直观的方式应该就是,一个for循环求出结果,代码如下: -```C++ +```CPP int function1(int x, int n) { int result = 1; // 注意 任何数的0次方等于1 for (int i = 0; i < n; i++) { @@ -44,7 +44,7 @@ int function1(int x, int n) { 那么就可以写出了如下这样的一个递归的算法,使用递归解决了这个问题。 -```C++ +```CPP int function2(int x, int n) { if (n == 0) { return 1; // return 1 同样是因为0次方是等于1的 @@ -62,7 +62,7 @@ int function2(int x, int n) { 这个时间复杂度就没有达到面试官的预期。于是又写出了如下的递归算法的代码: -```C++ +```CPP int function3(int x, int n) { if (n == 0) { return 1; @@ -101,7 +101,7 @@ int function3(int x, int n) { 于是又写出如下递归算法的代码: -```C++ +```CPP int function4(int x, int n) { if (n == 0) { return 1; @@ -132,7 +132,7 @@ int function4(int x, int n) { 对于function3 这样的递归实现,很容易让人感觉这是O(logn)的时间复杂度,其实这是O(n)的算法! -```C++ +```CPP int function3(int x, int n) { if (n == 0) { return 1; diff --git a/problems/剑指Offer05.替换空格.md b/problems/剑指Offer05.替换空格.md index 4f991602..4ae5f9f2 100644 --- a/problems/剑指Offer05.替换空格.md +++ b/problems/剑指Offer05.替换空格.md @@ -46,7 +46,7 @@ i指向新长度的末尾,j指向旧长度的末尾。 C++代码如下: -```C++ +```CPP class Solution { public: string replaceSpace(string s) { diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md index 4a756e82..76908f2d 100644 --- a/problems/剑指Offer58-II.左旋转字符串.md +++ b/problems/剑指Offer58-II.左旋转字符串.md @@ -58,7 +58,7 @@ https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/ C++代码如下: -```C++ +```CPP class Solution { public: string reverseLeftWords(string s, int n) { diff --git a/problems/动态规划-股票问题总结篇.md b/problems/动态规划-股票问题总结篇.md index 0edf8d49..d186aaf9 100644 --- a/problems/动态规划-股票问题总结篇.md +++ b/problems/动态规划-股票问题总结篇.md @@ -24,7 +24,7 @@ 【贪心解法】 取最左最小值,取最右最大值,那么得到的差值就是最大利润,代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -56,7 +56,7 @@ public: 代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -79,7 +79,7 @@ public: 使用滚动数组,代码如下: -```C++ +```CPP // 版本二 class Solution { public: @@ -110,7 +110,7 @@ public: 收集每天的正利润便可,代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -146,7 +146,7 @@ dp数组定义: 代码如下:(注意代码中的注释,标记了和121.买卖股票的最佳时机唯一不同的地方) -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -204,7 +204,7 @@ dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]); 代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -230,7 +230,7 @@ public: 当然,大家可以看到力扣官方题解里的一种优化空间写法,我这里给出对应的C++版本: -```C++ +```CPP // 版本二 class Solution { public: @@ -291,7 +291,7 @@ dp[i][2] = max(dp[i - 1][i] + prices[i], dp[i][2]) 同理可以类比剩下的状态,代码如下: -```C++ +```CPP for (int j = 0; j < 2 * k - 1; j += 2) { dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]); dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]); @@ -300,7 +300,7 @@ for (int j = 0; j < 2 * k - 1; j += 2) { 整体代码如下: -```C++ +```CPP class Solution { public: int maxProfit(int k, vector& prices) { @@ -375,7 +375,7 @@ p[i][3] = dp[i - 1][2]; 综上分析,递推代码如下: -```C++ +```CPP dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3]- prices[i], dp[i - 1][1]) - prices[i]; dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]); dp[i][2] = dp[i - 1][0] + prices[i]; @@ -384,7 +384,7 @@ dp[i][3] = dp[i - 1][2]; 整体代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -439,7 +439,7 @@ dp[i][1] 表示第i天不持有股票所得最多现金 以上分析完毕,代码如下: -```C++ +```CPP class Solution { public: int maxProfit(vector& prices, int fee) { diff --git a/problems/周总结/20200927二叉树周末总结.md b/problems/周总结/20200927二叉树周末总结.md index 1f5768ab..f81cc6bb 100644 --- a/problems/周总结/20200927二叉树周末总结.md +++ b/problems/周总结/20200927二叉树周末总结.md @@ -13,7 +13,7 @@ 对于二叉树节点的定义,C++代码如下: -```C++ +```CPP struct TreeNode { int val; TreeNode *left; @@ -35,7 +35,7 @@ TreeNode* a = new TreeNode(9); 没有构造函数的话就要这么写: -```C++ +```CPP TreeNode* a = new TreeNode(); a->val = 9; a->left = NULL; @@ -66,7 +66,7 @@ morris遍历是二叉树遍历算法的超强进阶算法,morris遍历可以 拿前序遍历来举例,空节点入栈: -```C++ +```CPP class Solution { public: vector preorderTraversal(TreeNode* root) { @@ -88,7 +88,7 @@ public: 前序遍历空节点不入栈的代码:(注意注释部分和上文的区别) -```C++ +```CPP class Solution { public: vector preorderTraversal(TreeNode* root) { diff --git a/problems/周总结/20201003二叉树周末总结.md b/problems/周总结/20201003二叉树周末总结.md index 6626c27e..db89fc82 100644 --- a/problems/周总结/20201003二叉树周末总结.md +++ b/problems/周总结/20201003二叉树周末总结.md @@ -21,7 +21,7 @@ 100.相同的树的递归代码如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* left, TreeNode* right) { @@ -48,7 +48,7 @@ public: 100.相同的树,精简之后代码如下: -```C++ +```CPP class Solution { public: bool compare(TreeNode* left, TreeNode* right) { @@ -67,7 +67,7 @@ public: 100.相同的树,迭代法代码如下: -```C++ +```CPP class Solution { public: @@ -109,7 +109,7 @@ public: **而根节点的高度就是二叉树的最大深度**,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度,所以[二叉树:看看这些树的最大深度](https://mp.weixin.qq.com/s/guKwV-gSNbA1CcbvkMtHBg)中使用的是后序遍历。 本题当然也可以使用前序,代码如下:(**充分表现出求深度回溯的过程**) -```C++ +```CPP class Solution { public: int result; @@ -143,7 +143,7 @@ public: 注意以上代码是为了把细节体现出来,简化一下代码如下: -```C++ +```CPP class Solution { public: int result; @@ -223,12 +223,12 @@ public: 文中我明确的说了:**回溯就隐藏在traversal(cur->left, path + "->", result);中的 path + "->"。 每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。** 如果还不理解的话,可以把 -```C++ +```CPP traversal(cur->left, path + "->", result); ``` 改成 -```C++ +```CPP string tmp = path + "->"; traversal(cur->left, tmp, result); ``` diff --git a/problems/周总结/20201224贪心周末总结.md b/problems/周总结/20201224贪心周末总结.md index 6077a00a..a82433cf 100644 --- a/problems/周总结/20201224贪心周末总结.md +++ b/problems/周总结/20201224贪心周末总结.md @@ -31,7 +31,7 @@ 把[贪心算法:用最少数量的箭引爆气球](https://mp.weixin.qq.com/s/HxVAJ6INMfNKiGwI88-RFw)代码稍做修改,别可以AC本题。 修改后的C++代码如下: -```C++ +```CPP class Solution { public: // 按照区间左边界从大到小排序 diff --git a/problems/周总结/20210107动规周末总结.md b/problems/周总结/20210107动规周末总结.md index 3434fe96..67957f05 100644 --- a/problems/周总结/20210107动规周末总结.md +++ b/problems/周总结/20210107动规周末总结.md @@ -51,7 +51,7 @@ dp[0]其实就是一个无意义的存在,不用去初始化dp[0]。 一个严谨的思考过程,应该是初始化dp[1] = 1,dp[2] = 2,然后i从3开始遍历,代码如下: -```C++ +```CPP dp[1] = 1; dp[2] = 2; for (int i = 3; i <= n; i++) { // 注意i是从3开始的 @@ -67,7 +67,7 @@ for (int i = 3; i <= n; i++) { // 注意i是从3开始的 这里我先给出我的实现代码: -```C++ +```CPP class Solution { public: int climbStairs(int n) { @@ -122,7 +122,7 @@ public: 所以代码也可以这么写: -```C++ +```CPP class Solution { public: int minCostClimbingStairs(vector& cost) { diff --git a/problems/周总结/20210121动规周末总结.md b/problems/周总结/20210121动规周末总结.md index 4b63a3a3..bffe47fb 100644 --- a/problems/周总结/20210121动规周末总结.md +++ b/problems/周总结/20210121动规周末总结.md @@ -29,7 +29,7 @@ dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 3. dp数组如何初始化 -```C++ +```CPP // 初始化 dp vector> dp(weight.size() + 1, vector(bagWeight + 1, 0)); for (int j = bagWeight; j >= weight[0]; j--) { @@ -43,7 +43,7 @@ for (int j = bagWeight; j >= weight[0]; j--) { 但是先遍历物品更好理解。代码如下: -```C++ +```CPP // weight数组的大小 就是物品个数 for(int i = 1; i < weight.size(); i++) { // 遍历物品 for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 @@ -107,7 +107,7 @@ dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); 代码如下: -```C++ +```CPP for(int i = 0; i < weight.size(); i++) { // 遍历物品 for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); diff --git a/problems/周总结/20210128动规周末总结.md b/problems/周总结/20210128动规周末总结.md index bb08bc1f..bea4cc60 100644 --- a/problems/周总结/20210128动规周末总结.md +++ b/problems/周总结/20210128动规周末总结.md @@ -86,7 +86,7 @@ dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1); 完全背包的物品是可以添加多次的,所以遍历背包容量要从小到大去遍历,即: -```C++ +```CPP // 先遍历物品,再遍历背包 for(int i = 0; i < weight.size(); i++) { // 遍历物品 for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量 diff --git a/problems/周总结/20210204动规周末总结.md b/problems/周总结/20210204动规周末总结.md index 1341b83f..d2417f8f 100644 --- a/problems/周总结/20210204动规周末总结.md +++ b/problems/周总结/20210204动规周末总结.md @@ -20,7 +20,7 @@ 所以本题遍历顺序最终遍历顺序:**target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历**。 -```C++ +```CPP class Solution { public: int combinationSum4(vector& nums, int target) { @@ -56,7 +56,7 @@ public: 和昨天的题目[动态规划:377. 组合总和 Ⅳ](https://mp.weixin.qq.com/s/Iixw0nahJWQgbqVNk8k6gA)基本就是一道题了,遍历顺序也是一样一样的! 代码如下: -```C++ +```CPP class Solution { public: int climbStairs(int n) { @@ -93,7 +93,7 @@ public: 外层for循环遍历物品,内层for遍历背包: -```C++ +```CPP // 版本一 class Solution { public: @@ -115,7 +115,7 @@ public: 外层for遍历背包,内层for循环遍历物品: -```C++ +```CPP // 版本二 class Solution { public: @@ -148,7 +148,7 @@ public: 先遍历背包,在遍历物品: -```C++ +```CPP // 版本一 class Solution { public: @@ -167,7 +167,7 @@ public: 先遍历物品,在遍历背包: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/周总结/20210225动规周末总结.md b/problems/周总结/20210225动规周末总结.md index 7e6ed19b..ea3c5515 100644 --- a/problems/周总结/20210225动规周末总结.md +++ b/problems/周总结/20210225动规周末总结.md @@ -71,7 +71,7 @@ dp[1] = max(nums[0], nums[1]); 这道题目我给出了暴力的解法: -```C++ +```CPP class Solution { public: int rob(TreeNode* root) { @@ -94,7 +94,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: unordered_map umap; // 记录计算过的结果 @@ -120,7 +120,7 @@ public: 1. 确定递归函数的参数和返回值 -```C++ +```CPP vector robTree(TreeNode* cur) { ``` @@ -142,7 +142,7 @@ if (cur == NULL) return vector{0, 0}; 采用后序遍历,代码如下: -```C++ +```CPP // 下标0:不偷,下标1:偷 vector left = robTree(cur->left); // 左 vector right = robTree(cur->right); // 右 @@ -160,7 +160,7 @@ vector right = robTree(cur->right); // 右 代码如下: -```C++ +```CPP vector left = robTree(cur->left); // 左 vector right = robTree(cur->right); // 右 @@ -218,7 +218,7 @@ public: 因为股票就买卖一次,那么贪心的想法很自然就是取最左最小值,取最右最大值,那么得到的差值就是最大利润。 -```C++ +```CPP class Solution { public: int maxProfit(vector& prices) { @@ -237,7 +237,7 @@ public: 动规解法,版本一,代码如下: -```C++ +```CPP // 版本一 class Solution { public: @@ -262,7 +262,7 @@ public: 那么我们只需要记录 当前天的dp状态和前一天的dp状态就可以了,可以使用滚动数组来节省空间,代码如下: -```C++ +```CPP // 版本二 class Solution { public: diff --git a/problems/周总结/20210304动规周末总结.md b/problems/周总结/20210304动规周末总结.md index 37ad8499..9fea6244 100644 --- a/problems/周总结/20210304动规周末总结.md +++ b/problems/周总结/20210304动规周末总结.md @@ -110,7 +110,7 @@ j的状态表示为: 还要强调一下:dp[i][1],**表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区**。 -```C++ +```CPP for (int j = 0; j < 2 * k - 1; j += 2) { dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]); dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]); @@ -125,7 +125,7 @@ for (int j = 0; j < 2 * k - 1; j += 2) { 代码如下: -```C++ +```CPP for (int j = 1; j < 2 * k; j += 2) { dp[0][j] = -prices[0]; } diff --git a/problems/周总结/二叉树阶段总结系列一.md b/problems/周总结/二叉树阶段总结系列一.md index e586e0e8..c8235ff1 100644 --- a/problems/周总结/二叉树阶段总结系列一.md +++ b/problems/周总结/二叉树阶段总结系列一.md @@ -18,7 +18,7 @@ 对于二叉树节点的定义,C++代码如下: -```C++ +```CPP struct TreeNode { int val; TreeNode *left; @@ -40,7 +40,7 @@ TreeNode* a = new TreeNode(9); 没有构造函数的话就要这么写: -```C++ +```CPP TreeNode* a = new TreeNode(); a->val = 9; a->left = NULL; @@ -68,7 +68,7 @@ morris遍历是二叉树遍历算法的超强进阶算法,morris遍历可以 前序遍历空节点不入栈的代码:(注意注释部分,和文章中的区别) -```C++ +```CPP class Solution { public: vector preorderTraversal(TreeNode* root) { @@ -91,7 +91,7 @@ public: 后序遍历空节点不入栈的代码:(注意注释部分,和文章中的区别) -```C++ +```CPP class Solution { public: vector postorderTraversal(TreeNode* root) { @@ -152,7 +152,7 @@ public: 如果非要使用递归中序的方式写,也可以,如下代码就可以避免节点左右孩子翻转两次的情况: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { @@ -171,7 +171,7 @@ public: 代码如下: -```C++ +```CPP class Solution { public: TreeNode* invertTree(TreeNode* root) { diff --git a/problems/回溯算法去重问题的另一种写法.md b/problems/回溯算法去重问题的另一种写法.md index 763b8cbf..cc563fb1 100644 --- a/problems/回溯算法去重问题的另一种写法.md +++ b/problems/回溯算法去重问题的另一种写法.md @@ -30,7 +30,7 @@ used数组去重版本: [回溯算法:求子集问题(二)](https://mp.w 使用set去重的版本如下: -```C++ +```CPP class Solution { private: vector> result; @@ -71,7 +71,7 @@ public: 例如: -```C++ +```CPP class Solution { private: vector> result; @@ -110,7 +110,7 @@ private: 代码如下: -```C++ +```CPP class Solution { private: vector> result; @@ -142,7 +142,7 @@ uset已经是全局变量,本层的uset记录了一个元素,然后进入下 使用set去重的版本如下: -```C++ +```CPP class Solution { private: vector> result; @@ -183,7 +183,7 @@ public: 使用set去重的版本如下: -```C++ +```CPP class Solution { private: vector> result; diff --git a/problems/数组理论基础.md b/problems/数组理论基础.md index 9fe7744b..6d7b9f9a 100644 --- a/problems/数组理论基础.md +++ b/problems/数组理论基础.md @@ -53,7 +53,7 @@ 我们来做一个实验,C++测试代码如下: -```C++ +```CPP void test_arr() { int array[2][3] = { {0, 1, 2}, diff --git a/problems/根据身高重建队列(vector原理讲解).md b/problems/根据身高重建队列(vector原理讲解).md index d504cf8e..baf7dcf5 100644 --- a/problems/根据身高重建队列(vector原理讲解).md +++ b/problems/根据身高重建队列(vector原理讲解).md @@ -12,7 +12,7 @@ 但是在解释的过程中有不恰当的地方,所以来专门写一篇文章来详细说一说这个问题。 使用vector的代码如下: -```C++ +```CPP // 版本一,使用vector(动态数组) class Solution { public: @@ -38,7 +38,7 @@ public: 其直观上来看数组的insert操作是O(n)的,整体代码的时间复杂度是O(n^2)。 这么一分析好像和版本二链表实现的时间复杂度是一样的啊,为什么提交之后效率会差距这么大呢? -```C++ +```CPP // 版本二,使用list(链表) class Solution { public: @@ -107,7 +107,7 @@ for (int i = 0; i < vec.size(); i++) { 手动模拟的过程其实不是很简单的,需要很多细节,我粗略写了一个版本,如下: -```C++ +```CPP // 版本三 // 使用vector,但不让它动态扩容 class Solution { diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index c94bff32..c13efc3a 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -223,7 +223,7 @@ dp[i-1][j]和dp[i - 1][j - weight[i]] 都在dp[i][j]的左上角方向(包括 ## 完整C++测试代码 -```C++ +```CPP void test_2_wei_bag_problem1() { vector weight = {1, 3, 4}; vector value = {15, 20, 30}; diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index 9acc5f73..4f1455e9 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -153,7 +153,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15 ## 一维dp01背包完整C++测试代码 -```C++ +```CPP void test_1_wei_bag_problem() { vector weight = {1, 3, 4}; vector value = {15, 20, 30}; diff --git a/problems/背包问题理论基础多重背包.md b/problems/背包问题理论基础多重背包.md index 7d4ec08f..85cbf4de 100644 --- a/problems/背包问题理论基础多重背包.md +++ b/problems/背包问题理论基础多重背包.md @@ -56,7 +56,7 @@ 这种方式来实现多重背包的代码如下: -```C++ +```CPP void test_multi_pack() { vector weight = {1, 3, 4}; vector value = {15, 20, 30}; @@ -96,7 +96,7 @@ int main() { 代码如下:(详看注释) -```C++ +```CPP void test_multi_pack() { vector weight = {1, 3, 4}; vector value = {15, 20, 30}; diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index 474f485f..dc4f06f9 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -51,7 +51,7 @@ for(int i = 0; i < weight.size(); i++) { // 遍历物品 而完全背包的物品是可以添加多次的,所以要从小到大去遍历,即: -```C++ +```CPP // 先遍历物品,再遍历背包 for(int i = 0; i < weight.size(); i++) { // 遍历物品 for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量 @@ -98,7 +98,7 @@ dp状态图如下: 先遍历被背包在遍历物品,代码如下: -```C++ +```CPP // 先遍历背包,再遍历物品 for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 for(int i = 0; i < weight.size(); i++) { // 遍历物品 @@ -112,7 +112,7 @@ for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 完整的C++测试代码如下: -```C++ +```CPP // 先遍历物品,在遍历背包 void test_CompletePack() { vector weight = {1, 3, 4}; @@ -132,7 +132,7 @@ int main() { ``` -```C++ +```CPP // 先遍历背包,再遍历物品 void test_CompletePack() { diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md index 22f064b4..9acda71c 100644 --- a/problems/面试题02.07.链表相交.md +++ b/problems/面试题02.07.链表相交.md @@ -44,7 +44,7 @@ C++代码如下: -```C++ +```CPP class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { From d0504d4ffed670c9714b3bba0301ff51b8025bb0 Mon Sep 17 00:00:00 2001 From: Yifeng Date: Wed, 11 Aug 2021 03:26:50 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E8=AF=AD=E6=84=8F=E8=A1=A8=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 “节点10小于左节点5,大于右节点15” 改为 “节点10大于左节点5,小于右节点15” --- problems/0098.验证二叉搜索树.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index d6db901e..6f7e5c14 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -103,7 +103,7 @@ if (root->val > root->left->val && root->val < root->right->val) { ![二叉搜索树](https://img-blog.csdnimg.cn/20200812191501419.png) -节点10小于左节点5,大于右节点15,但右子树里出现了一个6 这就不符合了! +节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了! * 陷阱2 From 1f7fbfa1195ed298899120d085ccbe28502b0222 Mon Sep 17 00:00:00 2001 From: eshailincai Date: Tue, 10 Aug 2021 22:19:12 -0400 Subject: [PATCH 04/12] problems/0102, add Java implementation for leetcode 515 --- problems/0102.二叉树的层序遍历.md | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md index c38cc796..007eac44 100644 --- a/problems/0102.二叉树的层序遍历.md +++ b/problems/0102.二叉树的层序遍历.md @@ -1046,6 +1046,31 @@ class Solution: out_list.append(max(in_list)) return out_list ``` +java代码: + +```java +class Solution { + public List largestValues(TreeNode root) { + List retVal = new ArrayList(); + Queue tmpQueue = new LinkedList(); + if (root != null) tmpQueue.add(root); + + while (tmpQueue.size() != 0){ + int size = tmpQueue.size(); + List lvlVals = new ArrayList(); + for (int index = 0; index < size; index++){ + TreeNode node = tmpQueue.poll(); + lvlVals.add(node.val); + if (node.left != null) tmpQueue.add(node.left); + if (node.right != null) tmpQueue.add(node.right); + } + retVal.add(Collections.max(lvlVals)); + } + + return retVal; + } +} +``` go: From 9ca9e4f4cba69acd829598e109ca15cece34b783 Mon Sep 17 00:00:00 2001 From: X-shuffle <53906918+X-shuffle@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:15:35 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=200056.=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E5=8C=BA=E9=97=B4=20go=E7=89=88=E6=9C=AC=EF=BC=88?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A9=BA=E9=97=B4=E5=A4=8D=E6=9D=82=E5=BA=A6?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=BC=80=E8=BE=9F=E6=96=B0=E6=95=B0=E7=BB=84?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 0056.合并区间 go版本(优化空间复杂度,不开辟新数组) --- problems/0056.合并区间.md | 41 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 99c870c6..441cc63c 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -176,30 +176,27 @@ class Solution: ``` Go: -```Go +```golang func merge(intervals [][]int) [][]int { - sort.Slice(intervals, func(i, j int) bool { - return intervals[i][0]=intervals[i+1][0]{ + intervals[i][1]=max(intervals[i][1],intervals[i+1][1])//赋值最大值 + intervals=append(intervals[:i+1],intervals[i+2:]...) + i-- + } + } + return intervals } -func max(a, b int) int { - if a > b { return a } - return b +func max(a,b int)int{ + if a>b{ + return a + } + return b } ``` From 08b07abd74c50b041846d6453ea7c9a383388fae Mon Sep 17 00:00:00 2001 From: X-shuffle <53906918+X-shuffle@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:21:21 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200738.=E5=8D=95?= =?UTF-8?q?=E8=B0=83=E9=80=92=E5=A2=9E=E7=9A=84=E6=95=B0=E5=AD=97=20go?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 0738.单调递增的数字 go版本 --- problems/0738.单调递增的数字.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index 7cb24236..82f7f3ae 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -159,7 +159,26 @@ class Solution: ``` Go: - +```golang +func monotoneIncreasingDigits(N int) int { + s := strconv.Itoa(N)//将数字转为字符串,方便使用下标 + ss := []byte(s)//将字符串转为byte数组,方便更改。 + n := len(ss) + if n <= 1 { + return N + } + for i:=n-1 ; i>0; i-- { + if ss[i-1] > ss[i] {//前一个大于后一位,前一位减1,后面的全部置为9 + ss[i-1] -= 1 + for j := i ; j < n; j++ {//后面的全部置为9 + ss[j] = '9' + } + } + } + res, _ := strconv.Atoi(string(ss)) + return res +} +``` Javascript: ```Javascript var monotoneIncreasingDigits = function(n) { From b02e144d7a865a632db2bd025291c00f8583ee96 Mon Sep 17 00:00:00 2001 From: ironartisan Date: Wed, 11 Aug 2021 20:13:02 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E6=9B=B4=E6=96=B00116.=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E6=AF=8F=E4=B8=AA=E8=8A=82=E7=82=B9=E7=9A=84=E4=B8=8B=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=8F=B3=E4=BE=A7=E8=8A=82=E7=82=B9=E6=8C=87=E9=92=88?= =?UTF-8?q?java=E6=B3=A8=E9=87=8A=E5=8F=8A=E4=BB=A3=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...个节点的下一个右侧节点指针.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/problems/0116.填充每个节点的下一个右侧节点指针.md b/problems/0116.填充每个节点的下一个右侧节点指针.md index 8b816f5e..34c666f3 100644 --- a/problems/0116.填充每个节点的下一个右侧节点指针.md +++ b/problems/0116.填充每个节点的下一个右侧节点指针.md @@ -133,14 +133,14 @@ public: // 递归法 class Solution { public void traversal(Node cur) { - if(cur == null) return; - if(cur.left != null) cur.left.next = cur.right; - if(cur.right != null){ - if(cur.next != null) cur.right.next = cur.next.left; + if (cur == null) return; + if (cur.left != null) cur.left.next = cur.right; // 操作1 + if (cur.right != null) { + if(cur.next != null) cur.right.next = cur.next.left; //操作2 else cur.right.next = null; } - traversal(cur.left); - traversal(cur.right); + traversal(cur.left); // 左 + traversal(cur.right); //右 } public Node connect(Node root) { traversal(root); @@ -152,26 +152,26 @@ class Solution { // 迭代法 class Solution { public Node connect(Node root) { - if(root == null) return root; + if (root == null) return root; Queue que = new LinkedList(); que.offer(root); Node nodePre = null; Node node = null; - while(!que.isEmpty()){ + while (!que.isEmpty()) { int size = que.size(); - for(int i=0; i Date: Wed, 11 Aug 2021 22:24:28 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A01382.=E5=B0=86=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91=E5=8F=98=E5=B9=B3=E8=A1=A1?= =?UTF-8?q?python3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1382.将二叉搜索树变平衡.md | 24 ++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/problems/1382.将二叉搜索树变平衡.md b/problems/1382.将二叉搜索树变平衡.md index b9d4fb65..75530663 100644 --- a/problems/1382.将二叉搜索树变平衡.md +++ b/problems/1382.将二叉搜索树变平衡.md @@ -55,7 +55,7 @@ private: vec.push_back(cur->val); traversal(cur->right); } - 有序数组转平衡二叉树 + // 有序数组转平衡二叉树 TreeNode* getTree(vector& nums, int left, int right) { if (left > right) return nullptr; int mid = left + ((right - left) / 2); @@ -78,7 +78,27 @@ public: Java: Python: - +```python +class Solution: + def balanceBST(self, root: TreeNode) -> TreeNode: + res = [] + # 有序树转成有序数组 + def traversal(cur: TreeNode): + if not cur: return + traversal(cur.left) + res.append(cur.val) + traversal(cur.right) + # 有序数组转成平衡二叉树 + def getTree(nums: List, left, right): + if left > right: return + mid = left + (right -left) // 2 + root = TreeNode(nums[mid]) + root.left = getTree(nums, left, mid - 1) + root.right = getTree(nums, mid + 1, right) + return root + traversal(root) + return getTree(res, 0, len(res) - 1) +``` Go: JavaScript: From 2706b07a974af830beb0258563efc7663636b525 Mon Sep 17 00:00:00 2001 From: ironartisan Date: Thu, 12 Aug 2021 09:37:26 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A01382.=E5=B0=86=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91=E5=8F=98=E5=B9=B3=E8=A1=A1?= =?UTF-8?q?java=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1382.将二叉搜索树变平衡.md | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/problems/1382.将二叉搜索树变平衡.md b/problems/1382.将二叉搜索树变平衡.md index 75530663..758d5ad8 100644 --- a/problems/1382.将二叉搜索树变平衡.md +++ b/problems/1382.将二叉搜索树变平衡.md @@ -76,7 +76,31 @@ public: # 其他语言版本 Java: - +```java +class Solution { + ArrayList res = new ArrayList(); + // 有序树转成有序数组 + private void travesal(TreeNode cur) { + if (cur == null) return; + travesal(cur.left); + res.add(cur.val); + travesal(cur.right); + } + // 有序数组转成平衡二叉树 + private TreeNode getTree(ArrayList nums, int left, int right) { + if (left > right) return null; + int mid = left + (right - left) / 2; + TreeNode root = new TreeNode(nums.get(mid)); + root.left = getTree(nums, left, mid - 1); + root.right = getTree(nums, mid + 1, right); + return root; + } + public TreeNode balanceBST(TreeNode root) { + travesal(root); + return getTree(res, 0, res.size() - 1); + } +} +``` Python: ```python class Solution: From fa6e237f628aec738b0a186f5c7dc355a2d29c4c Mon Sep 17 00:00:00 2001 From: X-shuffle <53906918+X-shuffle@users.noreply.github.com> Date: Thu, 12 Aug 2021 09:42:37 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200714.=E4=B9=B0?= =?UTF-8?q?=E5=8D=96=E8=82=A1=E7=A5=A8=E7=9A=84=E6=9C=80=E4=BD=B3=E6=97=B6?= =?UTF-8?q?=E6=9C=BA=E5=90=AB=E6=89=8B=E7=BB=AD=E8=B4=B9=20go=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 0714.买卖股票的最佳时机含手续费 go版本 --- ...买卖股票的最佳时机含手续费.md | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/problems/0714.买卖股票的最佳时机含手续费.md b/problems/0714.买卖股票的最佳时机含手续费.md index 6dc95a2d..b0a64bd2 100644 --- a/problems/0714.买卖股票的最佳时机含手续费.md +++ b/problems/0714.买卖股票的最佳时机含手续费.md @@ -216,7 +216,30 @@ class Solution: # 贪心思路 ``` Go: - +```golang +func maxProfit(prices []int, fee int) int { + var minBuy int = prices[0] //第一天买入 + var res int + for i:=0;i=minBuy&&prices[i]-fee-minBuy<=0{ + continue + } + //可以售卖了 + if prices[i]>minBuy+fee{ + //累加每天的收益 + res+=prices[i]-minBuy-fee + //更新最小值(如果还在收获利润的区间里,表示并不是真正的卖出,而计算利润每次都要减去手续费,所以要让minBuy = prices[i] - fee;,这样在明天收获利润的时候,才不会多减一次手续费!) + minBuy=prices[i]-fee + } + } + return res +} +``` Javascript: ```Javascript // 贪心思路 From a2539333a0d798cba512b44dd47fc1abb7d89fbb Mon Sep 17 00:00:00 2001 From: Junwen Huang <58247686+hjwforever@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:10:23 +0800 Subject: [PATCH 11/12] =?UTF-8?q?upt:=20edit=20=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=90=86=E8=AE=BA=E5=9F=BA=E7=A1=80.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加JavaScript版的二叉树节点定义方式 --- problems/二叉树理论基础.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/problems/二叉树理论基础.md b/problems/二叉树理论基础.md index abeeae67..edd1fed4 100644 --- a/problems/二叉树理论基础.md +++ b/problems/二叉树理论基础.md @@ -223,6 +223,14 @@ type TreeNode struct { } ``` +JavaScript: +``` +function TreeNode(val, left, right) { + this.val = (val===undefined ? 0 : val) + this.left = (left===undefined ? null : left) + this.right = (right===undefined ? null : right) +} +``` ----------------------- From 25fa9ad2f3704b7cf0e224f0c8439bb73ad0ec44 Mon Sep 17 00:00:00 2001 From: ironartisan Date: Thu, 12 Aug 2021 14:19:07 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A00925.=E9=95=BF=E6=8C=89?= =?UTF-8?q?=E9=94=AE=E5=85=A5python3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0925.长按键入.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/problems/0925.长按键入.md b/problems/0925.长按键入.md index 4d3543f4..ef712252 100644 --- a/problems/0925.长按键入.md +++ b/problems/0925.长按键入.md @@ -8,7 +8,7 @@

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

# 925.长按键入 - +题目链接:https://leetcode-cn.com/problems/long-pressed-name/ 你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。 @@ -100,7 +100,31 @@ public: Java: Python: - +```python +class Solution: + def isLongPressedName(self, name: str, typed: str) -> bool: + i, j = 0, 0 + m, n = len(name) , len(typed) + while i< m and j < n: + if name[i] == typed[j]: # 相同时向后匹配 + i += 1 + j += 1 + else: # 不相同 + if j == 0: return False # 如果第一位不相同,直接返回false + # 判断边界为n-1,若为n会越界,例如name:"kikcxmvzi" typed:"kiikcxxmmvvzzz" + while j < n - 1 and typed[j] == typed[j-1]: j += 1 + if name[i] == typed[j]: + i += 1 + j += 1 + else: return False + # 说明name没有匹配完 + if i < m: return False + # 说明type没有匹配完 + while j < n: + if typed[j] == typed[j-1]: j += 1 + else: return False + return True +``` Go: JavaScript: