diff --git a/Assets/Course/Course-Git-03.md b/Assets/Course/Course-Git-03.md index 62eec50d..e92a5c48 100644 --- a/Assets/Course/Course-Git-03.md +++ b/Assets/Course/Course-Git-03.md @@ -65,7 +65,7 @@ - [0676. 实现一个魔法字典](https://leetcode.cn/problems/implement-magic-dictionary/) - [更多字典树题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/06.String/03.String-Multi-Pattern-Matching/02.Trie-List.md) -### Task 03 二叉树(5 天) +### Task 03 二叉树(第 08 ~ 12 天) - 第 08 ~ 09 天学习内容: - [树与二叉树基础知识](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/07.Tree/01.Binary-Tree/01.Binary-Tree-Basic.md) @@ -98,7 +98,7 @@ - [0235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/) - [更多二叉搜索树题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/07.Tree/02.Binary-Search-Tree/02.Binary-Search-Tree-List.md) -### Task 04:并查集(2 天) +### Task 04:并查集(第 13 ~ 14 天) - 第 13 ~14 天学习内容: - [并查集知识](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/07.Tree/05.Union-Find/01.Union-Find.md) diff --git a/Assets/Course/Course-Git-06.md b/Assets/Course/Course-Git-06.md new file mode 100644 index 00000000..cebffca9 --- /dev/null +++ b/Assets/Course/Course-Git-06.md @@ -0,0 +1,103 @@ +# Leetcode 刷题课程第六期 + +## 课程信息 + +- 学习周期:16 天,每天平均花费时间 1 小时 ~ 3 小时不等,根据个人学习接受能力强弱有所浮动。 +- 学习形式:理论学习 + 题目刷题 +- 人群定位:有 Python 语言编程基础,想要学习算法、数据结构基础知识,想在 LeetCode 刷算法题的学员。 +- 难度系数:⭐⭐ + +## 课程大纲 + +### Task 00:熟悉规则(1 天) + +- 组队、修改群昵称。 +- 熟悉打卡规则。 +- 之前从未在 LeetCode 上刷过题的同学建议阅读相关内容:[LeetCode 入门与攻略](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/00.Introduction/03.LeetCode-Guide.md)。 + +--- + +### Task 01:第 001 ~ 012 题(第 01 ~ 04 天) + +- 第 01 天课程题目: + - [0054. 螺旋矩阵](https://leetcode.cn/problems/spiral-matrix/) + - [0048. 旋转图像](https://leetcode.cn/problems/rotate-image/) + - [0215. 数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/) +- 第 02 天课程题目: + - [0912. 排序数组](https://leetcode.cn/problems/sort-an-array/) + - [0088. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/) + - [0169. 多数元素](https://leetcode.cn/problems/majority-element/) +- 第 03 天课程题目: + - [0136. 只出现一次的数字](https://leetcode.cn/problems/single-number/) + - [0056. 合并区间](https://leetcode.cn/problems/merge-intervals/) + - [0179. 最大数](https://leetcode.cn/problems/largest-number/) +- 第 04 天课程题目: + - [0704. 二分查找](https://leetcode.cn/problems/binary-search/) + - [0034. 在排序数组中查找元素的第一个和最后一个位置](https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/) + - [0153. 寻找旋转排序数组中的最小值](https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/) + +### Task 02: 第 013 ~ 025 题( 第 05 ~ 08 天) + +- 第 05 天课程题目: + - [0033. 搜索旋转排序数组](https://leetcode.cn/problems/search-in-rotated-sorted-array/) + - [0162. 寻找峰值](https://leetcode.cn/problems/find-peak-element/) + - [0004. 寻找两个正序数组的中位数](https://leetcode.cn/problems/median-of-two-sorted-arrays/) +- 第 06 天课程题目: + - [0240. 搜索二维矩阵 II](https://leetcode.cn/problems/search-a-2d-matrix-ii/) + - [0069. x 的平方根](https://leetcode.cn/problems/sqrtx/) + - [0283. 移动零](https://leetcode.cn/problems/move-zeroes/) +- 第 07 天课程题目: + - [0415. 字符串相加](https://leetcode.cn/problems/add-strings/) + - [0239. 滑动窗口最大值](https://leetcode.cn/problems/sliding-window-maximum/) + - [0003. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/) +- 第 08 天课程题目: + - [0076. 最小覆盖子串](https://leetcode.cn/problems/minimum-window-substring/) + - [0718. 最长重复子数组](https://leetcode.cn/problems/maximum-length-of-repeated-subarray/) + - [0083. 删除排序链表中的重复元素](https://leetcode.cn/problems/remove-duplicates-from-sorted-list/) + - [0082. 删除排序链表中的重复元素 II](https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/) + +### Task 03 第 026 ~ 037 题(第 09 ~ 12 天) + +- 第 09 天课程题目: + - [0206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/) + - [0092. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/) + - [0025. K 个一组翻转链表](https://leetcode.cn/problems/reverse-nodes-in-k-group/) +- 第 10 天课程题目: + - [0234. 回文链表](https://leetcode.cn/problems/palindrome-linked-list/) + - [0021. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/) + - [0148. 排序链表](https://leetcode.cn/problems/sort-list/) +- 第 11 天课程题目: + - [0023. 合并K个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/) + - [0141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/) + - [0142. 环形链表 II](https://leetcode.cn/problems/linked-list-cycle-ii/) +- 第 12 天课程题目: + - [0160. 相交链表](https://leetcode.cn/problems/intersection-of-two-linked-lists/) + - [0019. 删除链表的倒数第 N 个结点](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/) + - [0143. 重排链表](https://leetcode.cn/problems/reorder-list/) + +### Task 04:第 038 ~ 050 题(第 13 ~ 16 天) + +- 第 13 天课程题目: + - [0002. 两数相加](https://leetcode.cn/problems/add-two-numbers/) + - [0155. 最小栈](https://leetcode.cn/problems/min-stack/) + - [0020. 有效的括号](https://leetcode.cn/problems/valid-parentheses/) +- 第 14 天课程题目: + - [0227. 基本计算器 II](https://leetcode.cn/problems/basic-calculator-ii/) + - [0232. 用栈实现队列](https://leetcode.cn/problems/implement-queue-using-stacks/) + - [0394. 字符串解码](https://leetcode.cn/problems/decode-string/) +- 第 15 天课程题目: + - [0032. 最长有效括号](https://leetcode.cn/problems/longest-valid-parentheses/) + - [0042. 接雨水](https://leetcode.cn/problems/trapping-rain-water/) + - [0225. 用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/) +- 第 16 天课程题目: + - [0001. 两数之和](https://leetcode.cn/problems/two-sum/) + - [0015. 三数之和](https://leetcode.cn/problems/3sum/) + - [0041. 缺失的第一个正数](https://leetcode.cn/problems/first-missing-positive/) + - [0128. 最长连续序列](https://leetcode.cn/problems/longest-consecutive-sequence/) +- [更多面试题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/00.Introduction/07.Interview-200-List.md) + +### 附加题目 + +- [0146. LRU 缓存](https://leetcode.cn/problems/lru-cache/) +- [0460. LFU 缓存](https://leetcode.cn/problems/lfu-cache/) +- [0031. 下一个排列](https://leetcode.cn/problems/next-permutation/) \ No newline at end of file diff --git a/Assets/Course/Course-Git-07.md b/Assets/Course/Course-Git-07.md new file mode 100644 index 00000000..21f9eb64 --- /dev/null +++ b/Assets/Course/Course-Git-07.md @@ -0,0 +1,103 @@ +# Leetcode 刷题课程第七期 + +## 课程信息 + +- 学习周期:16 天,每天平均花费时间 1 小时 ~ 3 小时不等,根据个人学习接受能力强弱有所浮动。 +- 学习形式:理论学习 + 题目刷题 +- 人群定位:有 Python 语言编程基础,想要学习算法、数据结构基础知识,想在 LeetCode 刷算法题的学员。 +- 难度系数:⭐⭐ + +## 课程大纲 + +### Task 00:熟悉规则(1 天) + +- 组队、修改群昵称。 +- 熟悉打卡规则。 +- 之前从未在 LeetCode 上刷过题的同学建议阅读相关内容:[LeetCode 入门与攻略](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/00.Introduction/03.LeetCode-Guide.md)。 + +--- + +### Task 01:第 051 ~ 062 题(第 01 ~ 04 天) + +- 第 01 天课程题目: + - [0003. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/) + - [0005. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/) + - [0008. 字符串转换整数 (atoi)](https://leetcode.cn/problems/string-to-integer-atoi/) +- 第 02 天课程题目: + - [0151. 反转字符串中的单词](https://leetcode.cn/problems/reverse-words-in-a-string/) + - [0043. 字符串相乘](https://leetcode.cn/problems/multiply-strings/) + - [0014. 最长公共前缀](https://leetcode.cn/problems/longest-common-prefix/) +- 第 03 天课程题目: + - [0144. 二叉树的前序遍历](https://leetcode.cn/problems/binary-tree-preorder-traversal/) + - [0094. 二叉树的中序遍历](https://leetcode.cn/problems/binary-tree-inorder-traversal/) + - [0102. 二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/) +- 第 04 天课程题目: + - [0103. 二叉树的锯齿形层序遍历](https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/) + - [0236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/) + - [0104. 二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/) + +### Task 02: 第 063 ~ 074 题( 第 05 ~ 08 天) + +- 第 05 天课程题目: + - [0112. 路径总和](https://leetcode.cn/problems/path-sum/) + - [0113. 路径总和 II](https://leetcode.cn/problems/path-sum-ii/) + - [0101. 对称二叉树](https://leetcode.cn/problems/symmetric-tree/) +- 第 06 天课程题目: + - [0124. 二叉树中的最大路径和](https://leetcode.cn/problems/binary-tree-maximum-path-sum/) + - [0199. 二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/) + - [0226. 翻转二叉树](https://leetcode.cn/problems/invert-binary-tree/) +- 第 07 天课程题目: + - [0105. 从前序与中序遍历序列构造二叉树](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) + - [0098. 验证二叉搜索树](https://leetcode.cn/problems/validate-binary-search-tree/) + - [0110. 平衡二叉树](https://leetcode.cn/problems/balanced-binary-tree/) +- 第 08 天课程题目: + - [0200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/) + - [0695. 岛屿的最大面积](https://leetcode.cn/problems/max-area-of-island/) + - [0129. 求根节点到叶节点数字之和](https://leetcode.cn/problems/sum-root-to-leaf-numbers/) + +### Task 03 第 075 ~ 087(第 09 ~ 12 天) + +- 第 09 天课程题目: + - [0199. 二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/) + - [0543. 二叉树的直径](https://leetcode.cn/problems/diameter-of-binary-tree/) + - [0662. 二叉树最大宽度](https://leetcode.cn/problems/maximum-width-of-binary-tree/) +- 第 10 天课程题目: + - [0322. 零钱兑换](https://leetcode.cn/problems/coin-change/) + - [0078. 子集](https://leetcode.cn/problems/subsets/) + - [0221. 最大正方形](https://leetcode.cn/problems/maximal-square/) +- 第 11 天课程题目: + - [0024. 两两交换链表中的节点](https://leetcode.cn/problems/swap-nodes-in-pairs/) + - [0070. 爬楼梯](https://leetcode.cn/problems/climbing-stairs/) + - [0053. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/) +- 第 12 天课程题目: + - [0046. 全排列](https://leetcode.cn/problems/permutations/) + - [0022. 括号生成](https://leetcode.cn/problems/generate-parentheses/) + - [0039. 组合总和](https://leetcode.cn/problems/combination-sum/) + - [0093. 复原 IP 地址](https://leetcode.cn/problems/restore-ip-addresses/) + +### Task 04:第 088 ~ 100 题(第 13 ~ 16 天) + +- 第 13 天课程题目: + - [0121. 买卖股票的最佳时机](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/) + - [0122. 买卖股票的最佳时机 II](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/) + - [0300. 最长递增子序列](https://leetcode.cn/problems/longest-increasing-subsequence/) +- 第 14 天课程题目: + - [1143. 最长公共子序列](https://leetcode.cn/problems/longest-common-subsequence/) + - [0064. 最小路径和](https://leetcode.cn/problems/minimum-path-sum/) + - [0072. 编辑距离](https://leetcode.cn/problems/edit-distance/) +- 第 15 天课程题目: + - [0062. 不同路径](https://leetcode.cn/problems/unique-paths/) + - [0152. 乘积最大子数组](https://leetcode.cn/problems/maximum-product-subarray/) + - [0198. 打家劫舍](https://leetcode.cn/problems/house-robber/) +- 第 16 天课程题目: + - [0138. 复制带随机指针的链表](https://leetcode.cn/problems/copy-list-with-random-pointer/) + - [0297. 二叉树的序列化与反序列化](https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/) + - [0209. 长度最小的子数组](https://leetcode.cn/problems/minimum-size-subarray-sum/) + - [0139. 单词拆分](https://leetcode.cn/problems/word-break/) +- [更多面试题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/00.Introduction/07.Interview-200-List.md) + +### 附加题目 + +- [0165. 比较版本号](https://leetcode.cn/problems/compare-version-numbers/) +- [0468. 验证IP地址](https://leetcode.cn/problems/validate-ip-address/) +- [0470. 用 Rand7() 实现 Rand10()](https://leetcode.cn/problems/implement-rand10-using-rand7/) \ No newline at end of file diff --git a/Assets/Origins/Categories-List.md b/Assets/Origins/Categories-List.md index 6e863336..41b432d2 100644 --- a/Assets/Origins/Categories-List.md +++ b/Assets/Origins/Categories-List.md @@ -143,7 +143,7 @@ ### [单模式串匹配题目](../../Contents/06.String/02.String-Single-Pattern-Matching/07.String-Single-Pattern-Matching-List.md) -###### 0028. 找出字符串中第一个匹配项的下标、0459. 重复的子字符串、0686. 重复叠加字符串匹配、0796. 旋转字符串、1408. 数组中的字符串匹配、2156. 查找给定哈希值的子串 +###### 0028. 找出字符串中第一个匹配项的下标、0459. 重复的子字符串、0686. 重复叠加字符串匹配、1668. 最大重复子字符串、0796. 旋转字符串、1408. 数组中的字符串匹配、2156. 查找给定哈希值的子串 ### [字典树题目](../../Contents/06.String/03.String-Multi-Pattern-Matching/02.Trie-List.md) @@ -235,11 +235,11 @@ ### [枚举算法题目](../../Contents/09.Algorithm-Base/01.Enumeration-Algorithm/02.Enumeration-Algorithm-List.md) -###### 0001. 两数之和、0204. 计数质数、1925. 统计平方和三元组的数目、1450. 在既定时间做作业的学生人数、剑指 Offer 57 - II. 和为s的连续正数序列、0078. 子集、0090. 子集 II、0800. 相似 RGB 颜色、0221. 最大正方形、0560. 和为 K 的子数组 +###### 0001. 两数之和、0204. 计数质数、1925. 统计平方和三元组的数目、1450. 在既定时间做作业的学生人数、1620. 网络信号最好的坐标、剑指 Offer 57 - II. 和为s的连续正数序列、0078. 子集、0090. 子集 II、0800. 相似 RGB 颜色、0221. 最大正方形、0560. 和为 K 的子数组 ### [递归算法题目](../../Contents/09.Algorithm-Base/02.Recursive-Algorithm/02.Recursive-Algorithm-List.md) -###### 0344. 反转字符串、0024. 两两交换链表中的节点、0118. 杨辉三角、0119. 杨辉三角 II、0206. 反转链表、0092. 反转链表 II、0021. 合并两个有序链表、0509. 斐波那契数、0070. 爬楼梯、0104. 二叉树的最大深度、0124. 二叉树中的最大路径和、0226. 翻转二叉树、0050. Pow(x, n)、0021. 合并两个有序链表、0779. 第K个语法符号、0095. 不同的二叉搜索树 II、剑指 Offer 62. 圆圈中最后剩下的数字 +###### 0344. 反转字符串、0024. 两两交换链表中的节点、0118. 杨辉三角、0119. 杨辉三角 II、0206. 反转链表、0092. 反转链表 II、0021. 合并两个有序链表、0509. 斐波那契数、0070. 爬楼梯、0104. 二叉树的最大深度、0124. 二叉树中的最大路径和、0226. 翻转二叉树、0050. Pow(x, n)、0779. 第K个语法符号、0095. 不同的二叉搜索树 II、剑指 Offer 62. 圆圈中最后剩下的数字 ### [分治算法题目](../../Contents/09.Algorithm-Base/03.Divide-And-Conquer-Algorithm/02.Divide-And-Conquer-Algorithm-List.md) diff --git a/Contents/00.Introduction/05.Categories-List.md b/Contents/00.Introduction/05.Categories-List.md index cf8dfd58..19c8decc 100644 --- a/Contents/00.Introduction/05.Categories-List.md +++ b/Contents/00.Introduction/05.Categories-List.md @@ -429,6 +429,7 @@ | 0028 | [找出字符串中第一个匹配项的下标](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0028.%20%E6%89%BE%E5%87%BA%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%B9%E9%85%8D%E9%A1%B9%E7%9A%84%E4%B8%8B%E6%A0%87.md) | 字符串、双指针 | 简单 | | 0459 | [重复的子字符串](https://leetcode.cn/problems/repeated-substring-pattern/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0459.%20%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2.md) | 字符串、字符串匹配 | 简单 | | 0686 | [重复叠加字符串匹配](https://leetcode.cn/problems/repeated-string-match/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0686.%20%E9%87%8D%E5%A4%8D%E5%8F%A0%E5%8A%A0%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D.md) | 字符串、字符串匹配 | 中等 | +| 1668 | 最大重复子字符串 | | | | | 0796 | [旋转字符串](https://leetcode.cn/problems/rotate-string/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0796.%20%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.md) | 字符串、字符串匹配 | 简单 | | 1408 | [数组中的字符串匹配](https://leetcode.cn/problems/string-matching-in-an-array/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1408.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D.md) | 字符串、字符串匹配 | 简单 | | 2156 | [查找给定哈希值的子串](https://leetcode.cn/problems/find-substring-with-given-hash-value/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/2156.%20%E6%9F%A5%E6%89%BE%E7%BB%99%E5%AE%9A%E5%93%88%E5%B8%8C%E5%80%BC%E7%9A%84%E5%AD%90%E4%B8%B2.md) | 字符串、滑动窗口、哈希函数、滚动哈希 | 中等 | @@ -707,6 +708,7 @@ | 0204 | [计数质数](https://leetcode.cn/problems/count-primes/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0204.%20%E8%AE%A1%E6%95%B0%E8%B4%A8%E6%95%B0.md) | 数学、哈希表 | 简单 | | 1925 | [统计平方和三元组的数目](https://leetcode.cn/problems/count-square-sum-triples/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1925.%20%E7%BB%9F%E8%AE%A1%E5%B9%B3%E6%96%B9%E5%92%8C%E4%B8%89%E5%85%83%E7%BB%84%E7%9A%84%E6%95%B0%E7%9B%AE.md) | 数学、枚举 | 简单 | | 1450 | [在既定时间做作业的学生人数](https://leetcode.cn/problems/number-of-students-doing-homework-at-a-given-time/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1450.%20%E5%9C%A8%E6%97%A2%E5%AE%9A%E6%97%B6%E9%97%B4%E5%81%9A%E4%BD%9C%E4%B8%9A%E7%9A%84%E5%AD%A6%E7%94%9F%E4%BA%BA%E6%95%B0.md) | 数组 | 简单 | +| 1620 | 网络信号最好的坐标 | | | | | 剑指 Offer 57 - II | [和为s的连续正数序列](https://leetcode.cn/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/%E5%89%91%E6%8C%87%20Offer%2057%20-%20II.%20%E5%92%8C%E4%B8%BAs%E7%9A%84%E8%BF%9E%E7%BB%AD%E6%AD%A3%E6%95%B0%E5%BA%8F%E5%88%97.md) | 数学、双指针、枚举 | 简单 | | 0078 | [子集](https://leetcode.cn/problems/subsets/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0078.%20%E5%AD%90%E9%9B%86.md) | 位运算、数组、回溯算法 | 中等 | | 0090 | [子集 II](https://leetcode.cn/problems/subsets-ii/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0090.%20%E5%AD%90%E9%9B%86%20II.md) | 位运算、数组、回溯 | 中等 | @@ -731,7 +733,6 @@ | 0124 | [二叉树中的最大路径和](https://leetcode.cn/problems/binary-tree-maximum-path-sum/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0124.%20%E4%BA%8C%E5%8F%89%E6%A0%91%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E8%B7%AF%E5%BE%84%E5%92%8C.md) | 树、深度优先搜索、动态规划、二叉树 | 困难 | | 0226 | [翻转二叉树](https://leetcode.cn/problems/invert-binary-tree/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0226.%20%E7%BF%BB%E8%BD%AC%E4%BA%8C%E5%8F%89%E6%A0%91.md) | 树、递归 | 简单 | | 0050 | [Pow(x, n)](https://leetcode.cn/problems/powx-n/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0050.%20Pow%28x%2C%20n%29.md) | 数学、二分查找 | 中等 | -| 0021 | [合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0021.%20%E5%90%88%E5%B9%B6%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E9%93%BE%E8%A1%A8.md) | 递归、链表 | 简单 | | 0779 | [第K个语法符号](https://leetcode.cn/problems/k-th-symbol-in-grammar/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0779.%20%E7%AC%ACK%E4%B8%AA%E8%AF%AD%E6%B3%95%E7%AC%A6%E5%8F%B7.md) | 递归 | 中等 | | 0095 | [不同的二叉搜索树 II](https://leetcode.cn/problems/unique-binary-search-trees-ii/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0095.%20%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%20II.md) | 树、二叉搜索树、动态规划、回溯、二叉树 | 中等 | | 剑指 Offer 62 | [圆圈中最后剩下的数字](https://leetcode.cn/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/%E5%89%91%E6%8C%87%20Offer%2062.%20%E5%9C%86%E5%9C%88%E4%B8%AD%E6%9C%80%E5%90%8E%E5%89%A9%E4%B8%8B%E7%9A%84%E6%95%B0%E5%AD%97.md) | 递归、数学 | 简单 | diff --git a/Contents/04.Queue/02.Priority-Queue/01.Priority-Queue.md b/Contents/04.Queue/02.Priority-Queue/01.Priority-Queue.md index b292c3e4..f191b543 100644 --- a/Contents/04.Queue/02.Priority-Queue/01.Priority-Queue.md +++ b/Contents/04.Queue/02.Priority-Queue/01.Priority-Queue.md @@ -32,15 +32,15 @@ - **数组(顺序存储)实现优先队列**:入队操作直接插入到数组队尾,时间复杂度为 $O(1)$。出队操作需要遍历整个数组,找到优先级最高的元素,返回并删除该元素,时间复杂度为 $O(n)$。 - **链表(链式存储)实现优先队列**:链表中的元素按照优先级排序,入队操作需要为待插入元素创建节点,并在链表中找到合适的插入位置,时间复杂度为 $O(n)$。出队操作直接返回链表队头元素,并删除队头元素,时间复杂度为 $O(1)$。 -- **二叉堆结构实现优先队列**:构建一个二叉堆结构,二叉堆按照优先级进行排序。入队操作就是将元素插入到二叉堆中合适位置,时间复杂度为 $O(log_2n)$。吹对操作则返回二叉堆中优先级最大节点并删除,时间复杂度也是 $O(log_2n)$。 +- **二叉堆结构实现优先队列**:构建一个二叉堆结构,二叉堆按照优先级进行排序。入队操作就是将元素插入到二叉堆中合适位置,时间复杂度为 $O(\log_2n)$。吹对操作则返回二叉堆中优先级最大节点并删除,时间复杂度也是 $O(\log_2n)$。 下面是三种结构实现的优先队列入队操作和出队操作的时间复杂度总结。 | | 入队操作时间复杂度 | 出队操作(取出优先级最高的元素)时间复杂度 | | ---- | ------------------ | ------------------------------------------ | -| 堆 | $O(log_2n)$ | $O(log_2n)$ | -| 数组 | $O(n)$ | $O(1)$ | -| 链表 | $O(1)$ | $O(n)$ | +| 堆 | $O(\log_2n)$ | $O(\log_2n)$ | +| 数组 | $O(1)$ | $O(n)$ | +| 链表 | $O(n)$ | $O(1)$ | 从上面的表格可以看出,使用「二叉堆」这种数据结构来实现优先队列是比较高效的。下面我们来讲解一下二叉堆实现的优先队列。 @@ -299,9 +299,9 @@ class Solution: 1. 使用哈希表记录下数组中各个元素的频数。 2. 然后将哈希表中的元素去重,转换为新数组。时间复杂度 $O(n)$,空间复杂度 $O(n)$。 3. 使用二叉堆构建优先队列,优先级为元素频数。此时堆顶元素即为频数最高的元素。时间复杂度 $O(n)$,空间复杂度 $O(n)$。 -4. 将堆顶元素加入到答案数组中,进行出队操作。时间复杂度 $O(log{n})$。 +4. 将堆顶元素加入到答案数组中,进行出队操作。时间复杂度 $O(\log_2 n)$。 - 出队操作:交换堆顶元素与末尾元素,将末尾元素已移出堆。继续调整大顶堆。 -5. 不断重复第 4 步,直到 `k` 次结束。调整 `k` 次的时间复杂度 $O(nlog{n})$。 +5. 不断重复第 4 步,直到 `k` 次结束。调整 `k` 次的时间复杂度 $O(n\log_2 n)$。 ##### 思路 1:代码 diff --git a/Contents/06.String/02.String-Single-Pattern-Matching/07.String-Single-Pattern-Matching-List.md b/Contents/06.String/02.String-Single-Pattern-Matching/07.String-Single-Pattern-Matching-List.md index 50d08132..f3e14647 100644 --- a/Contents/06.String/02.String-Single-Pattern-Matching/07.String-Single-Pattern-Matching-List.md +++ b/Contents/06.String/02.String-Single-Pattern-Matching/07.String-Single-Pattern-Matching-List.md @@ -5,6 +5,7 @@ | 0028 | [找出字符串中第一个匹配项的下标](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0028.%20%E6%89%BE%E5%87%BA%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%B9%E9%85%8D%E9%A1%B9%E7%9A%84%E4%B8%8B%E6%A0%87.md) | 字符串、双指针 | 简单 | | 0459 | [重复的子字符串](https://leetcode.cn/problems/repeated-substring-pattern/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0459.%20%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2.md) | 字符串、字符串匹配 | 简单 | | 0686 | [重复叠加字符串匹配](https://leetcode.cn/problems/repeated-string-match/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0686.%20%E9%87%8D%E5%A4%8D%E5%8F%A0%E5%8A%A0%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D.md) | 字符串、字符串匹配 | 中等 | +| 1668 | 最大重复子字符串 | | | | | 0796 | [旋转字符串](https://leetcode.cn/problems/rotate-string/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0796.%20%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.md) | 字符串、字符串匹配 | 简单 | | 1408 | [数组中的字符串匹配](https://leetcode.cn/problems/string-matching-in-an-array/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1408.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D.md) | 字符串、字符串匹配 | 简单 | | 2156 | [查找给定哈希值的子串](https://leetcode.cn/problems/find-substring-with-given-hash-value/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/2156.%20%E6%9F%A5%E6%89%BE%E7%BB%99%E5%AE%9A%E5%93%88%E5%B8%8C%E5%80%BC%E7%9A%84%E5%AD%90%E4%B8%B2.md) | 字符串、滑动窗口、哈希函数、滚动哈希 | 中等 | diff --git a/Contents/07.Tree/02.Binary-Search-Tree/01.Binary-Search-Tree.md b/Contents/07.Tree/02.Binary-Search-Tree/01.Binary-Search-Tree.md index 1cb90d6f..4527f538 100644 --- a/Contents/07.Tree/02.Binary-Search-Tree/01.Binary-Search-Tree.md +++ b/Contents/07.Tree/02.Binary-Search-Tree/01.Binary-Search-Tree.md @@ -6,11 +6,11 @@ > - 如果任意节点的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。 > - 任意节点的左子树、右子树均为二叉搜索树。 -如图所示,这 `3` 棵树都是二叉搜索树。 +如图所示,这 $3$ 棵树都是二叉搜索树。 ![img](https://qcdn.itcharge.cn/images/20220218175944.png) -二叉树具有一个特性,即:**左子树的节点值 < 根节点值 < 右子树的节点值**。 +二叉树具有一个特性,即:$左子树的节点值 < 根节点值 < 右子树的节点值$。 根据这个特性,如果我们以中序遍历的方式遍历整个二叉搜索树时,会得到一个递增序列。例如,一棵二叉搜索树的中序遍历序列如下图所示。 @@ -47,9 +47,9 @@ class Solution: ### 2.3 二叉搜索树的查找算法分析 - 二叉搜索树的查找时间复杂度和树的形态有关。 -- 在最好情况下,二叉搜索树的形态与二分查找的判定树相似。每次查找都可以所辖一半搜索范围。查找路径最多从根节点到叶子节点,比较次数最多为树的高度 $log n$。在最好情况下查找的时间复杂度为 $O(log_2 n)$。 +- 在最好情况下,二叉搜索树的形态与二分查找的判定树相似。每次查找都可以所辖一半搜索范围。查找路径最多从根节点到叶子节点,比较次数最多为树的高度 $\log_2 n$。在最好情况下查找的时间复杂度为 $O(\log_2 n)$。 - 在最坏情况下,二叉搜索树的形态为单支树,即只有左子树或者只有右子树。每次查找的搜索范围都缩小为 $n - 1$,退化为顺序查找,在最坏情况下时间复杂度为 $O(n)$。 -- 在平均情况下,二叉搜索树的平均查找长度为 $ASL = [(n+1)/n] * log_2(n+1) - 1$。所以二分搜索树的查找平均时间复杂度为 $O(log_2 n)$。 +- 在平均情况下,二叉搜索树的平均查找长度为 $ASL = [(n + 1) / n] * /log_2(n+1) - 1$。所以二分搜索树的查找平均时间复杂度为 $O(log_2 n)$。 ## 3. 二叉搜索树的插入 @@ -117,7 +117,7 @@ class Solution: ### 5.1 二叉搜索树的删除算法步骤 -在二叉搜索树中删除元素,首先要找到待删除节点,然后执行删除操作。根据待删除节点所在位置的不同,可以分为 `3` 种情况: +在二叉搜索树中删除元素,首先要找到待删除节点,然后执行删除操作。根据待删除节点所在位置的不同,可以分为 $3$ 种情况: 1. 被删除节点的左子树为空。则令其右子树代替被删除节点的位置。 2. 被删除节点的右子树为空。则令其左子树代替被删除节点的位置。 diff --git a/Contents/09.Algorithm-Base/01.Enumeration-Algorithm/02.Enumeration-Algorithm-List.md b/Contents/09.Algorithm-Base/01.Enumeration-Algorithm/02.Enumeration-Algorithm-List.md index ae634eae..dbb7be6e 100644 --- a/Contents/09.Algorithm-Base/01.Enumeration-Algorithm/02.Enumeration-Algorithm-List.md +++ b/Contents/09.Algorithm-Base/01.Enumeration-Algorithm/02.Enumeration-Algorithm-List.md @@ -6,6 +6,7 @@ | 0204 | [计数质数](https://leetcode.cn/problems/count-primes/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0204.%20%E8%AE%A1%E6%95%B0%E8%B4%A8%E6%95%B0.md) | 数学、哈希表 | 简单 | | 1925 | [统计平方和三元组的数目](https://leetcode.cn/problems/count-square-sum-triples/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1925.%20%E7%BB%9F%E8%AE%A1%E5%B9%B3%E6%96%B9%E5%92%8C%E4%B8%89%E5%85%83%E7%BB%84%E7%9A%84%E6%95%B0%E7%9B%AE.md) | 数学、枚举 | 简单 | | 1450 | [在既定时间做作业的学生人数](https://leetcode.cn/problems/number-of-students-doing-homework-at-a-given-time/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/1450.%20%E5%9C%A8%E6%97%A2%E5%AE%9A%E6%97%B6%E9%97%B4%E5%81%9A%E4%BD%9C%E4%B8%9A%E7%9A%84%E5%AD%A6%E7%94%9F%E4%BA%BA%E6%95%B0.md) | 数组 | 简单 | +| 1620 | 网络信号最好的坐标 | | | | | 剑指 Offer 57 - II | [和为s的连续正数序列](https://leetcode.cn/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/%E5%89%91%E6%8C%87%20Offer%2057%20-%20II.%20%E5%92%8C%E4%B8%BAs%E7%9A%84%E8%BF%9E%E7%BB%AD%E6%AD%A3%E6%95%B0%E5%BA%8F%E5%88%97.md) | 数学、双指针、枚举 | 简单 | | 0078 | [子集](https://leetcode.cn/problems/subsets/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0078.%20%E5%AD%90%E9%9B%86.md) | 位运算、数组、回溯算法 | 中等 | | 0090 | [子集 II](https://leetcode.cn/problems/subsets-ii/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0090.%20%E5%AD%90%E9%9B%86%20II.md) | 位运算、数组、回溯 | 中等 | diff --git a/Contents/09.Algorithm-Base/02.Recursive-Algorithm/02.Recursive-Algorithm-List.md b/Contents/09.Algorithm-Base/02.Recursive-Algorithm/02.Recursive-Algorithm-List.md index 6f7017c3..ddb1cdfb 100644 --- a/Contents/09.Algorithm-Base/02.Recursive-Algorithm/02.Recursive-Algorithm-List.md +++ b/Contents/09.Algorithm-Base/02.Recursive-Algorithm/02.Recursive-Algorithm-List.md @@ -15,7 +15,6 @@ | 0124 | [二叉树中的最大路径和](https://leetcode.cn/problems/binary-tree-maximum-path-sum/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0124.%20%E4%BA%8C%E5%8F%89%E6%A0%91%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E8%B7%AF%E5%BE%84%E5%92%8C.md) | 树、深度优先搜索、动态规划、二叉树 | 困难 | | 0226 | [翻转二叉树](https://leetcode.cn/problems/invert-binary-tree/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0226.%20%E7%BF%BB%E8%BD%AC%E4%BA%8C%E5%8F%89%E6%A0%91.md) | 树、递归 | 简单 | | 0050 | [Pow(x, n)](https://leetcode.cn/problems/powx-n/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0050.%20Pow%28x%2C%20n%29.md) | 数学、二分查找 | 中等 | -| 0021 | [合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0021.%20%E5%90%88%E5%B9%B6%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E9%93%BE%E8%A1%A8.md) | 递归、链表 | 简单 | | 0779 | [第K个语法符号](https://leetcode.cn/problems/k-th-symbol-in-grammar/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0779.%20%E7%AC%ACK%E4%B8%AA%E8%AF%AD%E6%B3%95%E7%AC%A6%E5%8F%B7.md) | 递归 | 中等 | | 0095 | [不同的二叉搜索树 II](https://leetcode.cn/problems/unique-binary-search-trees-ii/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/0095.%20%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%20II.md) | 树、二叉搜索树、动态规划、回溯、二叉树 | 中等 | | 剑指 Offer 62 | [圆圈中最后剩下的数字](https://leetcode.cn/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/) | [Python](https://github.com/itcharge/LeetCode-Py/blob/main/Solutions/%E5%89%91%E6%8C%87%20Offer%2062.%20%E5%9C%86%E5%9C%88%E4%B8%AD%E6%9C%80%E5%90%8E%E5%89%A9%E4%B8%8B%E7%9A%84%E6%95%B0%E5%AD%97.md) | 递归、数学 | 简单 | diff --git "a/Solutions/0098. \351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" "b/Solutions/0098. \351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" index f44f7500..66b9783b 100644 --- "a/Solutions/0098. \351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" +++ "b/Solutions/0098. \351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" @@ -5,25 +5,50 @@ ## 题目大意 -给定一个二叉树,判断其是否是一个有效的二叉搜索树。 +**描述**:给定一个二叉树的根节点 `root`。 -二叉搜索树特征: +**要求**:判断其是否是一个有效的二叉搜索树。 -- 节点的左子树只包含小于当前节点的数。 -- 节点的右子树只包含大于当前节点的数。 -- 所有左子树和右子树自身必须也是二叉搜索树。 +**说明**: -## 解题思路 +- **二叉搜索树特征**: + - 节点的左子树只包含小于当前节点的数。 + - 节点的右子树只包含大于当前节点的数。 + - 所有左子树和右子树自身必须也是二叉搜索树。 +- 树中节点数目范围在$[1, 10^4]$ 内。 +- $-2^{31} \le Node.val \le 2^{31} - 1$。 -根据题意进行递归遍历即可。前序、中序、后序遍历都可以。 +**示例**: + +![img](https://assets.leetcode.com/uploads/2020/12/01/tree1.jpg) + +```Python +输入:root = [2,1,3] +输出:true +``` + +![img](https://assets.leetcode.com/uploads/2020/12/01/tree2.jpg) -以前序遍历为例,递归函数为:`preorderTraversal(root, min_v, max_v)` +```Python +输入:root = [5,1,4,null,null,3,6] +输出:false +解释:根节点的值是 5 ,但是右子节点的值是 4 。 +``` -前序遍历时,先判断根节点的值是否在 (min_v, max_v) 之间。如果不在则直接返回 False。在区间内,则继续递归检测左右子树是否满足,都满足才是一棵二叉搜索树。 +## 解题思路 -递归遍历左子树的时候,要将上界 max_v 改为左子树的根节点值,因为左子树上所有节点的值均小于根节点的值。同理,遍历右子树的时候,要将下界 min_v 改为右子树的根节点值,因为右子树上所有节点的值均大于根节点。 +### 思路 1:递归遍历 -## 代码 +根据题意进行递归遍历即可。前序、中序、后序遍历都可以。 + +1. 以前序遍历为例,递归函数为:`preorderTraversal(root, min_v, max_v)`。 +2. 前序遍历时,先判断根节点的值是否在 `(min_v, max_v)` 之间。 + 1. 如果不在则直接返回 `False`。 + 2. 如果在区间内,则继续递归检测左右子树是否满足,都满足才是一棵二叉搜索树。 +3. 当递归遍历左子树的时候,要将上界 `max_v` 改为左子树的根节点值,因为左子树上所有节点的值均小于根节点的值。 +4. 当递归遍历右子树的时候,要将下界 `min_v` 改为右子树的根节点值,因为右子树上所有节点的值均大于根节点。 + +### 思路 1:代码 ```Python class Solution: @@ -38,3 +63,7 @@ class Solution: return preorderTraversal(root, float('-inf'), float('inf')) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是二叉树的节点数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0108. \345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\346\215\242\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" "b/Solutions/0108. \345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\346\215\242\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" index 4d85b499..7fb17ead 100644 --- "a/Solutions/0108. \345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\346\215\242\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" +++ "b/Solutions/0108. \345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\346\215\242\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" @@ -5,24 +5,59 @@ ## 题目大意 -给定一个升序的有序数组 nums,将其转换为一棵高度平衡的二叉搜索树。 +**描述**:给定一个升序的有序数组 `nums`。 + +**要求**:将其转换为一棵高度平衡的二叉搜索树。 + +**说明**: + +- $1 \le nums.length \le 10^4$。 +- $-10^4 \le nums[i] \le 10^4$。 +- `nums` 按严格递增顺序排列。 + +**示例**: + +![img](https://assets.leetcode.com/uploads/2021/02/18/btree1.jpg) + +```Python +输入:nums = [-10,-3,0,5,9] +输出:[0,-3,9,-10,null,5] +解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案 +``` + +![img](https://assets.leetcode.com/uploads/2021/02/18/btree.jpg) + +```Python +输入:nums = [1,3] +输出:[3,1] +解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。 +``` ## 解题思路 -直观上,如果把数组的中间元素当做根,那么数组左侧元素都小于根节点,右侧元素都大于根节点,且左右两侧元素个数相同,或最多相差 1 个。那么构建的树高度差也不会超过 1。所以猜想出:如果左右子树约平均,树就越平衡。这样我们就可以每次取中间元素作为当前的根节点,两侧的元素作为左右子树递归建树,左侧区间 [L, mid-1] 作为左子树,右侧区间 [mid+1, R] 作为右子树。 +### 思路 1:递归遍历 -## 代码 +直观上,如果把数组的中间元素当做根,那么数组左侧元素都小于根节点,右侧元素都大于根节点,且左右两侧元素个数相同,或最多相差 $1$ 个。那么构建的树高度差也不会超过 $1$。 + +所以猜想出:如果左右子树越平均,树就越平衡。这样我们就可以每次取中间元素作为当前的根节点,两侧的元素作为左右子树递归建树,左侧区间 $[L, mid - 1]$ 作为左子树,右侧区间 $[mid + 1, R]$ 作为右子树。 + +### 思路 1:代码 ```Python class Solution: - def sortedArrayToBST(self, nums: List[int]) -> TreeNode: - n = len(nums) - if n == 0: - return None - mid = n // 2 - root = TreeNode(nums[mid]) - root.left = Solution.sortedArrayToBST(self, nums[:mid]) - root.right = Solution.sortedArrayToBST(self, nums[mid+1:]) - return root + def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: + def build(left, right): + if left > right: + return + mid = left + (right - left) // 2 + root = TreeNode(nums[mid]) + root.left = build(left, mid - 1) + root.right = build(mid + 1, right) + return root + return build(0, len(nums) - 1) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是数组的长度。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0128. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227.md" "b/Solutions/0128. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227.md" index a4cf4d72..fb347ec3 100644 --- "a/Solutions/0128. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227.md" +++ "b/Solutions/0128. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227.md" @@ -5,22 +5,44 @@ ## 题目大意 -给定一个未排序的整数数组 `nums`。 +**描述**:给定一个未排序的整数数组 `nums`。 -要求:找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。并且要用时间复杂度为 $O(n)$ 的算法解决此问题。 +**要求**:找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。并且要用时间复杂度为 $O(n)$ 的算法解决此问题。 + +**说明**: + +- $0 \le nums.length \le 10^5$。 +- $-10^9 \le nums[i] \le 10^9$。 + +**示例**: + +```Python +输入:nums = [100,4,200,1,3,2] +输出:4 +解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 + + +输入:nums = [0,3,7,2,5,8,4,6,0,1] +输出:9 +``` ## 解题思路 -暴力做法有两种思路。第 1 种思路是先排序再依次判断,这种做法时间复杂度最少是 $O(n \log n)$。第 2 种思路是枚举数组中的每个数 `num`,考虑以其为起点,不断尝试匹配 `num + 1`、`num + 2`、`...` 是否存在,最长匹配次数为 `len(nums)`。这样下来时间复杂度为 $O(n^2)$。但是可以使用集合或哈希表优化这个步骤。 +暴力做法有两种思路。 + +- 第 1 种思路是先排序再依次判断,这种做法时间复杂度最少是 $O(n \log_2 n)$。 +- 第 2 种思路是枚举数组中的每个数 `num`,考虑以其为起点,不断尝试匹配 `num + 1`、`num + 2`、`...` 是否存在,最长匹配次数为 `len(nums)`。这样下来时间复杂度为 $O(n^2)$。 + +我们可以使用哈希表优化这个过程。 -- 先将数组存储到集合中进行去重,然后使用 `curr_streak` 维护当前连续序列长度,使用 `ans` 维护最长连续序列长度。 -- 遍历集合中的元素,对每个元素进行判断,如果该元素不是序列的开始(即 `num - 1` 在集合中),则跳过。 -- 如果 `num - 1` 不在集合中,说明 `num` 是序列的开始,判断 `num + 1` 、`nums + 2`、`...` 是否在哈希表中,并不断更新当前连续序列长度 `curr_streak`。并在遍历结束之后更新最长序列的长度。 -- 最后输出最长序列长度。 +### 思路 1:哈希表 -将数组存储到集合中进行去重的操作的时间复杂度是 $O(n)$。查询每个数是否在集合中的时间复杂度是 $O(1)$ ,并且跳过了所有不是起点的元素。更新当前连续序列长度 `curr_streak` 的时间复杂度是 $O(n)$,所以最终的时间复杂度是 $O(n)$。符合题意要求。 +1. 先将数组存储到集合中进行去重,然后使用 `curr_streak` 维护当前连续序列长度,使用 `ans` 维护最长连续序列长度。 +2. 遍历集合中的元素,对每个元素进行判断,如果该元素不是序列的开始(即 `num - 1` 在集合中),则跳过。 +3. 如果 `num - 1` 不在集合中,说明 `num` 是序列的开始,判断 `num + 1` 、`nums + 2`、`...` 是否在哈希表中,并不断更新当前连续序列长度 `curr_streak`。并在遍历结束之后更新最长序列的长度。 +4. 最后输出最长序列长度。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -40,3 +62,11 @@ class Solution: return ans ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。将数组存储到集合中进行去重的操作的时间复杂度是 $O(n)$。查询每个数是否在集合中的时间复杂度是 $O(1)$ ,并且跳过了所有不是起点的元素。更新当前连续序列长度 `curr_streak` 的时间复杂度是 $O(n)$,所以最终的时间复杂度是 $O(n)$。 +- **空间复杂度**:$O(n)$。 + +## 参考资料 + +- 【题解】[128. 最长连续序列 - 力扣(Leetcode)](https://leetcode.cn/problems/longest-consecutive-sequence/solutions/1176496/xiao-bai-lang-ha-xi-ji-he-ha-xi-biao-don-j5a2/) diff --git "a/Solutions/0235. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.md" "b/Solutions/0235. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.md" index 3901e448..c1b1a5f5 100644 --- "a/Solutions/0235. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.md" +++ "b/Solutions/0235. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.md" @@ -5,23 +5,46 @@ ## 题目大意 -给定一个二叉搜索树,找到该树中两个指定节点的最近公共祖先。 +**描述**:给定一个二叉搜索树的根节点 `root`,以及两个指定节点 `p` 和 `q`。 -- 祖先:若节点 p 在节点 node 的左子树或右子树中,或者 p = node,则称 node 是 p 的祖先。 -- 最近公共祖先:对于树的两个节点 p、q,最近公共祖先表示为一个节点 lca_node,满足 lca_node 是 p、q 的祖先且 lca_node 的深度尽可能大(一个节点也可以是自己的祖先) +**要求**:找到该树中两个指定节点的最近公共祖先。 + +**说明**: + +- **祖先**:若节点 `p` 在节点 `node` 的左子树或右子树中,或者 `p == node`,则称 `node` 是 `p` 的祖先。 +- **最近公共祖先**:对于树的两个节点 `p`、`q`,最近公共祖先表示为一个节点 `lca_node`,满足 `lca_node` 是 `p`、`q` 的祖先且 `lca_node` 的深度尽可能大(一个节点也可以是自己的祖先)。 +- 所有节点的值都是唯一的。 +- `p`、`q` 为不同节点且均存在于给定的二叉搜索树中。 + +**示例**: + +![img](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/14/binarysearchtree_improved.png) + +```Python +输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 +输出: 6 +解释: 节点 2 和节点 8 的最近公共祖先是 6。 + + +输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 +输出: 2 +解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 +``` ## 解题思路 -对于节点 p、节点 q,最近公共祖先就是从根节点分别到它们路径上的分岔点,也是路径中最后一个相同的节点,现在我们的问题就是求这个分岔点。 +### 思路 1:递归遍历 -使用递归遍历查找最近公共祖先。 +对于节点 `p`、节点 `q`,最近公共祖先就是从根节点分别到它们路径上的分岔点,也是路径中最后一个相同的节点,现在我们的问题就是求这个分岔点。 -- 从根节点开始遍历; - - 如果当前节点的值大于 p、q 的值,说明 p 和 q 应该在当前节点的左子树,因此将当前节点移动到它的左子节点,继续遍历; - - 如果当前节点的值小于 p、q 的值,说明 p 和 q 应该在当前节点的右子树,因此将当前节点移动到它的右子节点,继续遍历; - - 如果当前节点不满足上面两种情况,则说明 p 和 q 分别在当前节点的左右子树上,则当前节点就是分岔点,直接返回该节点即可。 +我们可以使用递归遍历查找二叉搜索树的最近公共祖先,具体方法如下。 -## 代码 +1. 从根节点 `root` 开始遍历。 +2. 如果当前节点的值大于 `p`、`q` 的值,说明 `p` 和 `q` 应该在当前节点的左子树,因此将当前节点移动到它的左子节点,继续遍历; +3. 如果当前节点的值小于 `p`、`q` 的值,说明 `p` 和 `q` 应该在当前节点的右子树,因此将当前节点移动到它的右子节点,继续遍历; +4. 如果当前节点不满足上面两种情况,则说明 `p` 和 `q` 分别在当前节点的左右子树上,则当前节点就是分岔点,直接返回该节点即可。 + +### 思路 1:代码 ```Python class Solution: @@ -37,3 +60,7 @@ class Solution: return ancestor ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是二叉搜索树的节点个数。 +- **空间复杂度**:$O(1)$。 \ No newline at end of file diff --git "a/Solutions/0450. \345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271.md" "b/Solutions/0450. \345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271.md" index bf302dc7..f4363b46 100644 --- "a/Solutions/0450. \345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271.md" +++ "b/Solutions/0450. \345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271.md" @@ -5,47 +5,51 @@ ## 题目大意 -给定一个二叉搜索树的根节点 root,以及一个值 key。要求从二叉搜索树中删除 key 对应的节点。并保证删除后的树仍是二叉搜索树。要求算法时间复杂度为 0(h),h 为树的高度。返回二叉搜索树的根节点。 +**描述**:给定一个二叉搜索树的根节点 `root`,以及一个值 `key`。 -## 解题思路 +**要求**:从二叉搜索树中删除 key 对应的节点。并保证删除后的树仍是二叉搜索树。要求算法时间复杂度为 $0(h)$,$h$ 为树的高度。最后返回二叉搜索树的根节点。 -删除分两个步骤:查找和删除。查找通过递归查找,删除的话需要考虑情况。 +**说明**: -递归,遍历搜索二叉树。对于当前节点: +- 节点数的范围 $[0, 10^4]$。 +- $-10^5 \le Node.val \le 10^5$。 +- 节点值唯一。 +- `root` 是合法的二叉搜索树。 +- $-10^5 \le key \le 10^5$。 -- 如果节点为空,返回当前节点。 -- 如果当前节点值大于 key,则去左子树中搜索并删除,此时 root.left 也要跟着递归更新。 -- 如果当前节点值小于 key,则去右子树中搜索并删除,此时 root.right 也要跟着递归更新。 -- 如果当前节点值等于 key,则该节点就是待删除节点。 - - 如果当前节点的左子树为空,则删除该节点之后,则右子树代替当前节点位置,返回右子树。 - - 如果当前节点的右子树为空,则删除该节点之后,则左子树代替当前节点位置,返回左子树。 - - 如果当前节点的左右子树都有,则将左子树转移到右子树最左侧的叶子节点位置上,然后右子树代替当前节点位置。 +**示例**: -第三种情况如下所示: +![img](https://assets.leetcode.com/uploads/2020/09/04/del_node_1.jpg) -``` -删除 4 之前: - 4 - / \ - 2 6 - / \ / \ -1 3 5 7 +```Python +输入:root = [5,3,6,2,4,null,7], key = 3 +输出:[5,4,6,2,null,null,7] +解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。 +一个正确的答案是 [5,4,6,2,null,null,7], 如上图所示。 +另一个正确答案是 [5,2,6,null,4,null,7]。 + + +输入: root = [5,3,6,2,4,null,7], key = 0 +输出: [5,3,6,2,4,null,7] +解释: 二叉树不包含值为 0 的节点 ``` +## 解题思路 +### 思路 1:递归 -``` -删除 4 之后: - 6 - / \ - 5 7 - / - 2 - / \ -1 3 -``` +删除分两个步骤:查找和删除。查找通过递归查找,删除的话需要考虑情况。 -## 代码 +1. 从根节点 `root` 开始,递归遍历搜索二叉树。 + 1. 如果当前节点节点为空,返回当前节点。 + 2. 如果当前节点值大于 `key`,则去左子树中搜索并删除,此时 `root.left` 也要跟着递归更新,递归完成后返回当前节点。 + 3. 如果当前节点值小于 `key`,则去右子树中搜索并删除,此时 `root.right` 也要跟着递归更新,递归完成后返回当前节点。 + 4. 如果当前节点值等于 `key`,则该节点就是待删除节点。 + 1. 如果当前节点的左子树为空,则删除该节点之后,则右子树代替当前节点位置,返回右子树。 + 2. 如果当前节点的右子树为空,则删除该节点之后,则左子树代替当前节点位置,返回左子树。 + 3. 如果当前节点的左右子树都有,则将左子树转移到右子树最左侧的叶子节点位置上,然后右子树代替当前节点位置。返回右子树。 + +### 思路 1:代码 ```Python class Solution: @@ -71,3 +75,8 @@ class Solution: curr.left = root.left return root.right ``` + +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是二叉搜索树的节点数。 +- **空间复杂度**:$O(n)$。 diff --git "a/Solutions/0547. \347\234\201\344\273\275\346\225\260\351\207\217.md" "b/Solutions/0547. \347\234\201\344\273\275\346\225\260\351\207\217.md" index 03d4087a..590d1723 100644 --- "a/Solutions/0547. \347\234\201\344\273\275\346\225\260\351\207\217.md" +++ "b/Solutions/0547. \347\234\201\344\273\275\346\225\260\351\207\217.md" @@ -24,8 +24,6 @@ **示例**: -- 如图所示: - ![](https://assets.leetcode.com/uploads/2020/12/24/graph1.jpg) ```Python @@ -33,15 +31,21 @@ 输出:2 ``` +![img](https://assets.leetcode.com/uploads/2020/12/24/graph2.jpg) + +```Python +输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]] +输出:3 +``` + ## 解题思路 ### 思路 1:并查集 -具体做法如下: -- 遍历矩阵 `isConnected`。如果 `isConnected[i][j] = 1`,将 `i` 节点和 `j` 节点相连。 -- 然后判断每个城市节点的根节点,然后统计不重复的根节点有多少个,即为「省份」的数量。 +1. 遍历矩阵 `isConnected`。如果 `isConnected[i][j] == 1`,将 `i` 节点和 `j` 节点相连。 +2. 然后判断每个城市节点的根节点,然后统计不重复的根节点有多少个,即为「省份」的数量。 -### 思路 1:并查集代码 +### 思路 1:代码 ```Python class UnionFind: @@ -78,4 +82,9 @@ class Solution: for i in range(size): res.add(union_find.find(i)) return len(res) -``` \ No newline at end of file +``` + +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n^2 \times \alpha(n))$。其中 $n$ 是城市的数量,$\alpha$ 是反 `Ackerman` 函数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0684. \345\206\227\344\275\231\350\277\236\346\216\245.md" "b/Solutions/0684. \345\206\227\344\275\231\350\277\236\346\216\245.md" index 2ce21ad1..52729f86 100644 --- "a/Solutions/0684. \345\206\227\344\275\231\350\277\236\346\216\245.md" +++ "b/Solutions/0684. \345\206\227\344\275\231\350\277\236\346\216\245.md" @@ -5,17 +5,49 @@ ## 题目大意 -一个 `n` 个节点的树(节点值为 `1~n`)添加一条边后就形成了图,添加的这条边不属于树中已经存在的边。图的信息记录存储与长度为 `n` 的二维数组 `edges`,`edges[i] = [ai, bi]` 表示图中在 `ai` 和 `bi` 之间存在一条边。 +**描述**:一个 `n` 个节点的树(节点值为 `1~n`)添加一条边后就形成了图,添加的这条边不属于树中已经存在的边。图的信息记录存储与长度为 `n` 的二维数组 `edges`,`edges[i] = [ai, bi]` 表示图中在 `ai` 和 `bi` 之间存在一条边。 -现在给定代表边信息的二维数组 `edges`,要求找到一条可以山区的边,使得删除后的剩余部分是一个有着 `n` 个节点的树。如果有多个答案,则返回数组 `edges` 中最后出现的边。 +现在给定代表边信息的二维数组 `edges`。 + +**要求**:找到一条可以山区的边,使得删除后的剩余部分是一个有着 `n` 个节点的树。如果有多个答案,则返回数组 `edges` 中最后出现的边。 + +**说明**: + +- $n == edges.length$。 +- $3 \le n \le 1000$。 +- $edges[i].length == 2$。 +- $1 \le ai < bi \le edges.length$。 +- $ai ≠ bi$。 +- $edges$ 中无重复元素。 +- 给定的图是连通的。 + +**示例**: + +![img](https://pic.leetcode-cn.com/1626676174-hOEVUL-image.png) + +```Python +输入: edges = [[1,2], [1,3], [2,3]] +输出: [2,3] +``` + +![img](https://pic.leetcode-cn.com/1626676179-kGxcmu-image.png) + +```Python +输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]] +输出: [1,4] +``` ## 解题思路 +### 思路 1:并查集 + 树可以看做是无环的图,这道题就是要找出那条添加边之后成环的边。可以考虑用并查集来做。 -从前向后遍历每一条边,如果边的两个节点不在同一个集合,就加入到一个集合(链接到同一个根节点)。如果边的节点已经出现在同一个集合里,说明边的两个节点已经连在一起了,再加入这条边一定会出现环,则这条边就是所求答案。 +1. 从前向后遍历每一条边。 +2. 如果边的两个节点不在同一个集合,就加入到一个集合(链接到同一个根节点)。 +3. 如果边的节点已经出现在同一个集合里,说明边的两个节点已经连在一起了,再加入这条边一定会出现环,则这条边就是所求答案。 -## 代码 +### 思路 1:代码 ```Python class UnionFind: @@ -50,3 +82,7 @@ class Solution: return None ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n \times \alpha(n))$。其中 $n$ 是图中的节点个数,$\alpha$ 是反 `Ackerman` 函数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0700. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\220\234\347\264\242.md" "b/Solutions/0700. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\220\234\347\264\242.md" index 685ccd07..7ed98c4d 100644 --- "a/Solutions/0700. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\220\234\347\264\242.md" +++ "b/Solutions/0700. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\220\234\347\264\242.md" @@ -5,19 +5,44 @@ ## 题目大意 -给定一个二叉搜索树和一个值 val。要求在二叉搜索树中查找节点值等于 val 的节点,并返回该节点。 +**描述**:给定一个二叉搜索树和一个值 `val`。 -## 解题思路 +**要求**:在二叉搜索树中查找节点值等于 `val` 的节点,并返回该节点。 + +**说明**: + +- 数中节点数在 $[1, 5000]$ 范围内。 +- $1 \le Node.val \le 10^7$。 +- `root` 是二叉搜索树。 +- $1 \le val \le 10^7$。 + +**示例**: + +![img](https://assets.leetcode.com/uploads/2021/01/12/tree1.jpg) + +```Python +输入:root = [4,2,7,1,3], val = 2 +输出:[2,1,3] +``` -递归遍历。 +![img](https://assets.leetcode.com/uploads/2021/01/12/tree2.jpg) -- 如果 val 等于当前节点的值,即 val == root.val,则返回 root; -- 如果 val 小于当前节点的值 ,即 val < root.val,则递归遍历左子树,继续查找; -- 如果 val 大于当前节点的值 ,即 val > root.val,则递归遍历右子树,继续查找。 +```Python +输入:root = [4,2,7,1,3], val = 5 +输出:[] +``` -若最终也没有找到,返回空节点。 +## 解题思路 -## 代码 +### 思路 1:递归 + +1. 从根节点 `root` 开始向下递归遍历。 + 1. 如果 `val` 等于当前节点的值,即 `val == root.val`,则返回 `root`; + 2. 如果 `val` 小于当前节点的值 ,即 `val < root.val`,则递归遍历左子树,继续查找; + 3. 如果 `val` 大于当前节点的值 ,即 `val > root.val`,则递归遍历右子树,继续查找。 +2. 如果遍历到最后也没有找到,则返回空节点。 + +### 思路 1:代码 ```Python class Solution: @@ -30,3 +55,7 @@ class Solution: return self.searchBST(root.right, val) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是二叉搜索树的节点数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0701. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\217\222\345\205\245\346\223\215\344\275\234.md" "b/Solutions/0701. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\217\222\345\205\245\346\223\215\344\275\234.md" index 763bb74a..1463f6ff 100644 --- "a/Solutions/0701. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\217\222\345\205\245\346\223\215\344\275\234.md" +++ "b/Solutions/0701. \344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\217\222\345\205\245\346\223\215\344\275\234.md" @@ -5,22 +5,51 @@ ## 题目大意 -给定一个二叉搜索树,和一个值 val。将 val 插入到二叉搜索树中,返回新的二叉搜索树的根节点。 +**描述**:给定一个二叉搜索树的根节点和要插入树中的值 `val`。 + +**要求**:将 `val` 插入到二叉搜索树中,返回新的二叉搜索树的根节点。 + +**说明**: + +- 树中的节点数将在 $[0, 10^4]$ 的范围内。 +- $-10^8 \le Node.val \le 10^8$ +- 所有值 `Node.val` 是独一无二的。 +- $-10^8 \le val \le 10^8$。 +- **保证** $val$ 在原始 BST 中不存在。 + +**示例**: + +```Python +输入:root = [4,2,7,1,3], val = 5 +输出:[4,2,7,1,3,5] +解释:另一个满足题目要求可以通过的树是: + + +输入:root = [40,20,60,10,30,50,70], val = 25 +输出:[40,20,60,10,30,50,70,null,null,25] +``` ## 解题思路 -搜索二叉树的性质: +### 思路 1:递归 -- 左子树上任意节点值均小于根节点,即 root.left.val < root.val -- 右子树上任意节点值均大于根节点,即 root.left.val > root.val +已知搜索二叉树的性质: -那么根据 val 和根节点的关系,则可以确定将 val 插入到哪个子树上。 +- 左子树上任意节点值均小于根节点,即 `root.left.val < root.val`。 +- 右子树上任意节点值均大于根节点,即 `root.left.val > root.val`。 -如果插入的子树为空,则新建节点,赋值为 val。链接到该子树的父节点上。 +那么根据 `val` 和当前节点的大小关系,则可以确定将 `val` 插入到当前节点的哪个子树上。具体步骤如下: -如果插入的子树不为空,则根据 val 值和子树节点的大小关系,继续向下判断插入的子树位置。 +1. 从根节点 `root` 开始向下递归遍历。根据 `val` 值和当前子树节点 `cur` 的大小关系: + 1. 如果 `val < cur.val`,则应在当前节点的左子树继续遍历判断。 + 1. 如果左子树为空,则新建节点,赋值为 `val`。链接到该子树的父节点上。并停止遍历。 + 2. 如果左子树不为空,则继续向左子树移动。 + 2. 如果 `val >= cur.val`,则应在当前节点的右子树继续遍历判断。 + 1. 如果右子树为空,则新建节点,赋值为 `val`。链接到该子树的父节点上。并停止遍历。 + 2. 如果右子树不为空,则继续向左子树移动。 +2. 遍历完返回根节点 `root`。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -28,20 +57,24 @@ class Solution: if not root: return TreeNode(val) - curr = root - while curr: - if val < curr.val: - if not curr.left: - curr.left = TreeNode(val) + cur = root + while cur: + if val < cur.val: + if not cur.left: + cur.left = TreeNode(val) break else: - curr = curr.left + cur = cur.left else: - if not curr.right: - curr.right = TreeNode(val) + if not cur.right: + cur.right = TreeNode(val) break else: - curr = curr.right + cur = cur.right return root ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。其中 $n$ 是二叉搜索树的节点数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0765. \346\203\205\344\276\243\347\211\265\346\211\213.md" "b/Solutions/0765. \346\203\205\344\276\243\347\211\265\346\211\213.md" index d2e87a44..8b2fa860 100644 --- "a/Solutions/0765. \346\203\205\344\276\243\347\211\265\346\211\213.md" +++ "b/Solutions/0765. \346\203\205\344\276\243\347\211\265\346\211\213.md" @@ -5,15 +5,36 @@ ## 题目大意 -`n` 对情侣坐在连续排列的 `2n` 个座位上,想要牵对方的手。计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。每一次交换可以选择任意两人,让他们互换座位。 - -人和座位用 `0 ~ 2n-1` 的整数表示,情侣按顺序编号,第一对是 `(0, 1)`,第二对是 `(2, 3)`,以此类推,最后一对是 `(2n-2, 2n-1)`。 +**描述**:$n$ 对情侣坐在连续排列的 $2 \times n$ 个座位上,想要牵对方的手。人和座位用 $0 \sim 2 \times n - 1$ 的整数表示。情侣按顺序编号,第一对是 $(0, 1)$,第二对是 $(2, 3)$,以此类推,最后一对是 $(2 \times n - 2, 2 \times n - 1)$。 给定代表情侣初始座位的数组 `row`,`row[i]` 表示第 `i` 个座位上的人的编号。 +**要求**:计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。每一次交换可以选择任意两人,让他们互换座位。 + +**说明**: + +- $2 \times n == row.length$。 +- $2 \le n \le 30$。 +- $n$ 是偶数。 +- $0 \le row[i] < 2 \times n$。 +- $row$ 中所有元素均无重复。 + +**示例**: + +```Python +输入: row = [0,2,1,3] +输出: 1 +解释: 只需要交换row[1]和row[2]的位置即可。 + + +输入: row = [3,2,0,1] +输出: 0 +解释: 无需交换座位,所有的情侣都已经可以手牵手了。 +``` + ## 解题思路 -很有意思的题目,使用并查集求解。 +### 思路 1:并查集 先观察一下可以直接牵手的情侣特点: @@ -23,14 +44,12 @@ 将每对情侣的编号 `(0, 1) (2, 3) (4, 5) ...` 除以 `2` 可以得到 `(0, 0) (1, 1) (2, 2) ...`,这样相同编号就代表是一对情侣。 -按照 `2` 个一组的顺序,遍历一下所有编号。 +1. 按照 `2` 个一组的顺序,遍历一下所有编号。 + 1. 如果相邻的两人编号除以 `2` 相同,则两人是情侣,将其合并到一个集合中。 + 2. 如果相邻的两人编号不同,则将其合并到同一个集合中,而这两个人分别都有各自的对象,所以在后续遍历中两个人各自的对象和他们同组上的另一个人一定都会并到统一集合中,最终形成一个闭环。比如 `(0, 1) (1, 3) (2, 0) (3, 2)`。假设闭环对数为 `k`,最少需要交换 `k - 1` 次才能让情侣牵手。 +2. 假设 `n` 对情侣中有 `m` 个闭环,则 `至少交换次数 = (n1 - 1) + (n2 - 1) + ... + (nn - 1) = n - m`。 -- 如果相邻的两人编号除以 `2` 相同,则两人是情侣,将其合并到一个集合中。 -- 如果相邻的两人编号不同,则将其合并到同一个集合中,而这两个人分别都有各自的对象,所以在后续遍历中两个人各自的对象和他们同组上的另一个人一定都会并到统一集合中,最终形成一个闭环。比如 `(0, 1) (1, 3) (2, 0) (3, 2)`。假设闭环对数为 `k`,最少需要交换 `k - 1` 次才能让情侣牵手。 - -假设 `n` 对情侣中有 `m` 个闭环,则至少交换次数 = `(n1 - 1) + (n2 - 1) + ... + (nn - 1)` = `n - m`。 - -## 代码 +### 思路 1:代码 ```Python class UnionFind: @@ -67,3 +86,7 @@ class Solution: return n - count ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n \times \alpha(n))$。其中 $n$ 是数组 $row$ 长度,$\alpha$ 是反 `Ackerman` 函数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0947. \347\247\273\351\231\244\346\234\200\345\244\232\347\232\204\345\220\214\350\241\214\346\210\226\345\220\214\345\210\227\347\237\263\345\244\264.md" "b/Solutions/0947. \347\247\273\351\231\244\346\234\200\345\244\232\347\232\204\345\220\214\350\241\214\346\210\226\345\220\214\345\210\227\347\237\263\345\244\264.md" index bddd1e37..2de44abf 100644 --- "a/Solutions/0947. \347\247\273\351\231\244\346\234\200\345\244\232\347\232\204\345\220\214\350\241\214\346\210\226\345\220\214\345\210\227\347\237\263\345\244\264.md" +++ "b/Solutions/0947. \347\247\273\351\231\244\346\234\200\345\244\232\347\232\204\345\220\214\350\241\214\346\210\226\345\220\214\345\210\227\347\237\263\345\244\264.md" @@ -5,27 +5,69 @@ ## 题目大意 -二维平面中有 `n` 块石头,每块石头都在整数坐标点上,且每个坐标点上最多只能有一块石头。 +**描述**:二维平面中有 `n` 块石头,每块石头都在整数坐标点上,且每个坐标点上最多只能有一块石头。如果一块石头的同行或者同列上有其他石头存在,那么就可以移除这块石头。 -如果一块石头的同行或者同列上有其他石头存在,那么就可以移除这块石头。 +给你一个长度为 `n` 的数组 `stones` ,其中 `stones[i] = [xi, yi]` 表示第 `i` 块石头的位置。 -给你一个长度为 `n` 的数组 `stones` ,其中 `stones[i] = [xi, yi]` 表示第 `i` 块石头的位置,返回可以移除的石子的最大数量。 +**要求**:返回可以移除的石子的最大数量。 + +**说明**: + +- $1 \le stones.length \le 1000$。 +- $0 \le xi, yi \le 10^4$。 +- 不会有两块石头放在同一个坐标点上。 + +**示例**: + +```Python +输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]] +输出:5 +解释:一种移除 5 块石头的方法如下所示: +1. 移除石头 [2,2] ,因为它和 [2,1] 同行。 +2. 移除石头 [2,1] ,因为它和 [0,1] 同列。 +3. 移除石头 [1,2] ,因为它和 [1,0] 同行。 +4. 移除石头 [1,0] ,因为它和 [0,0] 同列。 +5. 移除石头 [0,1] ,因为它和 [0,0] 同行。 +石头 [0,0] 不能移除,因为它没有与另一块石头同行/列。 + + +输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]] +输出:3 +解释:一种移除 3 块石头的方法如下所示: +1. 移除石头 [2,2] ,因为它和 [2,0] 同行。 +2. 移除石头 [2,0] ,因为它和 [0,0] 同列。 +3. 移除石头 [0,2] ,因为它和 [0,0] 同行。 +石头 [0,0] 和 [1,1] 不能移除,因为它们没有与另一块石头同行/列。 +``` ## 解题思路 -只要横向和纵向上有石头连在一起,只保留一个石头即可。 +### 思路 1:并查集 + +题目「求最多可以移走的石头数目」也可以换一种思路:「求最少留下的石头数目」。 -可以构建一个无向图,只要两个石头同行或者同列,就将两个点相连接。 +- 如果两个石头 `A`、`B` 处于同一行或者同一列,我们就可以删除石头 `A` 或 `B`,最少留下 `1` 个石头。 +- 如果三个石头 `A`、`B`、`C`,其中 `A`、`B` 处于同一行,`B`、`C` 处于同一列,则我们可以先删除石头 `A`,再删除石头 `C`,最少留下 `1` 个石头。 +- 如果有 `n` 个石头,其中每个石头都有一个同行或者同列的石头,则我们可以将 `n - 1` 个石头都删除,最少留下 `1` 个石头。 -利用并查集,将石头的横纵坐标加入到一个集合中,这样同行、同列的石头都在一个集合中了。然后计算出图的连通分量个数。 +通过上面的分析,我们可以利用并查集,将同行、同列的石头都加入到一个集合中。这样「最少可以留下的石头」就是并查集中集合的个数。 -则答案为:可以移除石子的最大数量 = 所有石头个数 - 连通分量个数。 +则答案为:**最多可以移走的石头数目 = 所有石头个数 - 最少可以留下的石头(并查集的集合个数)**。 -因为石子坐标是二维的,在使用并查集的时候要区分横纵坐标,因为 $0 <= xi, yi <= 10^4$,可以取 `n = 10010`,将纵坐标映射到 `[n, n + 10000]` 的范围内,这样就可以得到所有节点的标号。 +因为石子坐标是二维的,在使用并查集的时候要区分横纵坐标,因为 $0 <= xi, yi <= 10^4$,可以取 $n = 10010$,将纵坐标映射到 $[n, n + 10000]$ 的范围内,这样就可以得到所有节点的标号。 最后计算集合个数,可以使用 set 集合去重,然后统计数量。 -## 代码 +整体步骤如下: + +1. 定义一个 $10010 \times 2$ 大小的并查集。 +2. 遍历每块石头的横纵坐标: + 1. 将纵坐标映射到 $[10010, 10010 + 10000]$ 的范围内。 + 2. 然后将当前石头的横纵坐标相连接(加入到并查集中)。 +3. 建立一个 set 集合,查找每块石头横坐标所在集合对应的并查集编号,将编号加入到 set 集合中。 +4. 最后,返回「所有石头个数 - 并查集集合个数」即为答案。 + +### 思路 1:代码 ```Python class UnionFind: @@ -67,3 +109,7 @@ class Solution: return size - len(stones_set) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n \times \alpha(n))$。其中 $n$ 是石子个数。$\alpha$ 是反 `Ackerman` 函数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/0990. \347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" "b/Solutions/0990. \347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" index 14f61f0b..5c820c66 100644 --- "a/Solutions/0990. \347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" +++ "b/Solutions/0990. \347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" @@ -77,4 +77,9 @@ class Solution: if union_find.is_connected(index1, index2): return False return True -``` \ No newline at end of file +``` + +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n + C \times \log C)$。其中 $n$ 是方程组 $equations$ 中的等式数量。$C$ 是字母变量的数量。本题中变量都是小写字母,即 $C \le 26$。 +- **空间复杂度**:$O(C)$。 \ No newline at end of file diff --git "a/Solutions/1202. \344\272\244\346\215\242\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\347\264\240.md" "b/Solutions/1202. \344\272\244\346\215\242\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\347\264\240.md" index c807f194..e3eaed75 100644 --- "a/Solutions/1202. \344\272\244\346\215\242\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\347\264\240.md" +++ "b/Solutions/1202. \344\272\244\346\215\242\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\347\264\240.md" @@ -5,23 +5,42 @@ ## 题目大意 -给定一个字符串 `s`,再给定一个数组 `pairs`,其中 `pairs[i] = [a, b]` 表示字符串的第 `a` 个字符可以跟第 `b` 个字符交换。 +**描述**:给定一个字符串 `s`,再给定一个数组 `pairs`,其中 `pairs[i] = [a, b]` 表示字符串的第 `a` 个字符可以跟第 `b` 个字符交换。只要满足 `pairs` 中的交换关系,可以任意多次交换字符串中的字符。 -只要满足 `pairs` 中的交换关系,可以任意多次交换字符串中的字符。 +**要求**:返回 `s` 经过若干次交换之后,可以变成的字典序最小的字符串。 -要求:返回 `s` 经过若干次交换之后,可以变成的字典序最小的字符串。 +**说明**: -## 解题思路 +- $1 \le s.length \le 10^5$。 +- $0 \le pairs.length \le 10^5$。 +- $0 \le pairs[i][0], pairs[i][1] < s.length$。 +- `s` 中只含有小写英文字母。 + +**示例**: -如果第 `a` 个字符可以跟第 `b` 个字符交换,第 `b` 个字符可以跟第 `c` 个字符交换,那么第 `a` 个字符、第 `b` 个字符、第 `c` 个字符之间就可以相互交换。 +```Python +输入:s = "dcab", pairs = [[0,3],[1,2]] +输出:"bacd" +解释: +交换 s[0] 和 s[3], s = "bcad" +交换 s[1] 和 s[2], s = "bacd" + + +输入:s = "dcab", pairs = [[0,3],[1,2],[0,2]] +输出:"abcd" +解释: +交换 s[0] 和 s[3], s = "bcad" +交换 s[0] 和 s[2], s = "acbd" +交换 s[1] 和 s[2], s = "abcd" +``` -我们使用并查集,将可以相互交换的位置放到同一个集合中。 +## 解题思路 -然后再将同一个集合中字符进行逆序排序,然后遍历所有位置,弹出每个位置对应集合中末尾的字符,将其加入到答案数组中。 +### 思路 1:并查集 -最后数组所构造的字符串即为答案。 +如果第 `a` 个字符可以跟第 `b` 个字符交换,第 `b` 个字符可以跟第 `c` 个字符交换,那么第 `a` 个字符、第 `b` 个字符、第 `c` 个字符之间就可以相互交换。我们可以把可以相互交换的「位置」都放入一个集合中。然后对每个集合中的字符进行排序。然后将其放置回在字符串中原有位置即可。 -## 代码 +### 思路 1:代码 ```Python import collections @@ -73,3 +92,7 @@ class Solution: return "".join(ans) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n \times \log_2 n + m * \alpha(n))$。其中 $n$ 是字符串的长度,$m$ 为 $pairs$ 的索引对数量,$\alpha$ 是反 `Ackerman` 函数。 +- **空间复杂度**:$O(n)$。 \ No newline at end of file