diff --git "a/Solutions/0100. 347円233円270円345円220円214円347円232円204円346円240円221円.md" "b/Solutions/0100. 347円233円270円345円220円214円347円232円204円346円240円221円.md" index 6c783c32..e4026967 100644 --- "a/Solutions/0100. 347円233円270円345円220円214円347円232円204円346円240円221円.md" +++ "b/Solutions/0100. 347円233円270円345円220円214円347円232円204円346円240円221円.md" @@ -5,18 +5,44 @@ ## 题目大意 -给定两个二叉树 p 和 q。判断这两棵树是否相同。 +**描述**:给定两个二叉树的根节点 $p$ 和 $q$。 -两棵树相同的定义: +**要求**:判断这两棵树是否相同。 -- 结构上相同; -- 节点具有相同的值 +**说明**: + +- **两棵树相同的定义**:结构上相同;节点具有相同的值。 +- 两棵树上的节点数目都在范围 $[0, 100]$ 内。 +- $-10^4 \le Node.val \le 10^4$。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2020/12/20/ex1.jpg) + +```python +输入:p = [1,2,3], q = [1,2,3] +输出:True +``` + +- 示例 2: + +![](https://assets.leetcode.com/uploads/2020/12/20/ex2.jpg) + +```python +输入:p = [1,2], q = [1,null,2] +输出:False +``` ## 解题思路 -先判断两棵树的根节点是否相同,在递归地判断左右子树是否相同。 +### 思路 1:递归 + +1. 先判断两棵树的根节点是否相同。 +2. 然后再递归地判断左右子树是否相同。 -## 代码 +### 思路 1:代码 ```python class Solution: @@ -30,3 +56,7 @@ class Solution: return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(min(m, n)),ドル其中 $m$、$n$ 分别为两棵树中的节点数量。 +- **空间复杂度**:$O(min(m, n))$。 diff --git "a/Solutions/0107. 344円272円214円345円217円211円346円240円221円347円232円204円345円261円202円345円272円217円351円201円215円345円216円206円 II.md" "b/Solutions/0107. 344円272円214円345円217円211円346円240円221円347円232円204円345円261円202円345円272円217円351円201円215円345円216円206円 II.md" index 6a0e7af9..a2d884f5 100644 --- "a/Solutions/0107. 344円272円214円345円217円211円346円240円221円347円232円204円345円261円202円345円272円217円351円201円215円345円216円206円 II.md" +++ "b/Solutions/0107. 344円272円214円345円217円211円346円240円221円347円232円204円345円261円202円345円272円217円351円201円215円345円216円206円 II.md" @@ -5,22 +5,49 @@ ## 题目大意 -给定一个二叉树,返回其「自底向上」,且按「层序遍历」得到的节点值。 +**描述**:给定一个二叉树的根节点 $root$。 + +**要求**:返回其节点值按照「自底向上」的「层序遍历」(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)。 + +**说明**: + +- 树中节点数目在范围 $[0, 2000]$ 内。 +- $-1000 \le Node.val \le 1000$。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2021/02/19/tree1.jpg) + +```python +输入:root = [3,9,20,null,null,15,7] +输出:[[15,7],[9,20],[3]] +``` + +- 示例 2: + +```python +输入:root = [1] +输出:[[1]] +``` ## 解题思路 +### 思路 1:二叉树的层次遍历 + 先得到层次遍历的节点顺序,再将其进行反转返回即可。 其中层次遍历用到了广度优先搜索,不过需要增加一些变化。普通广度优先搜索只取一个元素,变化后的广度优先搜索每次取出第 i 层上所有元素。 具体步骤如下: -- 根节点入队 -- 当队列不为空时,求出当前队列长度 $s_i$ - - 依次从队列中取出这 $s_i$ 个元素,将其左右子节点入队,然后继续迭代 -- 当队列为空时,结束 +1. 根节点入队。 +2. 当队列不为空时,求出当前队列长度 $s_i$。 +3. 依次从队列中取出这 $s_i$ 个元素,将其左右子节点入队,然后继续迭代。 +4. 当队列为空时,结束。 -## 代码 +### 思路 1:代码 ```python class Solution: @@ -44,3 +71,8 @@ class Solution: return order[::-1] ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 为树中节点个数。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0111. 344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円260円217円346円267円261円345円272円246円.md" "b/Solutions/0111. 344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円260円217円346円267円261円345円272円246円.md" index 1f31ee91..d447e723 100644 --- "a/Solutions/0111. 344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円260円217円346円267円261円345円272円246円.md" +++ "b/Solutions/0111. 344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円260円217円346円267円261円345円272円246円.md" @@ -5,17 +5,44 @@ ## 题目大意 -给定一个二叉树,找出其最小深度。 +**描述**:给定一个二叉树的根节点 $root$。 -- 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 +**要求**:找出该二叉树的最小深度。 + +**说明**: + +- **最小深度**:从根节点到最近叶子节点的最短路径上的节点数量。 +- **叶子节点**:指没有子节点的节点。 +- 树中节点数的范围在 $[0, 10^5]$ 内。 +- $-1000 \le Node.val \le 1000$。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2020/10/12/ex_depth.jpg) + +```python +输入:root = [3,9,20,null,null,15,7] +输出:2 +``` + +- 示例 2: + +```python +输入:root = [2,null,3,null,4,null,5,null,6] +输出:5 +``` ## 解题思路 +### 思路 1:深度优先搜索 + 深度优先搜索递归遍历左右子树,记录最小深度。 对于每一个非叶子节点,计算其左右子树的最小叶子节点深度,将较小的深度+1 即为当前节点的最小叶子节点深度。 -## 代码 +### 思路 1:代码 ```python class Solution: @@ -42,3 +69,8 @@ class Solution: return min_depth + 1 ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 是树中的节点数量。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0116. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円.md" "b/Solutions/0116. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円.md" index d025c511..9f675257 100644 --- "a/Solutions/0116. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円.md" +++ "b/Solutions/0116. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円.md" @@ -5,7 +5,7 @@ ## 题目大意 -给定一个完美二叉树,所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树结构如下: +**描述**:给定一个完美二叉树,所有叶子节点都在同一层,每个父节点都有两个子节点。完美二叉树结构如下: ```python struct Node { @@ -16,16 +16,44 @@ struct Node { } ``` -要求填充每个 next 指针,是的这个指针指向下一个右侧节点。如果找不到下一个右侧节点,则将 next 置为 None。 -示例: +**要求**:填充每个 `next` 指针,使得这个指针指向下一个右侧节点。如果找不到下一个右侧节点,则将 `next` 置为 `None`。 + +**说明**: + +- 初始状态下,所有 next 指针都被设置为 `None`。 +- 树中节点的数量在 $[0, 2^{12} - 1]$ 范围内。 +- $-1000 \le node.val \le 1000$。 +- 进阶: + - 只能使用常量级额外空间。 + - 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。 + + +**示例**: + +- 示例 1: ![](https://assets.leetcode.com/uploads/2019/02/14/116_sample.png) +```python +输入:root = [1,2,3,4,5,6,7] +输出:[1,#,2,3,#,4,5,6,7,#] +解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。 +``` + +- 示例 2: + +```python +输入:root = [] +输出:[] +``` + ## 解题思路 -层次遍历。在层次遍历的过程中,依次取出每一层的节点,并进行连接。然后再扩展下一层节点。 +### 思路 1:层次遍历 -## 代码 +在层次遍历的过程中,依次取出每一层的节点,并进行连接。然后再扩展下一层节点。 + +### 思路 1:代码 ```python import collections @@ -50,3 +78,8 @@ class Solution: return root ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 为树中的节点数量。 +- **空间复杂度**:$O(1)$。 + diff --git "a/Solutions/0117. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円 II.md" "b/Solutions/0117. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円 II.md" index 8adf567f..0f561581 100644 --- "a/Solutions/0117. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円 II.md" +++ "b/Solutions/0117. 345円241円253円345円205円205円346円257円217円344円270円252円350円212円202円347円202円271円347円232円204円344円270円213円344円270円200円344円270円252円345円217円263円344円276円247円350円212円202円347円202円271円346円214円207円351円222円210円 II.md" @@ -5,7 +5,7 @@ ## 题目大意 -给定一个完美二叉树,二叉树结构如下: +**描述**:给定一个二叉树。二叉树结构如下: ```python struct Node { @@ -16,14 +16,43 @@ struct Node { } ``` -要求填充每个 next 指针,是的这个指针指向下一个右侧节点。如果找不到下一个右侧节点,则将 next 置为 None。 -示例: +**要求**:填充每个 `next` 指针,使得这个指针指向下一个右侧节点。如果找不到下一个右侧节点,则将 `next` 置为 `None`。 + +**说明**: + +- 初始状态下,所有 next 指针都被设置为 `None`。 +- 树中节点的数量在 $[0, 6000]$ 范围内。 +- $-100 \le Node.val \le 100$。 +- 进阶: + - 只能使用常量级额外空间。 + - 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2019/02/15/117_sample.png) + +```python +输入:root = [1,2,3,4,5,null,7] +输出:[1,#,2,3,#,4,5,7,#] +解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。 +``` + +- 示例 2: + +```python +输入:root = [] +输出:[] +``` ## 解题思路 -层次遍历。在层次遍历的过程中,依次取出每一层的节点,并进行连接。然后再扩展下一层节点。 +### 思路 1:层次遍历 -## 代码 +在层次遍历的过程中,依次取出每一层的节点,并进行连接。然后再扩展下一层节点。 + +### 思路 1:代码 ```python import collections @@ -48,3 +77,8 @@ class Solution: return root ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 为树中的节点数量。 +- **空间复杂度**:$O(1)$。 + diff --git "a/Solutions/0173. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円350円277円255円344円273円243円345円231円250円.md" "b/Solutions/0173. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円350円277円255円344円273円243円345円231円250円.md" index 3007767c..dc3985ca 100644 --- "a/Solutions/0173. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円350円277円255円344円273円243円345円231円250円.md" +++ "b/Solutions/0173. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円350円277円255円344円273円243円345円231円250円.md" @@ -5,21 +5,46 @@ ## 题目大意 -实现一个二叉搜索树的迭代器 BSTIterator。表示一个按中序遍历二叉搜索树(BST)的迭代器: +**要求**:实现一个二叉搜索树的迭代器 BSTIterator。表示一个按中序遍历二叉搜索树(BST)的迭代器: - `def __init__(self, root: TreeNode):`:初始化 BSTIterator 类的一个对象,会给出二叉搜索树的根节点。 - `def hasNext(self) -> bool:`:如果向右指针遍历存在数字,则返回 True,否则返回 False。 - `def next(self) -> int:`:将指针向右移动,返回指针处的数字。 +**说明**: + +- 指针初始化为一个不存在于 BST 中的数字,所以对 `next()` 的首次调用将返回 BST 中的最小元素。 +- 可以假设 `next()` 调用总是有效的,也就是说,当调用 `next()` 时,BST 的中序遍历中至少存在一个下一个数字。 +- 树中节点的数目在范围 $[1, 10^5]$ 内。 +- 0ドル \le Node.val \le 10^6$。 +- 最多调用 10ドル^5$ 次 `hasNext` 和 `next` 操作。 +- 进阶:设计一个满足下述条件的解决方案,`next()` 和 `hasNext()` 操作均摊时间复杂度为 `O(1)` ,并使用 `O(h)` 内存。其中 `h` 是树的高度。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2018/12/25/bst-tree.png) + +```python +输入 +["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"] +[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []] +输出 +[null, 3, 7, true, 9, true, 15, true, 20, false] +``` + ## 解题思路 +### 思路 1:中序遍历二叉搜索树 + 中序遍历的顺序是:左、根、右。我们使用一个栈来保存节点,以便于迭代的时候取出对应节点。 - 初始的遍历当前节点的左子树,将其路径上的节点存储到栈中。 - 调用 next 方法的时候,从栈顶取出节点,因为之前已经将路径上的左子树全部存入了栈中,所以此时该节点的左子树为空,这时候取出节点右子树,再将右子树的左子树进行递归遍历,并将其路径上的节点存储到栈中。 - 调用 hasNext 的方法的时候,直接判断栈中是否有值即可。 -## 代码 +### 思路 1:代码 ```python class BSTIterator: @@ -43,3 +68,8 @@ class BSTIterator: return len(self.stack) != 0 ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 为树中节点数量。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0703. 346円225円260円346円215円256円346円265円201円344円270円255円347円232円204円347円254円254円 K 345円244円247円345円205円203円347円264円240円.md" "b/Solutions/0703. 346円225円260円346円215円256円346円265円201円344円270円255円347円232円204円347円254円254円 K 345円244円247円345円205円203円347円264円240円.md" index e41e37da..0e524c0c 100644 --- "a/Solutions/0703. 346円225円260円346円215円256円346円265円201円344円270円255円347円232円204円347円254円254円 K 345円244円247円345円205円203円347円264円240円.md" +++ "b/Solutions/0703. 346円225円260円346円215円256円346円265円201円344円270円255円347円232円204円347円254円254円 K 345円244円247円345円205円203円347円264円240円.md" @@ -5,18 +5,52 @@ ## 题目大意 -设计一个 ` KthLargest` 类,用于找到数据流中第 `k` 大元素。 +**要求**:设计一个 KthLargest 类,用于找到数据流中第 $k$ 大元素。 -- `KthLargest(int k, int[] nums)`:使用整数 k 和整数流 nums 初始化对象。 -- `int add(int val)`:将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。 +实现 KthLargest 类: + +- `KthLargest(int k, int[] nums)`:使用整数 $k$ 和整数流 $nums$ 初始化对象。 +- `int add(int val)`:将 $val$ 插入数据流 $nums$ 后,返回当前数据流中第 $k$ 大的元素。 + +**说明**: + +- 1ドル \le k \le 10^4$。 +- 0ドル \le nums.length \le 10^4$。 +- $-10^4 \le nums[i] \le 10^4$。 +- $-10^4 \le val \le 10^4$。 +- 最多调用 `add` 方法 10ドル^4$ 次。 +- 题目数据保证,在查找第 $k$ 大元素时,数组中至少有 $k$ 个元素。 + +**示例**: + +- 示例 1: + +```python +输入: +["KthLargest", "add", "add", "add", "add", "add"] +[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]] +输出: +[null, 4, 5, 5, 8, 8] + +解释: +KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]); +kthLargest.add(3); // return 4 +kthLargest.add(5); // return 5 +kthLargest.add(10); // return 5 +kthLargest.add(9); // return 8 +kthLargest.add(4); // return 8 +``` ## 解题思路 -- 建立大小为 `k` 的大顶堆,堆中元素保证不超过 k 个。 -- 每次 `add` 操作时,将新元素压入堆中,如果堆中元素超出了 `k` 个,则将堆中最小元素(堆顶)移除。 -- 此时堆中最小元素(堆顶)就是整个数据流中的第 `k` 大元素。 +### 思路 1:堆 + +1. 建立大小为 $k$ 的大顶堆,堆中元素保证不超过 $k$ 个。 +2. 每次 `add` 操作时,将新元素压入堆中,如果堆中元素超出了 $k$ 个,则将堆中最小元素(堆顶)移除。 -## 代码 +- 此时堆中最小元素(堆顶)就是整个数据流中的第 $k$ 大元素。 + +### 思路 1:代码 ```python import heapq @@ -38,3 +72,10 @@ class KthLargest: return self.min_heap[0] ``` +### 思路 1:复杂度分析 + +- **时间复杂度**: + - 初始化时间复杂度:$O(n \times \log k),ドル其中 $n$ 为 $nums$ 初始化时的元素个数。 + - 单次插入时间复杂度:$O(\log k)$。 +- **空间复杂度**:$O(k)$。 + diff --git "a/Solutions/0778. 346円260円264円344円275円215円344円270円212円345円215円207円347円232円204円346円263円263円346円261円240円344円270円255円346円270円270円346円263円263円.md" "b/Solutions/0778. 346円260円264円344円275円215円344円270円212円345円215円207円347円232円204円346円263円263円346円261円240円344円270円255円346円270円270円346円263円263円.md" index 49b242d8..6c108154 100644 --- "a/Solutions/0778. 346円260円264円344円275円215円344円270円212円345円215円207円347円232円204円346円263円263円346円261円240円344円270円255円346円270円270円346円263円263円.md" +++ "b/Solutions/0778. 346円260円264円344円275円215円344円270円212円345円215円207円347円232円204円346円263円263円346円261円240円344円270円255円346円270円270円346円263円263円.md" @@ -5,27 +5,62 @@ ## 题目大意 -给定一个 `n * n` 大小的二维数组 `grid`,每一个方格的值 `grid[i][j]` 表示为位置 `(i, j)` 的高度。 +**描述**:给定一个 $n \times n$ 大小的二维数组 $grid,ドル每一个方格的值 $grid[i][j]$ 表示为位置 $(i, j)$ 的高度。 -现在要从左上角 `(0, 0)` 位置出发,经过方格的一些点,到达右下角 `(n - 1, n - 1)` 位置上。其中所经过路径的花费为这条路径上所有位置的最大高度。 +现在要从左上角 $(0, 0)$ 位置出发,经过方格的一些点,到达右下角 $(n - 1, n - 1)$ 位置上。其中所经过路径的花费为这条路径上所有位置的最大高度。 -现在要求:计算从 `(0, 0)` 位置到 `(n - 1, n - 1)` 的最优路径的花费。 +**要求**:计算从 $(0, 0)$ 位置到 $(n - 1, n - 1)$ 的最优路径的花费。 -最优路径指的路径上最大高度最小的那条路径。 +**说明**: + +- **最优路径**:路径上最大高度最小的那条路径。 +- $n == grid.length$。 +- $n == grid[i].length$。 +- 1ドル \le n \le 50$。 +- 0ドル \le grid[i][j] < n2$。 +- $grid[i][j]$ 中每个值均无重复。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode.com/uploads/2021/06/29/swim1-grid.jpg) + +```python +输入: grid = [[0,2],[1,3]] +输出: 3 +解释: +时间为 0 时,你位于坐标方格的位置为 (0, 0)。 +此时你不能游向任意方向,因为四个相邻方向平台的高度都大于当前时间为 0 时的水位。 +等时间到达 3 时,你才可以游向平台 (1, 1). 因为此时的水位是 3,坐标方格中的平台没有比水位 3 更高的,所以你可以游向坐标方格中的任意位置。 +``` + +- 示例 2: + +![](https://assets.leetcode.com/uploads/2021/06/29/swim2-grid-1.jpg) + +```python +输入: grid = [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]] +输出: 16 +解释: 最终的路线用加粗进行了标记。 +我们必须等到时间为 16,此时才能保证平台 (0, 0) 和 (4, 4) 是连通的。 +``` ## 解题思路 +### 思路 1:并查集 + 将整个网络抽象为一个无向图,每个点与相邻的点(上下左右)之间都存在一条无向边,边的权重为两个点之间的最大高度。 -我们要找到左上角到右下角的最优路径,可以遍历所有的点,将所有的边存储到数组中,每条边的存储格式为 `[x, y, h]`,意思是编号 `x` 的点和编号为 `y` 的点之间的权重为 `h`。 +我们要找到左上角到右下角的最优路径,可以遍历所有的点,将所有的边存储到数组中,每条边的存储格式为 $[x, y, h],ドル意思是编号 $x$ 的点和编号为 $y$ 的点之间的权重为 $h$。 然后按照权重从小到大的顺序,对所有边进行排序。 -再按照权重大小遍历所有边,将其依次加入并查集中。并且每次都需要判断 `(0, 0)` 点和 `(n - 1, n - 1)` 点是否连通。 +再按照权重大小遍历所有边,将其依次加入并查集中。并且每次都需要判断 $(0, 0)$ 点和 $(n - 1, n - 1)$ 点是否连通。 如果连通,则该边的权重即为答案。 -## 代码 +### 思路 1:代码 ```python class UnionFind: @@ -83,3 +118,8 @@ class Solution: return 0 ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(m \times n \times \alpha(m \times n)),ドル其中 $\alpha$ 是反 Ackerman 函数。 +- **空间复杂度**:$O(m \times n)$。 + diff --git "a/Solutions/0803. 346円211円223円347円240円226円345円235円227円.md" "b/Solutions/0803. 346円211円223円347円240円226円345円235円227円.md" index 7435ac99..a438c2d1 100644 --- "a/Solutions/0803. 346円211円223円347円240円226円345円235円227円.md" +++ "b/Solutions/0803. 346円211円223円347円240円226円345円235円227円.md" @@ -5,41 +5,94 @@ ## 题目大意 -给定一个 `m * n` 大小的二元网格,其中 `1` 表示砖块,`0` 表示空白。砖块稳定(不会掉落)的前提是: +**描述**:给定一个 $m \times n$ 大小的二元网格,其中 1ドル$ 表示砖块,0ドル$ 表示空白。砖块稳定(不会掉落)的前提是: - 一块砖直接连接到网格的顶部。 - 或者至少有一块相邻(4 个方向之一)砖块稳定不会掉落时。 -再给定一个数组 `hits`,这是需要依次消除砖块的位置。每当消除 `hits[i] = (row_i, col_i)` 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而掉落。一旦砖块掉落,它会立即从网格中消失(即,它不会落在其他稳定的砖块上)。 +再给定一个数组 $hits,ドル这是需要依次消除砖块的位置。每当消除 $hits[i] = (row_i, col_i)$ 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而掉落。一旦砖块掉落,它会立即从网格中消失(即,它不会落在其他稳定的砖块上)。 -要求:返回一个数组 `result`,其中 `result[i]` 表示第 `i` 次消除操作对应掉落的砖块数目。 +**要求**:返回一个数组 $result,ドル其中 $result[i]$ 表示第 $i$ 次消除操作对应掉落的砖块数目。 -注意:消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。 +**说明**: + +- 消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。 +- $m == grid.length$。 +- $n == grid[i].length$。 +- 1ドル \le m, n \le 200$。 +- $grid[i][j]$ 为 0ドル$ 或 1ドル$。 +- 1ドル \le hits.length \le 4 \times 10^4$。 +- $hits[i].length == 2$。 +- 0ドル \le xi \le m - 1$。 +- 0ドル \le yi \le n - 1$。 +- 所有 $(xi, yi)$ 互不相同。 + +**示例**: + +- 示例 1: + +```python +输入:grid = [[1,0,0,0],[1,1,1,0]], hits = [[1,0]] +输出:[2] +解释:网格开始为: +[[1,0,0,0], + [1,1,1,0]] +消除 (1,0) 处加粗的砖块,得到网格: +[[1,0,0,0] + [0,1,1,0]] +两个加粗的砖不再稳定,因为它们不再与顶部相连,也不再与另一个稳定的砖相邻,因此它们将掉落。得到网格: +[[1,0,0,0], + [0,0,0,0]] +因此,结果为 [2]。 +``` + +- 示例 2: + +```python +输入:grid = [[1,0,0,0],[1,1,0,0]], hits = [[1,1],[1,0]] +输出:[0,0] +解释:网格开始为: +[[1,0,0,0], + [1,1,0,0]] +消除 (1,1) 处加粗的砖块,得到网格: +[[1,0,0,0], + [1,0,0,0]] +剩下的砖都很稳定,所以不会掉落。网格保持不变: +[[1,0,0,0], + [1,0,0,0]] +接下来消除 (1,0) 处加粗的砖块,得到网格: +[[1,0,0,0], + [0,0,0,0]] +剩下的砖块仍然是稳定的,所以不会有砖块掉落。 +因此,结果为 [0,0]。 +``` ## 解题思路 +### 思路 1:并查集 + 一个很直观的想法: - 将所有砖块放入一个集合中。 -- 根据 `hits` 数组的顺序,每敲掉一块砖。则将这块砖与相邻(4 个方向)的砖块断开集合。 +- 根据 $hits$ 数组的顺序,每敲掉一块砖。则将这块砖与相邻(4 个方向)的砖块断开集合。 - 然后判断哪些砖块会掉落,从集合中删除会掉落的砖块,并统计掉落砖块的数量。 - - `掉落砖块的数目 = 击碎砖块之前与屋顶相连的砖块数目 - 击碎砖块之后与屋顶相连的砖块数目 - 1` 。 + - **掉落砖块的数目 = 击碎砖块之前与屋顶相连的砖块数目 - 击碎砖块之后与屋顶相连的砖块数目 - 1**。 涉及集合问题,很容易想到用并查集来做。但是并查集主要用于合并查找集合,不适合断开集合。我们可以反向思考问题: -- 先将 `hits` 中的所有位置上的砖块敲掉。 +- 先将 $hits$ 中的所有位置上的砖块敲掉。 - 将剩下的砖块建立并查集。 -- 逆序填回被敲掉的砖块,并与相邻(4 个方向)的砖块合并。这样问题就变为了 `补上砖块会新增多少个砖块粘到屋顶`。 +- 逆序填回被敲掉的砖块,并与相邻(4 个方向)的砖块合并。这样问题就变为了 **补上砖块会新增多少个砖块粘到屋顶**。 整个算法步骤具体如下: -- 先将二维数组 `grid` 复制一份到二维数组 `copy_gird` 上。这是因为遍历 `hits` 元素时需要判断原网格是空白还是被打碎的砖块。 -- 在 `copy_grid` 中将 `hits` 中打碎的砖块赋值为 `0`。 -- 建立并查集,将房顶上的砖块合并到一个集合中。 -- 逆序遍历 `hits`,将 `hits` 中的砖块补到 `copy_grid` 中,并计算每一步中有多少个砖块粘到屋顶上(与屋顶砖块在一个集合中),并存入答案数组对应位置。 -- 最后输出答案数组。 +1. 先将二维数组 $grid$ 复制一份到二维数组 $copy\underline{}gird$ 上。这是因为遍历 $hits$ 元素时需要判断原网格是空白还是被打碎的砖块。 +2. 在 $copy\underline{}grid$ 中将 $hits$ 中打碎的砖块赋值为 0ドル$。 +3. 建立并查集,将房顶上的砖块合并到一个集合中。 +4. 逆序遍历 $hits,ドル将 $hits$ 中的砖块补到 $copy\underline{}grid$ 中,并计算每一步中有多少个砖块粘到屋顶上(与屋顶砖块在一个集合中),并存入答案数组对应位置。 +5. 最后输出答案数组。 -## 代码 +### 思路 1:代码 ```python class UnionFind: @@ -119,3 +172,8 @@ class Solution: return res ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(m \times n \times \alpha(m \times n)),ドル其中 $\alpha$ 是反 Ackerman 函数。 +- **空间复杂度**:$O(m \times n)$。 + 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 c101339d..c4d82edf 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,9 +5,9 @@ ## 题目大意 -**描述**:二维平面中有 `n` 块石头,每块石头都在整数坐标点上,且每个坐标点上最多只能有一块石头。如果一块石头的同行或者同列上有其他石头存在,那么就可以移除这块石头。 +**描述**:二维平面中有 $n$ 块石头,每块石头都在整数坐标点上,且每个坐标点上最多只能有一块石头。如果一块石头的同行或者同列上有其他石头存在,那么就可以移除这块石头。 -给你一个长度为 `n` 的数组 `stones` ,其中 `stones[i] = [xi, yi]` 表示第 `i` 块石头的位置。 +给你一个长度为 $n$ 的数组 $stones$ ,其中 $stones[i] = [xi, yi]$ 表示第 $i$ 块石头的位置。 **要求**:返回可以移除的石子的最大数量。 @@ -51,9 +51,9 @@ 题目「求最多可以移走的石头数目」也可以换一种思路:「求最少留下的石头数目」。 -- 如果两个石头 `A`、`B` 处于同一行或者同一列,我们就可以删除石头 `A` 或 `B`,最少留下 `1` 个石头。 -- 如果三个石头 `A`、`B`、`C`,其中 `A`、`B` 处于同一行,`B`、`C` 处于同一列,则我们可以先删除石头 `A`,再删除石头 `C`,最少留下 `1` 个石头。 -- 如果有 `n` 个石头,其中每个石头都有一个同行或者同列的石头,则我们可以将 `n - 1` 个石头都删除,最少留下 `1` 个石头。 +- 如果两个石头 $A$、$B$ 处于同一行或者同一列,我们就可以删除石头 $A$ 或 $B,ドル最少留下 1ドル$ 个石头。 +- 如果三个石头 $A$、$B$、$C,ドル其中 $A$、$B$ 处于同一行,$B$、$C$ 处于同一列,则我们可以先删除石头 $A,ドル再删除石头 $C,ドル最少留下 1ドル$ 个石头。 +- 如果有 $n$ 个石头,其中每个石头都有一个同行或者同列的石头,则我们可以将 $n - 1$ 个石头都删除,最少留下 1ドル$ 个石头。 通过上面的分析,我们可以利用并查集,将同行、同列的石头都加入到一个集合中。这样「最少可以留下的石头」就是并查集中集合的个数。 @@ -116,5 +116,5 @@ class Solution: ### 思路 1:复杂度分析 -- **时间复杂度**:$O(n \times \alpha(n))$。其中 $n$ 是石子个数。$\alpha$ 是反 `Ackerman` 函数。 +- **时间复杂度**:$O(n \times \alpha(n))$。其中 $n$ 是石子个数。$\alpha$ 是反 Ackerman 函数。 - **空间复杂度**:$O(n)$。 \ No newline at end of file diff --git "a/Solutions/1631. 346円234円200円345円260円217円344円275円223円345円212円233円346円266円210円350円200円227円350円267円257円345円276円204円.md" "b/Solutions/1631. 346円234円200円345円260円217円344円275円223円345円212円233円346円266円210円350円200円227円350円267円257円345円276円204円.md" index 3fb02a0b..ce8b4d54 100644 --- "a/Solutions/1631. 346円234円200円345円260円217円344円275円223円345円212円233円346円266円210円350円200円227円350円267円257円345円276円204円.md" +++ "b/Solutions/1631. 346円234円200円345円260円217円344円275円223円345円212円233円346円266円210円350円200円227円350円267円257円345円276円204円.md" @@ -5,27 +5,58 @@ ## 题目大意 -给定一个 `rows * cols` 大小的二维数组 `heights`,其中 `heights[i][j]` 表示为位置 `(i, j)` 的高度。 +**描述**:给定一个 $rows \times cols$ 大小的二维数组 $heights,ドル其中 $heights[i][j]$ 表示为位置 $(i, j)$ 的高度。 -现在要从左上角 `(0, 0)` 位置出发,经过方格的一些点,到达右下角 `(n - 1, n - 1)` 位置上。其中所经过路径的花费为「这条路径上所有相邻位置的最大高度差绝对值」。 +现在要从左上角 $(0, 0)$ 位置出发,经过方格的一些点,到达右下角 $(n - 1, n - 1)$ 位置上。其中所经过路径的花费为「这条路径上所有相邻位置的最大高度差绝对值」。 -现在要求:计算从 `(0, 0)` 位置到 `(n - 1, n - 1)` 的最优路径的花费。 +**要求**:计算从 $(0, 0)$ 位置到 $(n - 1, n - 1)$ 的最优路径的花费。 -最优路径指的路径上「所有相邻位置最大高度差绝对值」最小的那条路径。 +**说明**: + +- **最优路径**:路径上「所有相邻位置最大高度差绝对值」最小的那条路径。 +- $rows == heights.length$。 +- $columns == heights[i].length$。 +- 1ドル \le rows, columns \le 100$。 +- 1ドル \le heights[i][j] \le 10^6$。 + +**示例**: + +- 示例 1: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/10/25/ex1.png) + +```python +输入:heights = [[1,2,2],[3,8,2],[5,3,5]] +输出:2 +解释:路径 [1,3,5,3,5] 连续格子的差值绝对值最大为 2 。 +这条路径比路径 [1,2,2,2,5] 更优,因为另一条路径差值最大值为 3。 +``` + +- 示例 2: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/10/25/ex2.png) + +```python +输入:heights = [[1,2,3],[3,8,4],[5,3,5]] +输出:1 +解释:路径 [1,2,3,4,5] 的相邻格子差值绝对值最大为 1 ,比路径 [1,3,5,3,5] 更优。 +``` ## 解题思路 +### 思路 1:并查集 + 将整个网络抽象为一个无向图,每个点与相邻的点(上下左右)之间都存在一条无向边,边的权重为两个点之间的高度差绝对值。 -我们要找到左上角到右下角的最优路径,可以遍历所有的点,将所有的边存储到数组中,每条边的存储格式为 `[x, y, h]`,意思是编号 `x` 的点和编号为 `y` 的点之间的权重为 `h`。 +我们要找到左上角到右下角的最优路径,可以遍历所有的点,将所有的边存储到数组中,每条边的存储格式为 $[x, y, h],ドル意思是编号 $x$ 的点和编号为 $y$ 的点之间的权重为 $h$。 然后按照权重从小到大的顺序,对所有边进行排序。 -再按照权重大小遍历所有边,将其依次加入并查集中。并且每次都需要判断 `(0, 0)` 点和 `(n - 1, n - 1)` 点是否连通。 +再按照权重大小遍历所有边,将其依次加入并查集中。并且每次都需要判断 $(0, 0)$ 点和 $(n - 1, n - 1)$ 点是否连通。 如果连通,则该边的权重即为答案。 -## 代码 +### 思路 1:代码 ```python class UnionFind: @@ -83,3 +114,8 @@ class Solution: return 0 ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(m \times n \times \alpha(m \times n)),ドル其中 $\alpha$ 是反 Ackerman 函数。 +- **空间复杂度**:$O(m \times n)$。 + diff --git "a/Solutions/345円211円221円346円214円207円 Offer 54. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円347円232円204円347円254円254円k345円244円247円350円212円202円347円202円271円.md" "b/Solutions/345円211円221円346円214円207円 Offer 54. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円347円232円204円347円254円254円k345円244円247円350円212円202円347円202円271円.md" index 630a97c6..3670980c 100644 --- "a/Solutions/345円211円221円346円214円207円 Offer 54. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円347円232円204円347円254円254円k345円244円247円350円212円202円347円202円271円.md" +++ "b/Solutions/345円211円221円346円214円207円 Offer 54. 344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円347円232円204円347円254円254円k345円244円247円350円212円202円347円202円271円.md" @@ -5,17 +5,55 @@ ## 题目大意 -给定一棵二叉搜索树的根节点 `root`,以及一个整数 `k`。 +**描述**:给定一棵二叉搜索树的根节点 $root,ドル以及一个整数 $k$。 -要求:找出二叉搜索树书第 `k` 大的节点。 +**要求**:找出二叉搜索树书第 $k$ 大的节点。 + +**说明**: + +- + +**示例**: + +- 示例 1: + +![](https://pic.leetcode.cn/1695101634-kzHKZW-image.png) + +```python +输入:root = [7, 3, 9, 1, 5], cnt = 2 + 7 + / \ + 3 9 + / \ + 1 5 +输出:7 +``` + +- 示例 2: + +![](https://pic.leetcode.cn/1695101636-ESZtLa-image.png) + +```python +输入: root = [10, 5, 15, 2, 7, null, 20, 1, null, 6, 8], cnt = 4 + 10 + / \ + 5 15 + / \ \ + 2 7 20 + / / \ + 1 6 8 +输出: 8 +``` ## 解题思路 +### 思路 1:遍历 + 已知中序遍历「左 -> 根 -> 右」能得到递增序列。逆中序遍历「右 -> 根 -> 左」可以得到递减序列。 -则根据「右 -> 根 -> 左」递归遍历 k 次,找到第 `k` 个节点位置,并记录答案。 +则根据「右 -> 根 -> 左」递归遍历 k 次,找到第 $k$ 个节点位置,并记录答案。 -## 代码 +### 思路 1:代码 ```python class Solution: @@ -40,3 +78,8 @@ class Solution: return self.res ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n),ドル其中 $n$ 为树中节点数量。 +- **空间复杂度**:$O(n)$。 +

AltStyle によって変換されたページ (->オリジナル) /