LeetCode 热题 HOT 100 完整题解笔记&知识点分类 C++代码实现
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 热题 HOT 100 完整题解笔记&知识点分类 C++代码实现相关的知识,希望对你有一定的参考价值。
1、知识点分布
填一下这个之前欠的天坑,复习一下算法入门的经典基础题。
除夕,正月初一,初二,一共写了三整天,除了吃饭就窝着补题。
每天30题+,整个人都写晕啦,终于写完啦()
markdown生成
#include<bits/stdc++.h>
using namespace std;
int main()
freopen("100.txt","r",stdin);
freopen("100.md","w",stdout);
for(int i = 1; i <= 100; i++)
string s; getline(cin,s);
cout<<"#### ";
printf("%03d: ",i);
cout<<s<<"\\n";
printf("```cpp\\n\\n```\\n");
return 0;
编号 题目 题号 分类
1 翻转二叉树 226 二叉树
2 合并二叉树 617 二叉树
3 二叉树的最大深度 104 二叉树
4 二叉树的中序遍历 94 二叉树
5 二叉树展开为链表 114 二叉树
6 把二叉搜索树转换为累加树 538 二叉树
7 从前序与中序遍历序列构造二叉树 105 二叉树
8 不同的二叉搜索树 96 二叉树
9 二叉树的最近公共祖先 236 二叉树
10 二叉树的层序遍历 102 二叉树
11 打家劫舍 III 337 二叉树
12 路径总和 III 437 二叉树
13 对称二叉树 101 二叉树
14 二叉树的序列化与反序列化 297 二叉树
15 二叉树的直径 543 二叉树
16 二叉树中的最大路径和 124 二叉树
17 验证二叉搜索树 98 二叉树
18 实现 Trie (前缀树) 208 字典树
19 单词拆分 139 字典树
20 全排列 46 搜索(回溯)
21 括号生成 22 搜索(回溯)
22 组合总和 39 搜索(回溯)
23 电话号码的字母组合 17 搜索(回溯)
24 目标和 494 搜索(回溯)
25 下一个排列 31 搜索(回溯)
26 零钱兑换 322 搜索(记忆化)
27 岛屿数量 200 搜索(联通块)
28 删除无效的括号 301 搜索(枚举)
29 课程表 207 搜索(拓扑排序)
30 除法求值 399 搜索(最短路)
31 每日温度 739 栈
32 接雨水 42 栈
33 最小栈 155 栈
34 字符串解码 394 栈
35 最大矩形 85 栈
36 回文链表 234 栈
37 有效的括号 20 栈
38 柱状图中最大的矩形 84 栈
39 最长有效括号 32 栈
40 反转链表 206 链表
41 合并两个有序链表 21 链表
42 排序链表 148 链表
43 相交链表 160 链表
44 合并K个升序链表 23 链表
45 环形链表 II 142 链表
46 LRU 缓存 146 链表
47 环形链表 141 链表
48 删除链表的倒数第 N 个结点 19 链表
49 两数相加 2 链表
50 字母异位词分组 49 字符串
51 回文子串 647 字符串
52 编辑距离 72 字符串
53 找到字符串中所有字母异位词 438 字符串
54 最小覆盖子串 76 字符串
55 无重复字符的最长子串 3 字符串
56 最长回文子串 5 字符串
57 正则表达式匹配 10 字符串
58 戳气球 312 数组(动态规划)
59 最佳买卖股票时机含冷冻期 309 数组(动态规划)
60 最大子数组和 53 数组(动态规划)
61 最长连续序列 128 数组(动态规划)
62 最长递增子序列 300 数组(动态规划)
63 打家劫舍 198 数组(动态规划)
64 分割等和子集 416 数组(动态规划)
65 乘积最大子数组 152 数组(动态规划)
66 搜索旋转排序数组 33 数组(二分)
67 在排序数组中查找元素的第一个和最后一个位置 34 数组(二分)
68 寻找两个正序数组的中位数 4 数组(二分)
69 数组中的第K个最大元素 215 数组(排序)
70 移动零 283 数组(排序)
71 前 K 个高频元素 347 数组(排序)
72 盛最多水的容器 11 数组(双指针)
73 颜色分类 75 数组(双指针)
74 最短无序连续子数组 581 数组(双指针)
75 三数之和 15 数组(双指针)
76 根据身高重建队列 406 数组(贪心)
77 除自身以外数组的乘积 238 数组(贪心)
78 多数元素 169 数组(贪心)
79 找到所有数组中消失的数字 448 数组(贪心)
80 任务调度器 621 数组(贪心)
81 买卖股票的最佳时机 121 数组(贪心)
82 两数之和 1 数组(贪心)
83 会议室 II 253 数组(贪心)
84 滑动窗口最大值 239 数组(贪心)
85 合并区间 56 数组(贪心)
86 和为 K 的子数组 560 数组(贪心)
87 跳跃游戏 55 数组(贪心)
88 不同路径 62 递推
89 完全平方数 279 递推
90 爬楼梯 70 递推
91 旋转图像 48 矩阵
92 最小路径和 64 矩阵
93 搜索二维矩阵 II 240 矩阵
94 最大正方形 221 矩阵
95 单词搜索 79 矩阵
96 汉明距离 461 位运算
97 子集 78 位运算
98 比特位计数 338 位运算
99 只出现一次的数字 136 位运算
100 寻找重复数 287 位运算
2、完整代码
001: 翻转二叉树 226
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/invert-binary-tree
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
// 翻转以 root 为根的二叉树,然后返回翻转后的二叉树的根节点
class Solution
public:
TreeNode* invertTree(TreeNode* root)
if (root == nullptr) return nullptr;
if (root->left == nullptr && root->right == nullptr)
return root;
TreeNode *left = invertTree(root->left);
TreeNode *right = invertTree(root->right);
root->right = left;
root->left = right;
return root;
;
002: 合并二叉树 617
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-binary-trees
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2)
if(root1==nullptr)return root2;
if(root2==nullptr)return root1;
TreeNode* m = new TreeNode(root1->val+root2->val);
m->left = mergeTrees(root1->left,root2->left);
m->right = mergeTrees(root1->right,root2->right);
return m;
;
003: 二叉树的最大深度 104
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
返回它的最大深度 3 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree
//无脑dfs就行
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
int maxDepth(TreeNode* root)
if(root==nullptr)return 0;
return max(maxDepth(root->left), maxDepth(root->right))+1;
;
004: 二叉树的中序遍历 94
给定一个二叉树的根节点 root
,返回它的 中序 遍历。
输入:root = [1,null,2,3]
输出:[1,3,2]
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
void dfs(TreeNode *u, vector<int>& res)
if(u==nullptr)return ;
dfs(u->left, res);
res.push_back(u->val);
dfs(u->right,res);
vector<int> inorderTraversal(TreeNode* root)
vector<int>res;
dfs(root, res);
return res;
;
005: 二叉树展开为链表 114
给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例 1:
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
void flatten(TreeNode* root)
vector<TreeNode*>l;
pre(root, l);
int n = l.size();
for(int i = 1; i < n; i++)
TreeNode* pree = l[i-1], *curr = l[i];
pree->left = nullptr;
pree->right = curr;
void pre(TreeNode* root, vector<TreeNode*>& l)
if(root==nullptr)return ;
l.push_back(root);
pre(root->left, l);
pre(root->right, l);
;
006: 把二叉搜索树转换为累加树 538
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键 小于 节点键的节点。
节点的右子树仅包含键 大于 节点键的节点。
左右子树也必须是二叉搜索树。
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
int sum = 0;
TreeNode* convertBST(TreeNode* root)
if(root != nullptr)
convertBST(root->right);
sum += root->val;
root->val = sum;
convertBST(root->left);
return root;
;
007: 从前序与中序遍历序列构造二叉树 105
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
unordered_map<int, int> index;
TreeNode * build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir)
if(pl > pr)return nullptr;
//根节点
int prt = pl;
int irt = index[preorder[prt]];
//
TreeNode* root = new TreeNode(preorder[prt]);
int lsz = irt-il;
root->left = build(preorder, inorder, pl+1,pl+lsz, il, irt-1);
root->right = build(preorder, inorder, pl+lsz+1,pr, irt+1,ir);
return root;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
int n = preorder.size();
for(int i = 0; i < n; i++)
index[inorder[i]] = i;
return build(preorder, inorder, 0,n-1, 0, n-1);
;
008: 不同的二叉搜索树 96
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees
class Solution
public:
int numTrees(int n)
//卡特兰数
long long x = 1;
for(int i = 0; i < n; i++)
x = x*2*(2*i+1)/(i+2);
return (int)x;
;
009: 二叉树的最近公共祖先 236
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL)
* ;
*/
class Solution
public:
unordered_map<int,TreeNode*>fa;
unordered_map<int,bool>vis;
void dfs(TreeNode * u)
if(u->left != nullptr)
fa[u->left->val] = u;
dfs(u->left);
if(u->right != nullptr)
fa[u->right->val] = u;
dfs(u->right);
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
fa[root->val] = nullptr;
dfs(root);
while(p != nullptr)
vis[p->val] = true;
p = fa[p->val];
while(q != nullptr)
if(vis[q->val])return q;
q = fa[q->val];
return nullptr;
;
010: 二叉树的层序遍历 102
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
//开个队列往里面丢就是了,简称bfs
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
vector<vector<int>> levelOrder(TreeNode* root)
vector<vector<int>>res;
if(!root)return res;
queue<TreeNode*>q;
q.push(root);
while(q.size())
int len = q.size();
res.push_back(vector<int>());
for(int i = 1; i <= len; i++)
auto t = q.front(); q.pop();
res.back().push_back(t->val);
if(t->left)q.push(t->left);
if(t->right)q.push(t->right);
return res;
;
011: 打家劫舍 III 337
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例 1:
输入: root = [3,2,3,null,3,null,1]
输出: 7
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/house-robber-iii
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
//f[i],选第i个点能获得的最大价值
//g[i],不选第i个点能获得的最大价值
unordered_map<TreeNode*, int> f, g;
void dfs(TreeNode* u)
if(!u)return ;
dfs(u->left);
dfs(u->right);
f[u] = u->val+g[u->left]+g[u->right];
g[u] = max(f[u->left],g[u->left])+max(f[u->right],g[u->right]);
int rob(TreeNode* root)
dfs(root);
return max(f[root], g[root]);
;
012: 路径总和 III 437
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例 1:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-iii
/**
* Definition for a binary tree node.
* struct TreeNode
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr)
* TreeNode(int x) : val(x), left(nullptr), right(nullptr)
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right)
* ;
*/
class Solution
public:
int dfs(TreeNode* u, int target)
if(!u)return 0;
int res = 0;
if(u->val==target)res++;
res += dfs(u->left,target-u->val);
res += dfs(u->right,target-u->val);
return res;
int pathSum(TreeNode* root, int targetSum)
//暴力,从每个点开始搜.
if(!root)return 0;
int res = dfs(以上是关于LeetCode 热题 HOT 100 完整题解笔记&知识点分类 C++代码实现的主要内容,如果未能解决你的问题,请参考以下文章
《 LeetCode 热题 HOT 100》——无重复字符的最长子串