mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-06 23:28:29 +08:00
Update
This commit is contained in:
59
README.md
59
README.md
@ -121,6 +121,8 @@
|
||||
* [二叉树:搜索树的公共祖先问题](https://mp.weixin.qq.com/s/Ja9dVw2QhBcg_vV-1fkiCg)
|
||||
* [二叉树:搜索树中的插入操作](https://mp.weixin.qq.com/s/lwKkLQcfbCNX2W-5SOeZEA)
|
||||
* [二叉树:搜索树中的删除操作](https://mp.weixin.qq.com/s/-p-Txvch1FFk3ygKLjPAKw)
|
||||
* [二叉树:修剪一棵搜索树](https://mp.weixin.qq.com/s/QzmGfYUMUWGkbRj7-ozHoQ)
|
||||
* [二叉树:构造一棵搜索树](https://mp.weixin.qq.com/s/sy3ygnouaZVJs8lhFgl9mw)
|
||||
|
||||
|
||||
|
||||
@ -163,6 +165,7 @@
|
||||
* 循环不变量原则
|
||||
* [0035.搜索插入位置](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q)
|
||||
* [0059.螺旋矩阵II](https://mp.weixin.qq.com/s/KTPhaeqxbMK9CxHUUgFDmg)
|
||||
* [106.从中序与后序遍历序列构造二叉树&105. 从前序与中序遍历序列构造二叉树](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)
|
||||
|
||||
* 字符串经典题目
|
||||
* [0344.反转字符串](https://mp.weixin.qq.com/s/X02S61WCYiCEhaik6VUpFA)
|
||||
@ -205,19 +208,46 @@
|
||||
* [0144.二叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0144.二叉树的前序遍历.md)
|
||||
* [0094.二叉树的中序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0094.二叉树的中序遍历.md)
|
||||
* [0145.二叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0145.二叉树的后序遍历.md)
|
||||
* [0589.N叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0589.N叉树的前序遍历.md)
|
||||
* [0590.N叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0590.N叉树的后序遍历.md)
|
||||
|
||||
|
||||
* [0102.二叉树的层序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0102.二叉树的层序遍历.md)
|
||||
* [0107.二叉树的层次遍历II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0107.二叉树的层次遍历II.md)
|
||||
|
||||
* [0199.二叉树的右视图](https://github.com/youngyangyang04/leetcode/blob/master/problems/0199.二叉树的右视图.md)
|
||||
* [0637.二叉树的层平均值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0637.二叉树的层平均值.md)
|
||||
|
||||
* [0226.翻转二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0226.翻转二叉树.md)
|
||||
* [0101.对称二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0101.对称二叉树.md)
|
||||
* [0100.相同的树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0100.相同的树.md)
|
||||
|
||||
* [0572.另一个树的子树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0572.另一个树的子树.md)
|
||||
* [0110.平衡二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0110.平衡二叉树.md)
|
||||
* [0104.二叉树的最大深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0104.二叉树的最大深度.md)
|
||||
* [0111.二叉树的最小深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0111.二叉树的最小深度.md)
|
||||
* [0222.完全二叉树的节点个数](https://github.com/youngyangyang04/leetcode/blob/master/problems/0222.完全二叉树的节点个数.md)
|
||||
* [0404.左叶子之和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0404.左叶子之和.md)
|
||||
* [0513.找树左下角的值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0513.找树左下角的值.md)
|
||||
* [0112.路径总和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0112.路径总和.md)
|
||||
* [0113.路径总和II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0113.路径总和II.md)
|
||||
* [0257.二叉树的所有路径](https://github.com/youngyangyang04/leetcode/blob/master/problems/0257.二叉树的所有路径.md)
|
||||
* [0236.二叉树的最近公共祖先](https://github.com/youngyangyang04/leetcode/blob/master/problems/0236.二叉树的最近公共祖先.md)
|
||||
* [0106.从中序与后序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0106.从中序与后序遍历序列构造二叉树.md)
|
||||
* [0105.从前序与中序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0105.从前序与中序遍历序列构造二叉树.md)
|
||||
* [0654.最大二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0654.最大二叉树.md)
|
||||
* [0617.合并二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0617.合并二叉树.md)
|
||||
* [0700.二叉搜索树中的搜索](https://github.com/youngyangyang04/leetcode/blob/master/problems/0700.二叉搜索树中的搜索.md)
|
||||
* [0098.验证二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0098.验证二叉搜索树.md)
|
||||
* [0530.二叉搜索树的最小绝对差](https://github.com/youngyangyang04/leetcode/blob/master/problems/0530.二叉搜索树的最小绝对差.md)
|
||||
* [0501.二叉搜索树中的众数](https://github.com/youngyangyang04/leetcode/blob/master/problems/0501.二叉搜索树中的众数.md)
|
||||
* [0235.二叉搜索树的最近公共祖先](https://github.com/youngyangyang04/leetcode/blob/master/problems/0235.二叉搜索树的最近公共祖先.md)
|
||||
* [0701.二叉搜索树中的插入操作](https://github.com/youngyangyang04/leetcode/blob/master/problems/0701.二叉搜索树中的插入操作.md)
|
||||
* [0450.删除二叉搜索树中的节点](https://github.com/youngyangyang04/leetcode/blob/master/problems/0450.删除二叉搜索树中的节点.md)
|
||||
* [0669.修剪二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0669.修剪二叉搜索树.md)
|
||||
* [0108.将有序数组转换为二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0108.将有序数组转换为二叉搜索树.md)
|
||||
* [0538.把二叉搜索树转换为累加树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0538.把二叉搜索树转换为累加树.md)
|
||||
* [0968.监控二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0968.监控二叉树.md)
|
||||
|
||||
* 回溯经典题目
|
||||
|
||||
@ -278,15 +308,17 @@
|
||||
|[0094.二叉树的中序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0094.二叉树的中序遍历.md) |树 |中等|**递归** **迭代/栈**|
|
||||
|[0098.验证二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0098.验证二叉搜索树.md) |树 |中等|**递归**|
|
||||
|[0100.相同的树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0100.相同的树.md) |树 |简单|**递归** |
|
||||
|[0101.对称二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0101.对称二叉树.md) |树 |简单|**递归** **迭代/队列/栈**|
|
||||
|[0101.对称二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0101.对称二叉树.md) |树 |简单|**递归** **迭代/队列/栈** 和100. 相同的树 相似|
|
||||
|[0102.二叉树的层序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0102.二叉树的层序遍历.md) |树 |中等|**广度优先搜索/队列**|
|
||||
|[0104.二叉树的最大深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0104.二叉树的最大深度.md) |树 |简单|**递归** **迭代/队列/BFS**|
|
||||
|[0105.从前序与中序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0105.从前序与中序遍历序列构造二叉树.md) |树 |中等|**递归**|
|
||||
|[0106.从中序与后序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0106.从中序与后序遍历序列构造二叉树.md) |树 |中等|**递归**|
|
||||
|[0105.从前序与中序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0105.从前序与中序遍历序列构造二叉树.md) |二叉树 |中等|**递归**|
|
||||
|[0106.从中序与后序遍历序列构造二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0106.从中序与后序遍历序列构造二叉树.md) |二叉树 |中等|**递归** 根据数组构造二叉树|
|
||||
|[0107.二叉树的层次遍历II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0107.二叉树的层次遍历II.md) |树 |简单|**广度优先搜索/队列/BFS**|
|
||||
|[0110.平衡二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0110.平衡二叉树.md) |树 |简单|**递归**|
|
||||
|[0111.二叉树的最小深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0111.二叉树的最小深度.md) |树 |简单|**递归** **队列/BFS**|
|
||||
|[0112.路径总和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0112.路径总和.md) |树 |简单|**深度优先搜索/递归** **回溯** **栈**|
|
||||
|[0108.将有序数组转换为二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0108.将有序数组转换为二叉搜索树.md) |二叉搜索树 |中等|**递归** **迭代** 通过递归函数返回值构造树|
|
||||
|[0110.平衡二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0110.平衡二叉树.md) |二叉树 |简单|**递归**|
|
||||
|[0111.二叉树的最小深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0111.二叉树的最小深度.md) |二叉树 |简单|**递归** **队列/BFS**|
|
||||
|[0112.路径总和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0112.路径总和.md) |二叉树树 |简单|**深度优先搜索/递归** **回溯** **栈** 思考递归函数什么时候需要返回值|
|
||||
|[0113.路径总和II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0113.路径总和II.md) |二叉树树 |简单|**深度优先搜索/递归** **回溯** **栈**|
|
||||
|[0116.填充每个节点的下一个右侧节点指针](https://github.com/youngyangyang04/leetcode/blob/master/problems/0116.填充每个节点的下一个右侧节点指针.md) |二叉树 |中等|**递归** **迭代/广度优先搜索**|
|
||||
|[0117.填充每个节点的下一个右侧节点指针II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0117.填充每个节点的下一个右侧节点指针II.md) |二叉树 |中等|**递归** **迭代/广度优先搜索**|
|
||||
|[0131.分割回文串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0131.分割回文串.md) |回溯 |中等|**回溯**|
|
||||
@ -311,7 +343,7 @@
|
||||
|[0226.翻转二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0226.翻转二叉树.md) |二叉树 |简单| **递归** **迭代**|
|
||||
|[0232.用栈实现队列](https://github.com/youngyangyang04/leetcode/blob/master/problems/0232.用栈实现队列.md) | 栈 |简单| **栈** |
|
||||
|[0235.二叉搜索树的最近公共祖先](https://github.com/youngyangyang04/leetcode/blob/master/problems/0235.二叉搜索树的最近公共祖先.md) | 二叉搜索树 |简单| **递归** **迭代** |
|
||||
|[0236.二叉树的最近公共祖先](https://github.com/youngyangyang04/leetcode/blob/master/problems/0236.二叉树的最近公共祖先.md) | 二叉树 |中等| **递归/回溯** |
|
||||
|[0236.二叉树的最近公共祖先](https://github.com/youngyangyang04/leetcode/blob/master/problems/0236.二叉树的最近公共祖先.md) | 二叉树 |中等| **递归/回溯** 与其说是递归,不如说是回溯|
|
||||
|[0237.删除链表中的节点](https://github.com/youngyangyang04/leetcode/blob/master/problems/0237.删除链表中的节点.md) |链表 |简单| **原链表移除** **添加虚拟节点** 递归|
|
||||
|[0239.滑动窗口最大值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0239.滑动窗口最大值.md) |滑动窗口/队列 |困难| **单调队列**|
|
||||
|[0242.有效的字母异位词](https://github.com/youngyangyang04/leetcode/blob/master/problems/0242.有效的字母异位词.md) |哈希表 |简单| **哈希**|
|
||||
@ -336,29 +368,32 @@
|
||||
|[0513.找树左下角的值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0513.找树左下角的值.md) |二叉树 |中等|**递归** **迭代**|
|
||||
|[0515.在每个树行中找最大值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0515.在每个树行中找最大值.md) |二叉树 |简单|**广度优先搜索/队列**|
|
||||
|[0530.二叉搜索树的最小绝对差](https://github.com/youngyangyang04/leetcode/blob/master/problems/0530.二叉搜索树的最小绝对差.md) |二叉树搜索树 |简单|**递归** **迭代**|
|
||||
|[0538.把二叉搜索树转换为累加树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0538.把二叉搜索树转换为累加树.md) |二叉树 |简单|**递归** **迭代**|
|
||||
|[0538.把二叉搜索树转换为累加树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0538.把二叉搜索树转换为累加树.md) |二叉搜索树 |简单|**递归** **迭代**|
|
||||
|[0541.反转字符串II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0541.反转字符串II.md) |字符串 |简单| **模拟**|
|
||||
|[0559.N叉树的最大深度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0559.N叉树的最大深度.md) |N叉树 |简单| **递归**|
|
||||
|[0572.另一个树的子树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0572.另一个树的子树.md) |二叉树 |简单| **递归**|
|
||||
|[0575.分糖果](https://github.com/youngyangyang04/leetcode/blob/master/problems/0575.分糖果.md) |哈希表 |简单|**哈希**|
|
||||
|[0589.N叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0589.N叉树的前序遍历.md) |树 |简单|**递归** **栈/迭代**|
|
||||
|[0590.N叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0590.N叉树的后序遍历.md) |树 |简单|**递归** **栈/迭代**|
|
||||
|[0589.N叉树的前序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0589.N叉树的前序遍历.md) |N叉树 |简单|**递归** **栈/迭代**|
|
||||
|[0590.N叉树的后序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0590.N叉树的后序遍历.md) |N叉树 |简单|**递归** **栈/迭代**|
|
||||
|[0617.合并二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0617.合并二叉树.md) |树 |简单|**递归** **迭代**|
|
||||
|[0637.二叉树的层平均值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0637.二叉树的层平均值.md) |树 |简单|**广度优先搜索/队列**|
|
||||
|[0654.最大二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0654.最大二叉树.md) |树 |中等|**递归**|
|
||||
|[0685.冗余连接II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0685.冗余连接II.md) | 并查集/树/图 |困难|**并查集**|
|
||||
|[0669.修剪二叉搜索树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0669.修剪二叉搜索树.md) | 二叉搜索树/二叉树 |简单|**递归** **迭代**|
|
||||
|[0700.二叉搜索树中的搜索](https://github.com/youngyangyang04/leetcode/blob/master/problems/0700.二叉搜索树中的搜索.md) |树 |简单|**递归** **迭代**|
|
||||
|[0701.二叉搜索树中的插入操作](https://github.com/youngyangyang04/leetcode/blob/master/problems/0701.二叉搜索树中的插入操作.md) |树 |简单|**递归** **迭代**|
|
||||
|[0700.二叉搜索树中的搜索](https://github.com/youngyangyang04/leetcode/blob/master/problems/0700.二叉搜索树中的搜索.md) |二叉搜索树 |简单|**递归** **迭代**|
|
||||
|[0701.二叉搜索树中的插入操作](https://github.com/youngyangyang04/leetcode/blob/master/problems/0701.二叉搜索树中的插入操作.md) |二叉搜索树 |简单|**递归** **迭代**|
|
||||
|[0705.设计哈希集合](https://github.com/youngyangyang04/leetcode/blob/master/problems/0705.设计哈希集合.md) |哈希表 |简单|**模拟**|
|
||||
|[0707.设计链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0707.设计链表.md) |链表 |中等|**模拟**|
|
||||
|[0763.划分字母区间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0763.划分字母区间.md) |贪心 |中等|**双指针/贪心** 体现贪心尽可能多的思想|
|
||||
|[0739.每日温度](https://github.com/youngyangyang04/leetcode/blob/master/problems/0739.每日温度.md) |栈 |中等|**单调栈** 适合单调栈入门|
|
||||
|[0841.钥匙和房间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0841.钥匙和房间.md) |孤岛问题 |中等|**bfs** **dfs**|
|
||||
|[0844.比较含退格的字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0844.比较含退格的字符串.md) |字符串 |简单|**栈** **双指针优化** 使用栈的思路但没有必要使用栈|
|
||||
|[0925.长按键入](https://github.com/youngyangyang04/leetcode/blob/master/problems/0925.长按键入.md) |字符串 |简单|**双指针/模拟** 是一道模拟类型的题目|
|
||||
|[0968.监控二叉树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0968.监控二叉树.md) |二叉树 |困难|**贪心** 贪心与二叉树的结合|
|
||||
|[0977.有序数组的平方](https://github.com/youngyangyang04/leetcode/blob/master/problems/0977.有序数组的平方.md) |数组 |中等|**双指针** 还是比较巧妙的|
|
||||
|[1002.查找常用字符](https://github.com/youngyangyang04/leetcode/blob/master/problems/1002.查找常用字符.md) |栈 |简单|**栈**|
|
||||
|[1047.删除字符串中的所有相邻重复项](https://github.com/youngyangyang04/leetcode/blob/master/problems/1047.删除字符串中的所有相邻重复项.md) |哈希表 |简单|**哈希表/数组**|
|
||||
|[1382.将二叉搜索树变平衡](https://github.com/youngyangyang04/leetcode/blob/master/problems/1047.删除字符串中的所有相邻重复项.md) |二叉搜索树 |中等|**递归** **迭代** 98和108的组合题目|
|
||||
|[剑指Offer05.替换空格](https://github.com/youngyangyang04/leetcode/blob/master/problems/剑指Offer05.替换空格.md) |字符串 |简单|**双指针**|
|
||||
|[ 剑指Offer58-I.翻转单词顺序](https://github.com/youngyangyang04/leetcode/blob/master/problems/剑指Offer05.替换空格.md) |字符串 |简单|**模拟/双指针**|
|
||||
|[剑指Offer58-II.左旋转字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/剑指Offer58-II.左旋转字符串.md) |字符串 |简单|**反转操作**|
|
||||
|
BIN
pics/108.将有序数组转换为二叉搜索树.png
Normal file
BIN
pics/108.将有序数组转换为二叉搜索树.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
BIN
pics/234.回文链表.png
Normal file
BIN
pics/234.回文链表.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 129 KiB |
Binary file not shown.
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
BIN
pics/763.划分字母区间.png
Normal file
BIN
pics/763.划分字母区间.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
@ -3,6 +3,12 @@ https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorde
|
||||
|
||||
> 给出两个序列
|
||||
|
||||
看完本文,可以一起解决如下两道题目
|
||||
|
||||
* 106.从中序与后序遍历序列构造二叉树
|
||||
* 105.从前序与中序遍历序列构造二叉树
|
||||
|
||||
|
||||
# 106.从中序与后序遍历序列构造二叉树
|
||||
|
||||
根据一棵树的中序遍历与后序遍历构造二叉树。
|
||||
@ -383,7 +389,7 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
# 105. 从前序与中序遍历序列构造二叉树
|
||||
# 105.从前序与中序遍历序列构造二叉树
|
||||
|
||||
根据一棵树的前序遍历与中序遍历构造二叉树。
|
||||
|
||||
|
@ -1,28 +1,122 @@
|
||||
> 构造二叉搜索树,一不小心就平衡了
|
||||
|
||||
## 思路
|
||||
# 108.将有序数组转换为二叉搜索树
|
||||
|
||||
要考率 和 普通数组转成二叉树有什么差别
|
||||
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
|
||||
|
||||
注意这里是构造平衡二叉搜索树,其实 这里不用强调,因为数组构造二叉树,构成平衡树是自然而然的事情,因为大家默认都是从中间取值,不可能随机取,自找麻烦
|
||||
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
|
||||
|
||||
一想 这道题目还是有难度的,
|
||||
示例:
|
||||
|
||||
一定是递归 分治
|
||||

|
||||
|
||||
循环不变量 的题目列表
|
||||
# 思路
|
||||
|
||||
注意答案不是唯一的
|
||||
做这道题目之前大家可以了解一下这几道:
|
||||
|
||||
输入:[-10,-3,0,5,9]
|
||||
输出:[0,-10,5,null,-3,null,9]
|
||||
预期结果:[0,-3,9,-10,null,5]
|
||||
* [106.从中序与后序遍历序列构造二叉树](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)
|
||||
* [654.最大二叉树](https://mp.weixin.qq.com/s/1iWJV6Aov23A7xCF4nV88w)中其实已经讲过了,如果根据数组构造一颗二叉树。
|
||||
* [701.二叉搜索树中的插入操作](https://mp.weixin.qq.com/s/lwKkLQcfbCNX2W-5SOeZEA)
|
||||
* [450.删除二叉搜索树中的节点](https://mp.weixin.qq.com/s/-p-Txvch1FFk3ygKLjPAKw)
|
||||
|
||||
|
||||
进入正题:
|
||||
|
||||
题目中说要转换为一棵高度平衡二叉搜索树。这和转换为一棵普通二叉搜索树有什么差别呢?
|
||||
|
||||
其实这里不用强调平衡二叉搜索树,数组构造二叉树,构成平衡树是自然而然的事情,因为大家默认都是从数组中间位置取值作为节点元素,一般不会随机取,**所以想构成不平衡的二叉树是自找麻烦**。
|
||||
|
||||
|
||||
在[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)和[二叉树:构造一棵最大的二叉树](https://mp.weixin.qq.com/s/1iWJV6Aov23A7xCF4nV88w)中其实已经讲过了,如果根据数组构造一颗二叉树。
|
||||
|
||||
**本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间**。
|
||||
|
||||
本题其实要比[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg) 和 [二叉树:构造一棵最大的二叉树](https://mp.weixin.qq.com/s/1iWJV6Aov23A7xCF4nV88w)简单一些,因为有序数组构造二叉搜索树,寻找分割点就比较容易了。
|
||||
|
||||
分割点就是数组中间位置的节点。
|
||||
|
||||
那么为问题来了,如果数组长度为偶数,中间节点有两个,取哪一个?
|
||||
|
||||
取哪一个都可以,只不过构成了不同的平衡二叉搜索树。
|
||||
|
||||
例如:输入:[-10,-3,0,5,9]
|
||||
|
||||
如下两棵树,都是这个数组的平衡二叉搜索树:
|
||||
|
||||
<img src='../pics/108.将有序数组转换为二叉搜索树.png' width=600> </img></div>
|
||||
|
||||
如果要分割的数组长度为偶数的时候,中间元素为两个,是取左边元素 就是树1,取右边元素就是树2。
|
||||
|
||||
**这也是题目中强调答案不是唯一的原因。 理解这一点,这道题目算是理解到位了**。
|
||||
|
||||
## 递归
|
||||
|
||||
递归三部曲:
|
||||
|
||||
* 确定递归函数返回值及其参数
|
||||
|
||||
删除二叉树节点,增加二叉树节点,都是用递归函数的返回值来完成,这样是比较方便的。
|
||||
|
||||
相信大家如果仔细看了[二叉树:搜索树中的插入操作](https://mp.weixin.qq.com/s/lwKkLQcfbCNX2W-5SOeZEA)和[二叉树:搜索树中的删除操作](https://mp.weixin.qq.com/s/-p-Txvch1FFk3ygKLjPAKw),一定会对递归函数返回值的作用深有感触。
|
||||
|
||||
那么本题要构造二叉树,依然用递归函数的返回值来构造中节点的左右孩子。
|
||||
|
||||
再来看参数,首先是传入数组,然后就是左下表left和右下表right,我们在[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg)中提过,在构造二叉树的时候尽量不要重新定义左右区间数组,而是用下表来操作原数组。
|
||||
|
||||
所以代码如下:
|
||||
|
||||
```
|
||||
// 左闭右闭区间[left, right]
|
||||
TreeNode* traversal(vector<int>& nums, int left, int right)
|
||||
```
|
||||
|
||||
这里注意,**我这里定义的是左闭右闭区间,在不断分割的过程中,也会坚持左闭右闭的区间,这又涉及到我们讲过的循环不变量**。
|
||||
|
||||
在[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg),[35.搜索插入位置](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q) 和[59.螺旋矩阵II](https://mp.weixin.qq.com/s/KTPhaeqxbMK9CxHUUgFDmg)都详细讲过循环不变量。
|
||||
|
||||
|
||||
* 确定递归终止条件
|
||||
|
||||
这里定义的是左闭右闭的区间,所以当区间 left > right的时候,就是空节点了。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
if (left > right) return nullptr;
|
||||
```
|
||||
|
||||
* 确定单层递归的逻辑
|
||||
|
||||
首先取数组中间元素的位置,不难写出`int mid = (left + right) / 2;`,**这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,在[二分法](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q)中尤其需要注意!**
|
||||
|
||||
所以可以这么写:`int mid = left + ((right - left) / 2);`
|
||||
|
||||
但本题leetcode的测试数据并不会越界,所以怎么写都可以。但需要有这个意识!
|
||||
|
||||
取了中间位置,就开始以中间位置的元素构造节点,代码:`TreeNode* root = new TreeNode(nums[mid]);`。
|
||||
|
||||
接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。
|
||||
|
||||
最后返回root节点,单层递归整体代码如下:
|
||||
|
||||
```
|
||||
int mid = left + ((right - left) / 2);
|
||||
TreeNode* root = new TreeNode(nums[mid]);
|
||||
root->left = traversal(nums, left, mid - 1);
|
||||
root->right = traversal(nums, mid + 1, right);
|
||||
return root;
|
||||
```
|
||||
|
||||
这里`int mid = left + ((right - left) / 2);`的写法相当于是如果数组长度为偶数,中间位置有两个元素,取靠左边的。
|
||||
|
||||
* 递归整体代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
private:
|
||||
TreeNode* traversal(vector<int>& nums, int left, int right) {
|
||||
if (left > right) return nullptr;
|
||||
int mid = (left + right) / 2; // 注意越界
|
||||
int mid = left + ((right - left) / 2);
|
||||
TreeNode* root = new TreeNode(nums[mid]);
|
||||
root->left = traversal(nums, left, mid - 1);
|
||||
root->right = traversal(nums, mid + 1, right);
|
||||
@ -36,3 +130,68 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
**注意:在调用traversal的时候为什么传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭**。
|
||||
|
||||
|
||||
## 迭代法
|
||||
|
||||
迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下表,一个队列放右区间下表。
|
||||
|
||||
模拟的就是不断分割的过程,C++代码如下:(我已经详细注释)
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
TreeNode* sortedArrayToBST(vector<int>& nums) {
|
||||
if (nums.size() == 0) return nullptr;
|
||||
|
||||
TreeNode* root = new TreeNode(0); // 初始根节点
|
||||
queue<TreeNode*> nodeQue; // 放遍历的节点
|
||||
queue<int> leftQue; // 保存左区间下表
|
||||
queue<int> rightQue; // 保存右区间下表
|
||||
nodeQue.push(root); // 根节点入队列
|
||||
leftQue.push(0); // 0为左区间下表初始位置
|
||||
rightQue.push(nums.size() - 1); // nums.size() - 1为右区间下表初始位置
|
||||
|
||||
while (!nodeQue.empty()) {
|
||||
TreeNode* curNode = nodeQue.front();
|
||||
nodeQue.pop();
|
||||
int left = leftQue.front(); leftQue.pop();
|
||||
int right = rightQue.front(); rightQue.pop();
|
||||
int mid = left + ((right - left) / 2);
|
||||
|
||||
curNode->val = nums[mid]; // 将mid对应的元素给中间节点
|
||||
|
||||
if (left <= mid - 1) { // 处理左区间
|
||||
curNode->left = new TreeNode(0);
|
||||
nodeQue.push(curNode->left);
|
||||
leftQue.push(left);
|
||||
rightQue.push(mid - 1);
|
||||
}
|
||||
|
||||
if (right >= mid + 1) { // 处理右区间
|
||||
curNode->right = new TreeNode(0);
|
||||
nodeQue.push(curNode->right);
|
||||
leftQue.push(mid + 1);
|
||||
rightQue.push(right);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
# 总结
|
||||
|
||||
**在[二叉树:构造二叉树登场!](https://mp.weixin.qq.com/s/7r66ap2s-shvVvlZxo59xg) 和 [二叉树:构造一棵最大的二叉树](https://mp.weixin.qq.com/s/1iWJV6Aov23A7xCF4nV88w)之后,我们顺理成章的应该构造一下二叉搜索树了,一不小心还是一棵平衡二叉搜索树**。
|
||||
|
||||
其实思路也是一样的,不断中间分割,然后递归处理左区间,右区间,也可以说是分治。
|
||||
|
||||
此时相信大家应该对通过递归函数的返回值来增删二叉树很熟悉了,这也是常规操作。
|
||||
|
||||
在定义区间的过程中我们又一次强调了循环不变量的重要性。
|
||||
|
||||
最后依然给出迭代的方法,其实就是模拟取中间元素,然后不断分割去构造二叉树的过程。
|
||||
|
||||
**就酱,如果对你有帮助的话,也转发给身边需要的同学吧!**
|
||||
|
||||
|
122
problems/0234.回文链表.md
Normal file
122
problems/0234.回文链表.md
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
## 题目链接
|
||||
https://leetcode-cn.com/problems/palindrome-linked-list/
|
||||
|
||||
## 思路
|
||||
|
||||
### 数组模拟
|
||||
|
||||
最直接的想法,就是把链表装成数组,然后再判断是否回文。
|
||||
|
||||
代码也比较简单。如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
bool isPalindrome(ListNode* head) {
|
||||
vector<int> vec;
|
||||
ListNode* cur = head;
|
||||
while (cur) {
|
||||
vec.push_back(cur->val);
|
||||
cur = cur->next;
|
||||
}
|
||||
// 比较数组回文
|
||||
for (int i = 0, j = vec.size() - 1; i < j; i++, j--) {
|
||||
if (vec[i] != vec[j]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
上面代码可以在优化,就是先求出链表长度,然后给定vector的初始长度,这样避免vector每次添加节点重新开辟空间
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
bool isPalindrome(ListNode* head) {
|
||||
|
||||
ListNode* cur = head;
|
||||
int length = 0;
|
||||
while (cur) {
|
||||
length++;
|
||||
cur = cur->next;
|
||||
}
|
||||
vector<int> vec(length, 0); // 给定vector的初始长度,这样避免vector每次添加节点重新开辟空间
|
||||
cur = head;
|
||||
int index = 0;
|
||||
while (cur) {
|
||||
vec[index++] = cur->val;
|
||||
cur = cur->next;
|
||||
}
|
||||
// 比较数组回文
|
||||
for (int i = 0, j = vec.size() - 1; i < j; i++, j--) {
|
||||
if (vec[i] != vec[j]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### 反转后半部分链表
|
||||
|
||||
分为如下几步:
|
||||
|
||||
* 用快慢指针,快指针有两步,慢指针走一步,快指针遇到终止位置时,慢指针就在链表中间位置
|
||||
* 同时用pre记录慢指针指向节点的前一个节点,用来分割链表
|
||||
* 将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
|
||||
* 将后半部分反转 ,得cur2,前半部分为cur1
|
||||
* 按照cur1的长度,一次比较cur1和cur2的节点数值
|
||||
|
||||
如图所示:
|
||||
|
||||
<img src='../pics/234.回文链表.png' width=600> </img></div>
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
bool isPalindrome(ListNode* head) {
|
||||
if (head == nullptr || head->next == nullptr) return true;
|
||||
ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割
|
||||
ListNode* fast = head;
|
||||
ListNode* pre = head; // 记录慢指针的前一个节点,用来分割链表
|
||||
while (fast && fast->next) {
|
||||
pre = slow;
|
||||
slow = slow->next;
|
||||
fast = fast->next->next;
|
||||
}
|
||||
pre->next = nullptr; // 分割链表
|
||||
|
||||
ListNode* cur1 = head; // 前半部分
|
||||
ListNode* cur2 = reverseList(slow); // 反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点
|
||||
|
||||
// 开始两个链表的比较
|
||||
while (cur1) {
|
||||
if (cur1->val != cur2->val) return false;
|
||||
cur1 = cur1->next;
|
||||
cur2 = cur2->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 反转链表
|
||||
ListNode* reverseList(ListNode* head) {
|
||||
ListNode* temp; // 保存cur的下一个节点
|
||||
ListNode* cur = head;
|
||||
ListNode* pre = nullptr;
|
||||
while(cur) {
|
||||
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
|
||||
cur->next = pre; // 翻转操作
|
||||
// 更新pre 和 cur指针
|
||||
pre = cur;
|
||||
cur = temp;
|
||||
}
|
||||
return pre;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
栈
|
||||
|
11
problems/0402.移掉K位数字.md
Normal file
11
problems/0402.移掉K位数字.md
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
## 思路
|
||||
|
||||
https://www.cnblogs.com/gzshan/p/12560566.html 图不错
|
||||
|
||||
有点难度
|
||||
|
||||
|
||||
暴力的解法,其实也不是那么好写的, 首字符去0,k没消耗完,等等这些情况
|
||||
|
||||
有点难,卡我很久
|
@ -3,28 +3,109 @@
|
||||
|
||||
https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
|
||||
|
||||
## 思路
|
||||
> 祝大家1024节日快乐!!
|
||||
|
||||
一看到累加树,相信很多小伙伴一脸懵逼,如何累加,遇到一个节点,然后在遍历其他节点累加?怎么一想这么麻烦呢。
|
||||
今天应该是一个程序猿普天同庆的日子,所以今天的题目比较简单,只要认真把前面每天的文章都看了,今天的题目就是分分钟的事了,大家可以愉快过节!
|
||||
|
||||
然后发现这是一颗二叉搜索树,二叉搜索树啊,这是有序的啊。
|
||||
# 538.把二叉搜索树转换为累加树
|
||||
|
||||
题目链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
|
||||
|
||||
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
|
||||
|
||||
提醒一下,二叉搜索树满足下列约束条件:
|
||||
|
||||
节点的左子树仅包含键 小于 节点键的节点。
|
||||
节点的右子树仅包含键 大于 节点键的节点。
|
||||
左右子树也必须是二叉搜索树。
|
||||
|
||||
示例 1:
|
||||
|
||||

|
||||
|
||||
输入:[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]
|
||||
|
||||
示例 2:
|
||||
输入:root = [0,null,1]
|
||||
输出:[1,null,1]
|
||||
|
||||
示例 3:
|
||||
输入:root = [1,0,2]
|
||||
输出:[3,3,2]
|
||||
|
||||
示例 4:
|
||||
输入:root = [3,2,4,1]
|
||||
输出:[7,9,4,10]
|
||||
|
||||
提示:
|
||||
|
||||
* 树中的节点数介于 0 和 104 之间。
|
||||
* 每个节点的值介于 -104 和 104 之间。
|
||||
* 树中的所有值 互不相同 。
|
||||
* 给定的树为二叉搜索树。
|
||||
|
||||
# 思路
|
||||
|
||||
一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后在遍历其他节点累加?怎么一想这么麻烦呢。
|
||||
|
||||
然后再发现这是一颗二叉搜索树,二叉搜索树啊,这是有序的啊。
|
||||
|
||||
那么有序的元素如果求累加呢?
|
||||
|
||||
**其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],大家是不是感觉这就是送分题了。**
|
||||
**其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。**
|
||||
|
||||
为什么变成数组就是送分题了呢,因为数组大家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了二叉搜索树,看起来就别扭了一些是不是。
|
||||
为什么变成数组就是感觉简单了呢?
|
||||
|
||||
那么知道如何遍历这个二叉树,也就迎刃而解了,从树中可以看出累加的顺讯是 右中左,所以我们需要中序遍历反过来遍历这个二叉树,然后顺序累加就可以了。
|
||||
因为数组大家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了二叉搜索树,看起来就别扭了一些是不是。
|
||||
|
||||
那么知道如何遍历这个二叉树,也就迎刃而解了,**从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了**。
|
||||
|
||||
## 递归
|
||||
|
||||
遍历顺序如图所示:
|
||||
|
||||
<img src='../pics/538.把二叉搜索树转换为累加树.png' width=600> </img></div>
|
||||
|
||||
本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。
|
||||
|
||||
以下我给出一种递归的写法,两种迭代法的写法,别问我为什么写出了这么多写法,把我写的这个题解[彻底吃透二叉树的前中后序递归法和迭代法!!](https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/che-di-chi-tou-er-cha-shu-de-qian-zhong-hou-xu-d-2/)看了,你也能分分钟写出来三种写法![机智]
|
||||
pre指针的使用技巧,我们在[二叉树:搜索树的最小绝对差](https://mp.weixin.qq.com/s/Hwzml6698uP3qQCC1ctUQQ)和[二叉树:我的众数是多少?](https://mp.weixin.qq.com/s/KSAr6OVQIMC-uZ8MEAnGHg)都提到了,这是常用的操作手段。
|
||||
|
||||
## C++递归代码
|
||||
* 递归函数参数以及返回值
|
||||
|
||||
这里很明确了,不需要递归函数的返回值做什么操作了,要遍历整棵树。
|
||||
|
||||
同时需要定义一个全局变量pre,用来保存cur节点的前一个节点的数值,定义为int型就可以了。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
int pre; // 记录前一个节点的数值
|
||||
void traversal(TreeNode* cur)
|
||||
```
|
||||
|
||||
* 确定终止条件
|
||||
|
||||
遇空就终止。
|
||||
|
||||
```
|
||||
if (cur == NULL) return;
|
||||
```
|
||||
|
||||
* 确定单层递归的逻辑
|
||||
|
||||
注意**要右中左来遍历二叉树**, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
traversal(cur->right); // 右
|
||||
cur->val += pre; // 中
|
||||
pre = cur->val;
|
||||
traversal(cur->left); // 左
|
||||
```
|
||||
|
||||
递归法整体代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
@ -46,7 +127,11 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
## C++迭代法(一)代码
|
||||
## 迭代法
|
||||
|
||||
迭代法其实就是中序模板题了,在[二叉树:前中后序迭代法](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)和[二叉树:前中后序统一方式迭代法](https://mp.weixin.qq.com/s/WKg0Ty1_3SZkztpHubZPRg)可以选一种自己习惯的写法。
|
||||
|
||||
这里我给出其中的一种,代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
@ -77,40 +162,12 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
## C++迭代法(二)代码
|
||||
# 总结
|
||||
|
||||
```
|
||||
class Solution {
|
||||
private:
|
||||
int pre; // 记录前一个节点的数值
|
||||
void traversal(TreeNode* root) {
|
||||
stack<TreeNode*> st;
|
||||
if (root != NULL) st.push(root);
|
||||
while (!st.empty()) {
|
||||
TreeNode* node = st.top();
|
||||
if (node != NULL) {
|
||||
st.pop();
|
||||
if (node->left) st.push(node->left); // 左
|
||||
经历了前面各种二叉树增删改查的洗礼之后,这道题目应该比较简单了。
|
||||
|
||||
st.push(node); // 中
|
||||
st.push(NULL);
|
||||
**好了,二叉树已经接近尾声了,接下来就是要对二叉树来一个大总结了**。
|
||||
|
||||
最后再次祝大家1024节日快乐,哈哈哈!
|
||||
|
||||
if (node->right) st.push(node->right); // 右
|
||||
} else {
|
||||
st.pop();
|
||||
node = st.top();
|
||||
st.pop();
|
||||
node->val += pre; // 处理中间节点
|
||||
pre = node->val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
TreeNode* convertBST(TreeNode* root) {
|
||||
pre = 0;
|
||||
traversal(root);
|
||||
return root;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
@ -97,7 +97,7 @@ if (root->val < low) {
|
||||
}
|
||||
```
|
||||
|
||||
如果root(当前节点)的元素小于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
|
||||
如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
|
||||
|
||||
代码如下:
|
||||
|
||||
|
@ -51,3 +51,4 @@ public:
|
||||
}
|
||||
};
|
||||
```
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
41
problems/0763.划分字母区间.md
Normal file
41
problems/0763.划分字母区间.md
Normal file
@ -0,0 +1,41 @@
|
||||
## 题目链接
|
||||
https://leetcode-cn.com/problems/partition-labels/
|
||||
|
||||
## 思路
|
||||
|
||||
一想到分割字符串就想到了回溯,但本题其实不用那么复杂。
|
||||
|
||||
可以分为如下两步:
|
||||
|
||||
* 统计每一个字符最后出现的位置
|
||||
* 从头遍历字符,如果找到之前字符最大出现位置下标和当前下标相等,则找到了分割点
|
||||
|
||||
如图:
|
||||
|
||||
<img src='../pics/763.划分字母区间.png' width=600> </img></div>
|
||||
|
||||
明白原理之后,代码并不复杂,如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
vector<int> partitionLabels(string S) {
|
||||
int hash[27] = {0}; // i为字符,hash[i]为字符出现的最后位置
|
||||
for (int i = 0; i < S.size(); i++) { // 统计每一个字符最后出现的位置
|
||||
hash[S[i] - 'a'] = i;
|
||||
}
|
||||
vector<int> result;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
for (int i = 0; i < S.size(); i++) {
|
||||
right = max(right, hash[S[i] - 'a']); // 找到字符出现的最远边界
|
||||
if (i == right) {
|
||||
result.push_back(right - left + 1);
|
||||
left = i + 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
```
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
@ -80,3 +80,5 @@ public:
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -118,3 +118,5 @@ public:
|
||||
|
||||
* 时间复杂度:O(n + m)
|
||||
* 空间复杂度:O(1)
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -57,3 +57,5 @@ public:
|
||||
|
||||
时间复杂度:O(n)
|
||||
空间复杂度:O(1)
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -217,3 +217,4 @@ public:
|
||||
}
|
||||
};
|
||||
```
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -73,3 +73,4 @@ public:
|
||||
|
||||
一样的代码多提交几次可能就击败百分之百了.....
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -108,3 +108,5 @@ public:
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
@ -84,5 +84,27 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
当然可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
public:
|
||||
string removeDuplicates(string S) {
|
||||
string result;
|
||||
for(char s : S) {
|
||||
if(result.empty() || result.back() != s) {
|
||||
result.push_back(s);
|
||||
}
|
||||
else {
|
||||
result.pop_back();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
> 更多算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
||||
|
||||
|
46
problems/1382.将二叉搜索树变平衡.md
Normal file
46
problems/1382.将二叉搜索树变平衡.md
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
## 题目地址
|
||||
https://leetcode-cn.com/problems/balance-a-binary-search-tree/
|
||||
|
||||
## 思路
|
||||
|
||||
这道题目,可以中序遍历把二叉树转变为有序数组,然后在根据有序数组构造平衡二叉搜索树。
|
||||
|
||||
建议做这道题之前,先看如下两篇题解:
|
||||
* [98.验证二叉搜索树](https://mp.weixin.qq.com/s/8odY9iUX5eSi0eRFSXFD4Q) 学习二叉搜索树的特性
|
||||
* [108.将有序数组转换为二叉搜索树](https://mp.weixin.qq.com/s/sy3ygnouaZVJs8lhFgl9mw) 学习如何通过有序数组构造二叉搜索树
|
||||
|
||||
这两道题目做过之后,本题分分钟就可以做出来了。
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
class Solution {
|
||||
private:
|
||||
vector<int> vec;
|
||||
// 有序树转成有序数组
|
||||
void traversal(TreeNode* cur) {
|
||||
if (cur == nullptr) {
|
||||
return;
|
||||
}
|
||||
traversal(cur->left);
|
||||
vec.push_back(cur->val);
|
||||
traversal(cur->right);
|
||||
}
|
||||
有序数组转平衡二叉树
|
||||
TreeNode* getTree(vector<int>& nums, int left, int right) {
|
||||
if (left > right) return nullptr;
|
||||
int mid = left + ((right - left) / 2);
|
||||
TreeNode* root = new TreeNode(nums[mid]);
|
||||
root->left = getTree(nums, left, mid - 1);
|
||||
root->right = getTree(nums, mid + 1, right);
|
||||
return root;
|
||||
}
|
||||
|
||||
public:
|
||||
TreeNode* balanceBST(TreeNode* root) {
|
||||
traversal(root);
|
||||
return getTree(vec, 0, vec.size() - 1);
|
||||
}
|
||||
};
|
||||
```
|
Reference in New Issue
Block a user