mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-11 15:06:07 +00:00
build
This commit is contained in:
@@ -50,87 +50,64 @@ In the implementation code, we declare a recursive function `dfs()` to solve the
|
||||
|
||||
```python title="binary_search_recur.py"
|
||||
def dfs(nums: list[int], target: int, i: int, j: int) -> int:
|
||||
"""二分查找:问题 f(i, j)"""
|
||||
# 若区间为空,代表无目标元素,则返回 -1
|
||||
"""Binary search: problem f(i, j)"""
|
||||
# If the interval is empty, indicating no target element, return -1
|
||||
if i > j:
|
||||
return -1
|
||||
# 计算中点索引 m
|
||||
# Calculate midpoint index m
|
||||
m = (i + j) // 2
|
||||
if nums[m] < target:
|
||||
# 递归子问题 f(m+1, j)
|
||||
# Recursive subproblem f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j)
|
||||
elif nums[m] > target:
|
||||
# 递归子问题 f(i, m-1)
|
||||
# Recursive subproblem f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1)
|
||||
else:
|
||||
# 找到目标元素,返回其索引
|
||||
# Found the target element, thus return its index
|
||||
return m
|
||||
|
||||
def binary_search(nums: list[int], target: int) -> int:
|
||||
"""二分查找"""
|
||||
"""Binary search"""
|
||||
n = len(nums)
|
||||
# 求解问题 f(0, n-1)
|
||||
# Solve problem f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1)
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search_recur.cpp"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
int dfs(vector<int> &nums, int target, int i, int j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
int m = (i + j) / 2;
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
int binarySearch(vector<int> &nums, int target) {
|
||||
int n = nums.size();
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search_recur.java"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
/* Binary search: problem f(i, j) */
|
||||
int dfs(int[] nums, int target, int i, int j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
// If the interval is empty, indicating no target element, return -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
// Calculate midpoint index m
|
||||
int m = (i + j) / 2;
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
// Recursive subproblem f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
// Recursive subproblem f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
// Found the target element, thus return its index
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
/* 二分查找 */
|
||||
/* Binary search */
|
||||
int binarySearch(int[] nums, int target) {
|
||||
int n = nums.length;
|
||||
// 求解问题 f(0, n-1)
|
||||
// Solve problem f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
```
|
||||
@@ -138,285 +115,73 @@ In the implementation code, we declare a recursive function `dfs()` to solve the
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search_recur.cs"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
int DFS(int[] nums, int target, int i, int j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
int m = (i + j) / 2;
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return DFS(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return DFS(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{binary_search_recur}-[func]{DFS}
|
||||
|
||||
/* 二分查找 */
|
||||
int BinarySearch(int[] nums, int target) {
|
||||
int n = nums.Length;
|
||||
// 求解问题 f(0, n-1)
|
||||
return DFS(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{binary_search_recur}-[func]{BinarySearch}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search_recur.go"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
func dfs(nums []int, target, i, j int) int {
|
||||
// 如果区间为空,代表没有目标元素,则返回 -1
|
||||
if i > j {
|
||||
return -1
|
||||
}
|
||||
// 计算索引中点
|
||||
m := i + ((j - i) >> 1)
|
||||
//判断中点与目标元素大小
|
||||
if nums[m] < target {
|
||||
// 小于则递归右半数组
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m+1, j)
|
||||
} else if nums[m] > target {
|
||||
// 小于则递归左半数组
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m-1)
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
func binarySearch(nums []int, target int) int {
|
||||
n := len(nums)
|
||||
return dfs(nums, target, 0, n-1)
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_recur.swift"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
func dfs(nums: [Int], target: Int, i: Int, j: Int) -> Int {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if i > j {
|
||||
return -1
|
||||
}
|
||||
// 计算中点索引 m
|
||||
let m = (i + j) / 2
|
||||
if nums[m] < target {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums: nums, target: target, i: m + 1, j: j)
|
||||
} else if nums[m] > target {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums: nums, target: target, i: i, j: m - 1)
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
func binarySearch(nums: [Int], target: Int) -> Int {
|
||||
// 求解问题 f(0, n-1)
|
||||
dfs(nums: nums, target: target, i: nums.startIndex, j: nums.endIndex - 1)
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search_recur.js"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
function dfs(nums, target, i, j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
const m = i + ((j - i) >> 1);
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
function binarySearch(nums, target) {
|
||||
const n = nums.length;
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search_recur.ts"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
function dfs(nums: number[], target: number, i: number, j: number): number {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
const m = i + ((j - i) >> 1);
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
function binarySearch(nums: number[], target: number): number {
|
||||
const n = nums.length;
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search_recur.dart"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
int dfs(List<int> nums, int target, int i, int j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
int m = (i + j) ~/ 2;
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
int binarySearch(List<int> nums, int target) {
|
||||
int n = nums.length;
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search_recur.rs"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
fn dfs(nums: &[i32], target: i32, i: i32, j: i32) -> i32 {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if i > j {
|
||||
return -1;
|
||||
}
|
||||
let m: i32 = (i + j) / 2;
|
||||
if nums[m as usize] < target {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if nums[m as usize] > target {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
fn binary_search(nums: &[i32], target: i32) -> i32 {
|
||||
let n = nums.len() as i32;
|
||||
// 求解问题 f(0, n-1)
|
||||
dfs(nums, target, 0, n - 1)
|
||||
}
|
||||
[class]{}-[func]{binary_search}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search_recur.c"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
int dfs(int nums[], int target, int i, int j) {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1;
|
||||
}
|
||||
// 计算中点索引 m
|
||||
int m = (i + j) / 2;
|
||||
if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
return dfs(nums, target, i, m - 1);
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
int binarySearch(int nums[], int target, int numsSize) {
|
||||
int n = numsSize;
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1);
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search_recur.kt"
|
||||
/* 二分查找:问题 f(i, j) */
|
||||
fun dfs(
|
||||
nums: IntArray,
|
||||
target: Int,
|
||||
i: Int,
|
||||
j: Int
|
||||
): Int {
|
||||
// 若区间为空,代表无目标元素,则返回 -1
|
||||
if (i > j) {
|
||||
return -1
|
||||
}
|
||||
// 计算中点索引 m
|
||||
val m = (i + j) / 2
|
||||
return if (nums[m] < target) {
|
||||
// 递归子问题 f(m+1, j)
|
||||
dfs(nums, target, m + 1, j)
|
||||
} else if (nums[m] > target) {
|
||||
// 递归子问题 f(i, m-1)
|
||||
dfs(nums, target, i, m - 1)
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
m
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 二分查找 */
|
||||
fun binarySearch(nums: IntArray, target: Int): Int {
|
||||
val n = nums.size
|
||||
// 求解问题 f(0, n-1)
|
||||
return dfs(nums, target, 0, n - 1)
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
@@ -434,8 +199,3 @@ In the implementation code, we declare a recursive function `dfs()` to solve the
|
||||
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20dfs%28nums%3A%20list%5Bint%5D,%20target%3A%20int,%20i%3A%20int,%20j%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%EF%BC%9A%E9%97%AE%E9%A2%98%20f%28i,%20j%29%22%22%22%0A%20%20%20%20%23%20%E8%8B%A5%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%EF%BC%8C%E4%BB%A3%E8%A1%A8%E6%97%A0%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20i%20%3E%20j%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E8%AE%A1%E7%AE%97%E4%B8%AD%E7%82%B9%E7%B4%A2%E5%BC%95%20m%0A%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%0A%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%23%20%E9%80%92%E5%BD%92%E5%AD%90%E9%97%AE%E9%A2%98%20f%28m%2B1,%20j%29%0A%20%20%20%20%20%20%20%20return%20dfs%28nums,%20target,%20m%20%2B%201,%20j%29%0A%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%23%20%E9%80%92%E5%BD%92%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i,%20m-1%29%0A%20%20%20%20%20%20%20%20return%20dfs%28nums,%20target,%20i,%20m%20-%201%29%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%23%20%E6%89%BE%E5%88%B0%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%EF%BC%8C%E8%BF%94%E5%9B%9E%E5%85%B6%E7%B4%A2%E5%BC%95%0A%20%20%20%20%20%20%20%20return%20m%0A%0Adef%20binary_search%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%22%22%22%0A%20%20%20%20n%20%3D%20len%28nums%29%0A%20%20%20%20%23%20%E6%B1%82%E8%A7%A3%E9%97%AE%E9%A2%98%20f%280,%20n-1%29%0A%20%20%20%20return%20dfs%28nums,%20target,%200,%20n%20-%201%29%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%208,%2012,%2015,%2023,%2026,%2031,%2035%5D%0A%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%EF%BC%88%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%EF%BC%89%0A%20%20%20%20index%20%3D%20binary_search%28nums,%20target%29%0A%20%20%20%20print%28%22%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%206%20%E7%9A%84%E7%B4%A2%E5%BC%95%20%3D%20%22,%20index%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=6&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
|
||||
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=def%20dfs%28nums%3A%20list%5Bint%5D,%20target%3A%20int,%20i%3A%20int,%20j%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%EF%BC%9A%E9%97%AE%E9%A2%98%20f%28i,%20j%29%22%22%22%0A%20%20%20%20%23%20%E8%8B%A5%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%EF%BC%8C%E4%BB%A3%E8%A1%A8%E6%97%A0%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20i%20%3E%20j%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E8%AE%A1%E7%AE%97%E4%B8%AD%E7%82%B9%E7%B4%A2%E5%BC%95%20m%0A%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%0A%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%23%20%E9%80%92%E5%BD%92%E5%AD%90%E9%97%AE%E9%A2%98%20f%28m%2B1,%20j%29%0A%20%20%20%20%20%20%20%20return%20dfs%28nums,%20target,%20m%20%2B%201,%20j%29%0A%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%23%20%E9%80%92%E5%BD%92%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i,%20m-1%29%0A%20%20%20%20%20%20%20%20return%20dfs%28nums,%20target,%20i,%20m%20-%201%29%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%23%20%E6%89%BE%E5%88%B0%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%EF%BC%8C%E8%BF%94%E5%9B%9E%E5%85%B6%E7%B4%A2%E5%BC%95%0A%20%20%20%20%20%20%20%20return%20m%0A%0Adef%20binary_search%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%22%22%22%0A%20%20%20%20n%20%3D%20len%28nums%29%0A%20%20%20%20%23%20%E6%B1%82%E8%A7%A3%E9%97%AE%E9%A2%98%20f%280,%20n-1%29%0A%20%20%20%20return%20dfs%28nums,%20target,%200,%20n%20-%201%29%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%208,%2012,%2015,%2023,%2026,%2031,%2035%5D%0A%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%EF%BC%88%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%EF%BC%89%0A%20%20%20%20index%20%3D%20binary_search%28nums,%20target%29%0A%20%20%20%20print%28%22%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%206%20%E7%9A%84%E7%B4%A2%E5%BC%95%20%3D%20%22,%20index%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=6&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
@@ -81,24 +81,24 @@ To improve the efficiency of querying $m$, we use a hash table `hmap` to store t
|
||||
l: int,
|
||||
r: int,
|
||||
) -> TreeNode | None:
|
||||
"""构建二叉树:分治"""
|
||||
# 子树区间为空时终止
|
||||
"""Build binary tree: Divide and conquer"""
|
||||
# Terminate when subtree interval is empty
|
||||
if r - l < 0:
|
||||
return None
|
||||
# 初始化根节点
|
||||
# Initialize root node
|
||||
root = TreeNode(preorder[i])
|
||||
# 查询 m ,从而划分左右子树
|
||||
# Query m to divide left and right subtrees
|
||||
m = inorder_map[preorder[i]]
|
||||
# 子问题:构建左子树
|
||||
# Subproblem: build left subtree
|
||||
root.left = dfs(preorder, inorder_map, i + 1, l, m - 1)
|
||||
# 子问题:构建右子树
|
||||
# Subproblem: build right subtree
|
||||
root.right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r)
|
||||
# 返回根节点
|
||||
# Return root node
|
||||
return root
|
||||
|
||||
def build_tree(preorder: list[int], inorder: list[int]) -> TreeNode | None:
|
||||
"""构建二叉树"""
|
||||
# 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
"""Build binary tree"""
|
||||
# Initialize hash table, storing in-order elements to indices mapping
|
||||
inorder_map = {val: i for i, val in enumerate(inorder)}
|
||||
root = dfs(preorder, inorder_map, 0, 0, len(inorder) - 1)
|
||||
return root
|
||||
@@ -107,58 +107,34 @@ To improve the efficiency of querying $m$, we use a hash table `hmap` to store t
|
||||
=== "C++"
|
||||
|
||||
```cpp title="build_tree.cpp"
|
||||
/* 构建二叉树:分治 */
|
||||
TreeNode *dfs(vector<int> &preorder, unordered_map<int, int> &inorderMap, int i, int l, int r) {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0)
|
||||
return NULL;
|
||||
// 初始化根节点
|
||||
TreeNode *root = new TreeNode(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
int m = inorderMap[preorder[i]];
|
||||
// 子问题:构建左子树
|
||||
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
unordered_map<int, int> inorderMap;
|
||||
for (int i = 0; i < inorder.size(); i++) {
|
||||
inorderMap[inorder[i]] = i;
|
||||
}
|
||||
TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorder.size() - 1);
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="build_tree.java"
|
||||
/* 构建二叉树:分治 */
|
||||
/* Build binary tree: Divide and conquer */
|
||||
TreeNode dfs(int[] preorder, Map<Integer, Integer> inorderMap, int i, int l, int r) {
|
||||
// 子树区间为空时终止
|
||||
// Terminate when subtree interval is empty
|
||||
if (r - l < 0)
|
||||
return null;
|
||||
// 初始化根节点
|
||||
// Initialize root node
|
||||
TreeNode root = new TreeNode(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
// Query m to divide left and right subtrees
|
||||
int m = inorderMap.get(preorder[i]);
|
||||
// 子问题:构建左子树
|
||||
// Subproblem: build left subtree
|
||||
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
// Subproblem: build right subtree
|
||||
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
// Return root node
|
||||
return root;
|
||||
}
|
||||
|
||||
/* 构建二叉树 */
|
||||
/* Build binary tree */
|
||||
TreeNode buildTree(int[] preorder, int[] inorder) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
// Initialize hash table, storing in-order elements to indices mapping
|
||||
Map<Integer, Integer> inorderMap = new HashMap<>();
|
||||
for (int i = 0; i < inorder.length; i++) {
|
||||
inorderMap.put(inorder[i], i);
|
||||
@@ -171,315 +147,73 @@ To improve the efficiency of querying $m$, we use a hash table `hmap` to store t
|
||||
=== "C#"
|
||||
|
||||
```csharp title="build_tree.cs"
|
||||
/* 构建二叉树:分治 */
|
||||
TreeNode? DFS(int[] preorder, Dictionary<int, int> inorderMap, int i, int l, int r) {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0)
|
||||
return null;
|
||||
// 初始化根节点
|
||||
TreeNode root = new(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
int m = inorderMap[preorder[i]];
|
||||
// 子问题:构建左子树
|
||||
root.left = DFS(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root.right = DFS(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{build_tree}-[func]{DFS}
|
||||
|
||||
/* 构建二叉树 */
|
||||
TreeNode? BuildTree(int[] preorder, int[] inorder) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
Dictionary<int, int> inorderMap = [];
|
||||
for (int i = 0; i < inorder.Length; i++) {
|
||||
inorderMap.TryAdd(inorder[i], i);
|
||||
}
|
||||
TreeNode? root = DFS(preorder, inorderMap, 0, 0, inorder.Length - 1);
|
||||
return root;
|
||||
}
|
||||
[class]{build_tree}-[func]{BuildTree}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="build_tree.go"
|
||||
/* 构建二叉树:分治 */
|
||||
func dfsBuildTree(preorder []int, inorderMap map[int]int, i, l, r int) *TreeNode {
|
||||
// 子树区间为空时终止
|
||||
if r-l < 0 {
|
||||
return nil
|
||||
}
|
||||
// 初始化根节点
|
||||
root := NewTreeNode(preorder[i])
|
||||
// 查询 m ,从而划分左右子树
|
||||
m := inorderMap[preorder[i]]
|
||||
// 子问题:构建左子树
|
||||
root.Left = dfsBuildTree(preorder, inorderMap, i+1, l, m-1)
|
||||
// 子问题:构建右子树
|
||||
root.Right = dfsBuildTree(preorder, inorderMap, i+1+m-l, m+1, r)
|
||||
// 返回根节点
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{dfsBuildTree}
|
||||
|
||||
/* 构建二叉树 */
|
||||
func buildTree(preorder, inorder []int) *TreeNode {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
inorderMap := make(map[int]int, len(inorder))
|
||||
for i := 0; i < len(inorder); i++ {
|
||||
inorderMap[inorder[i]] = i
|
||||
}
|
||||
|
||||
root := dfsBuildTree(preorder, inorderMap, 0, 0, len(inorder)-1)
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="build_tree.swift"
|
||||
/* 构建二叉树:分治 */
|
||||
func dfs(preorder: [Int], inorderMap: [Int: Int], i: Int, l: Int, r: Int) -> TreeNode? {
|
||||
// 子树区间为空时终止
|
||||
if r - l < 0 {
|
||||
return nil
|
||||
}
|
||||
// 初始化根节点
|
||||
let root = TreeNode(x: preorder[i])
|
||||
// 查询 m ,从而划分左右子树
|
||||
let m = inorderMap[preorder[i]]!
|
||||
// 子问题:构建左子树
|
||||
root.left = dfs(preorder: preorder, inorderMap: inorderMap, i: i + 1, l: l, r: m - 1)
|
||||
// 子问题:构建右子树
|
||||
root.right = dfs(preorder: preorder, inorderMap: inorderMap, i: i + 1 + m - l, l: m + 1, r: r)
|
||||
// 返回根节点
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
func buildTree(preorder: [Int], inorder: [Int]) -> TreeNode? {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
let inorderMap = inorder.enumerated().reduce(into: [:]) { $0[$1.element] = $1.offset }
|
||||
return dfs(preorder: preorder, inorderMap: inorderMap, i: inorder.startIndex, l: inorder.startIndex, r: inorder.endIndex - 1)
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="build_tree.js"
|
||||
/* 构建二叉树:分治 */
|
||||
function dfs(preorder, inorderMap, i, l, r) {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0) return null;
|
||||
// 初始化根节点
|
||||
const root = new TreeNode(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
const m = inorderMap.get(preorder[i]);
|
||||
// 子问题:构建左子树
|
||||
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
function buildTree(preorder, inorder) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
let inorderMap = new Map();
|
||||
for (let i = 0; i < inorder.length; i++) {
|
||||
inorderMap.set(inorder[i], i);
|
||||
}
|
||||
const root = dfs(preorder, inorderMap, 0, 0, inorder.length - 1);
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="build_tree.ts"
|
||||
/* 构建二叉树:分治 */
|
||||
function dfs(
|
||||
preorder: number[],
|
||||
inorderMap: Map<number, number>,
|
||||
i: number,
|
||||
l: number,
|
||||
r: number
|
||||
): TreeNode | null {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0) return null;
|
||||
// 初始化根节点
|
||||
const root: TreeNode = new TreeNode(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
const m = inorderMap.get(preorder[i]);
|
||||
// 子问题:构建左子树
|
||||
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
let inorderMap = new Map<number, number>();
|
||||
for (let i = 0; i < inorder.length; i++) {
|
||||
inorderMap.set(inorder[i], i);
|
||||
}
|
||||
const root = dfs(preorder, inorderMap, 0, 0, inorder.length - 1);
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="build_tree.dart"
|
||||
/* 构建二叉树:分治 */
|
||||
TreeNode? dfs(
|
||||
List<int> preorder,
|
||||
Map<int, int> inorderMap,
|
||||
int i,
|
||||
int l,
|
||||
int r,
|
||||
) {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0) {
|
||||
return null;
|
||||
}
|
||||
// 初始化根节点
|
||||
TreeNode? root = TreeNode(preorder[i]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
int m = inorderMap[preorder[i]]!;
|
||||
// 子问题:构建左子树
|
||||
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
TreeNode? buildTree(List<int> preorder, List<int> inorder) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
Map<int, int> inorderMap = {};
|
||||
for (int i = 0; i < inorder.length; i++) {
|
||||
inorderMap[inorder[i]] = i;
|
||||
}
|
||||
TreeNode? root = dfs(preorder, inorderMap, 0, 0, inorder.length - 1);
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="build_tree.rs"
|
||||
/* 构建二叉树:分治 */
|
||||
fn dfs(
|
||||
preorder: &[i32],
|
||||
inorder_map: &HashMap<i32, i32>,
|
||||
i: i32,
|
||||
l: i32,
|
||||
r: i32,
|
||||
) -> Option<Rc<RefCell<TreeNode>>> {
|
||||
// 子树区间为空时终止
|
||||
if r - l < 0 {
|
||||
return None;
|
||||
}
|
||||
// 初始化根节点
|
||||
let root = TreeNode::new(preorder[i as usize]);
|
||||
// 查询 m ,从而划分左右子树
|
||||
let m = inorder_map.get(&preorder[i as usize]).unwrap();
|
||||
// 子问题:构建左子树
|
||||
root.borrow_mut().left = dfs(preorder, inorder_map, i + 1, l, m - 1);
|
||||
// 子问题:构建右子树
|
||||
root.borrow_mut().right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r);
|
||||
// 返回根节点
|
||||
Some(root)
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
fn build_tree(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
let mut inorder_map: HashMap<i32, i32> = HashMap::new();
|
||||
for i in 0..inorder.len() {
|
||||
inorder_map.insert(inorder[i], i as i32);
|
||||
}
|
||||
let root = dfs(preorder, &inorder_map, 0, 0, inorder.len() as i32 - 1);
|
||||
root
|
||||
}
|
||||
[class]{}-[func]{build_tree}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="build_tree.c"
|
||||
/* 构建二叉树:分治 */
|
||||
TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0)
|
||||
return NULL;
|
||||
// 初始化根节点
|
||||
TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
|
||||
root->val = preorder[i];
|
||||
root->left = NULL;
|
||||
root->right = NULL;
|
||||
// 查询 m ,从而划分左右子树
|
||||
int m = inorderMap[preorder[i]];
|
||||
// 子问题:构建左子树
|
||||
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1, size);
|
||||
// 子问题:构建右子树
|
||||
root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r, size);
|
||||
// 返回根节点
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
TreeNode *buildTree(int *preorder, int preorderSize, int *inorder, int inorderSize) {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
int *inorderMap = (int *)malloc(sizeof(int) * MAX_SIZE);
|
||||
for (int i = 0; i < inorderSize; i++) {
|
||||
inorderMap[inorder[i]] = i;
|
||||
}
|
||||
TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorderSize - 1, inorderSize);
|
||||
free(inorderMap);
|
||||
return root;
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="build_tree.kt"
|
||||
/* 构建二叉树:分治 */
|
||||
fun dfs(
|
||||
preorder: IntArray,
|
||||
inorderMap: Map<Int?, Int?>,
|
||||
i: Int,
|
||||
l: Int,
|
||||
r: Int
|
||||
): TreeNode? {
|
||||
// 子树区间为空时终止
|
||||
if (r - l < 0) return null
|
||||
// 初始化根节点
|
||||
val root = TreeNode(preorder[i])
|
||||
// 查询 m ,从而划分左右子树
|
||||
val m = inorderMap[preorder[i]]!!
|
||||
// 子问题:构建左子树
|
||||
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1)
|
||||
// 子问题:构建右子树
|
||||
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r)
|
||||
// 返回根节点
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 构建二叉树 */
|
||||
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
|
||||
// 初始化哈希表,存储 inorder 元素到索引的映射
|
||||
val inorderMap = HashMap<Int?, Int?>()
|
||||
for (i in inorder.indices) {
|
||||
inorderMap[inorder[i]] = i
|
||||
}
|
||||
val root = dfs(preorder, inorderMap, 0, 0, inorder.size - 1)
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
@@ -498,11 +232,6 @@ To improve the efficiency of querying $m$, we use a hash table `hmap` to store t
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=class%20TreeNode%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%8F%89%E6%A0%91%E8%8A%82%E7%82%B9%E7%B1%BB%22%22%22%0A%20%20%20%20def%20__init__%28self,%20val%3A%20int%20%3D%200%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%E8%8A%82%E7%82%B9%E5%80%BC%0A%20%20%20%20%20%20%20%20self.left%3A%20TreeNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%B7%A6%E5%AD%90%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%20%20%20%20%20%20%20%20self.right%3A%20TreeNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%8F%B3%E5%AD%90%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%0Adef%20dfs%28%0A%20%20%20%20preorder%3A%20list%5Bint%5D,%0A%20%20%20%20inorder_map%3A%20dict%5Bint,%20int%5D,%0A%20%20%20%20i%3A%20int,%0A%20%20%20%20l%3A%20int,%0A%20%20%20%20r%3A%20int,%0A%29%20-%3E%20TreeNode%20%7C%20None%3A%0A%20%20%20%20%22%22%22%E6%9E%84%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91%EF%BC%9A%E5%88%86%E6%B2%BB%22%22%22%0A%20%20%20%20%23%20%E5%AD%90%E6%A0%91%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E7%BB%88%E6%AD%A2%0A%20%20%20%20if%20r%20-%20l%20%3C%200%3A%0A%20%20%20%20%20%20%20%20return%20None%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E6%A0%B9%E8%8A%82%E7%82%B9%0A%20%20%20%20root%20%3D%20TreeNode%28preorder%5Bi%5D%29%0A%20%20%20%20%23%20%E6%9F%A5%E8%AF%A2%20m%20%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%88%92%E5%88%86%E5%B7%A6%E5%8F%B3%E5%AD%90%E6%A0%91%0A%20%20%20%20m%20%3D%20inorder_map%5Bpreorder%5Bi%5D%5D%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%EF%BC%9A%E6%9E%84%E5%BB%BA%E5%B7%A6%E5%AD%90%E6%A0%91%0A%20%20%20%20root.left%20%3D%20dfs%28preorder,%20inorder_map,%20i%20%2B%201,%20l,%20m%20-%201%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%EF%BC%9A%E6%9E%84%E5%BB%BA%E5%8F%B3%E5%AD%90%E6%A0%91%0A%20%20%20%20root.right%20%3D%20dfs%28preorder,%20inorder_map,%20i%20%2B%201%20%2B%20m%20-%20l,%20m%20%2B%201,%20r%29%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%A0%B9%E8%8A%82%E7%82%B9%0A%20%20%20%20return%20root%0A%0A%0Adef%20build_tree%28preorder%3A%20list%5Bint%5D,%20inorder%3A%20list%5Bint%5D%29%20-%3E%20TreeNode%20%7C%20None%3A%0A%20%20%20%20%22%22%22%E6%9E%84%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%93%88%E5%B8%8C%E8%A1%A8%EF%BC%8C%E5%AD%98%E5%82%A8%20inorder%20%E5%85%83%E7%B4%A0%E5%88%B0%E7%B4%A2%E5%BC%95%E7%9A%84%E6%98%A0%E5%B0%84%0A%20%20%20%20inorder_map%20%3D%20%7Bval%3A%20i%20for%20i,%20val%20in%20enumerate%28inorder%29%7D%0A%20%20%20%20root%20%3D%20dfs%28preorder,%20inorder_map,%200,%200,%20len%28inorder%29%20-%201%29%0A%20%20%20%20return%20root%0A%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20preorder%20%3D%20%5B3,%209,%202,%201,%207%5D%0A%20%20%20%20inorder%20%3D%20%5B9,%203,%201,%202,%207%5D%0A%20%20%20%20print%28f%22%E5%89%8D%E5%BA%8F%E9%81%8D%E5%8E%86%20%3D%20%7Bpreorder%7D%22%29%0A%20%20%20%20print%28f%22%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86%20%3D%20%7Binorder%7D%22%29%0A%20%20%20%20root%20%3D%20build_tree%28preorder,%20inorder%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=21&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
|
||||
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=class%20TreeNode%3A%0A%20%20%20%20%22%22%22%E4%BA%8C%E5%8F%89%E6%A0%91%E8%8A%82%E7%82%B9%E7%B1%BB%22%22%22%0A%20%20%20%20def%20__init__%28self,%20val%3A%20int%20%3D%200%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%E8%8A%82%E7%82%B9%E5%80%BC%0A%20%20%20%20%20%20%20%20self.left%3A%20TreeNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%B7%A6%E5%AD%90%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%20%20%20%20%20%20%20%20self.right%3A%20TreeNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%8F%B3%E5%AD%90%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%0Adef%20dfs%28%0A%20%20%20%20preorder%3A%20list%5Bint%5D,%0A%20%20%20%20inorder_map%3A%20dict%5Bint,%20int%5D,%0A%20%20%20%20i%3A%20int,%0A%20%20%20%20l%3A%20int,%0A%20%20%20%20r%3A%20int,%0A%29%20-%3E%20TreeNode%20%7C%20None%3A%0A%20%20%20%20%22%22%22%E6%9E%84%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91%EF%BC%9A%E5%88%86%E6%B2%BB%22%22%22%0A%20%20%20%20%23%20%E5%AD%90%E6%A0%91%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E7%BB%88%E6%AD%A2%0A%20%20%20%20if%20r%20-%20l%20%3C%200%3A%0A%20%20%20%20%20%20%20%20return%20None%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E6%A0%B9%E8%8A%82%E7%82%B9%0A%20%20%20%20root%20%3D%20TreeNode%28preorder%5Bi%5D%29%0A%20%20%20%20%23%20%E6%9F%A5%E8%AF%A2%20m%20%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%88%92%E5%88%86%E5%B7%A6%E5%8F%B3%E5%AD%90%E6%A0%91%0A%20%20%20%20m%20%3D%20inorder_map%5Bpreorder%5Bi%5D%5D%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%EF%BC%9A%E6%9E%84%E5%BB%BA%E5%B7%A6%E5%AD%90%E6%A0%91%0A%20%20%20%20root.left%20%3D%20dfs%28preorder,%20inorder_map,%20i%20%2B%201,%20l,%20m%20-%201%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%EF%BC%9A%E6%9E%84%E5%BB%BA%E5%8F%B3%E5%AD%90%E6%A0%91%0A%20%20%20%20root.right%20%3D%20dfs%28preorder,%20inorder_map,%20i%20%2B%201%20%2B%20m%20-%20l,%20m%20%2B%201,%20r%29%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%A0%B9%E8%8A%82%E7%82%B9%0A%20%20%20%20return%20root%0A%0A%0Adef%20build_tree%28preorder%3A%20list%5Bint%5D,%20inorder%3A%20list%5Bint%5D%29%20-%3E%20TreeNode%20%7C%20None%3A%0A%20%20%20%20%22%22%22%E6%9E%84%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%93%88%E5%B8%8C%E8%A1%A8%EF%BC%8C%E5%AD%98%E5%82%A8%20inorder%20%E5%85%83%E7%B4%A0%E5%88%B0%E7%B4%A2%E5%BC%95%E7%9A%84%E6%98%A0%E5%B0%84%0A%20%20%20%20inorder_map%20%3D%20%7Bval%3A%20i%20for%20i,%20val%20in%20enumerate%28inorder%29%7D%0A%20%20%20%20root%20%3D%20dfs%28preorder,%20inorder_map,%200,%200,%20len%28inorder%29%20-%201%29%0A%20%20%20%20return%20root%0A%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20preorder%20%3D%20%5B3,%209,%202,%201,%207%5D%0A%20%20%20%20inorder%20%3D%20%5B9,%203,%201,%202,%207%5D%0A%20%20%20%20print%28f%22%E5%89%8D%E5%BA%8F%E9%81%8D%E5%8E%86%20%3D%20%7Bpreorder%7D%22%29%0A%20%20%20%20print%28f%22%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86%20%3D%20%7Binorder%7D%22%29%0A%20%20%20%20root%20%3D%20build_tree%28preorder,%20inorder%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=21&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
The diagram below shows the recursive process of building the binary tree, where each node is established during the "descending" process, and each edge (reference) is established during the "ascending" process.
|
||||
|
||||
=== "<1>"
|
||||
|
||||
@@ -100,97 +100,72 @@ In the code, we declare a recursive function `dfs(i, src, buf, tar)` whose role
|
||||
|
||||
```python title="hanota.py"
|
||||
def move(src: list[int], tar: list[int]):
|
||||
"""移动一个圆盘"""
|
||||
# 从 src 顶部拿出一个圆盘
|
||||
"""Move a disc"""
|
||||
# Take out a disc from the top of src
|
||||
pan = src.pop()
|
||||
# 将圆盘放入 tar 顶部
|
||||
# Place the disc on top of tar
|
||||
tar.append(pan)
|
||||
|
||||
def dfs(i: int, src: list[int], buf: list[int], tar: list[int]):
|
||||
"""求解汉诺塔问题 f(i)"""
|
||||
# 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
"""Solve the Tower of Hanoi problem f(i)"""
|
||||
# If only one disc remains on src, move it to tar
|
||||
if i == 1:
|
||||
move(src, tar)
|
||||
return
|
||||
# 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
# Subproblem f(i-1): move the top i-1 discs from src with the help of tar to buf
|
||||
dfs(i - 1, src, tar, buf)
|
||||
# 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
# Subproblem f(1): move the remaining one disc from src to tar
|
||||
move(src, tar)
|
||||
# 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
# Subproblem f(i-1): move the top i-1 discs from buf with the help of src to tar
|
||||
dfs(i - 1, buf, src, tar)
|
||||
|
||||
def solve_hanota(A: list[int], B: list[int], C: list[int]):
|
||||
"""求解汉诺塔问题"""
|
||||
"""Solve the Tower of Hanoi problem"""
|
||||
n = len(A)
|
||||
# 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
# Move the top n discs from A with the help of B to C
|
||||
dfs(n, A, B, C)
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="hanota.cpp"
|
||||
/* 移动一个圆盘 */
|
||||
void move(vector<int> &src, vector<int> &tar) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
int pan = src.back();
|
||||
src.pop_back();
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.push_back(pan);
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
void dfs(int i, vector<int> &src, vector<int> &buf, vector<int> &tar) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i == 1) {
|
||||
move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
void solveHanota(vector<int> &A, vector<int> &B, vector<int> &C) {
|
||||
int n = A.size();
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="hanota.java"
|
||||
/* 移动一个圆盘 */
|
||||
/* Move a disc */
|
||||
void move(List<Integer> src, List<Integer> tar) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
// Take out a disc from the top of src
|
||||
Integer pan = src.remove(src.size() - 1);
|
||||
// 将圆盘放入 tar 顶部
|
||||
// Place the disc on top of tar
|
||||
tar.add(pan);
|
||||
}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
/* Solve the Tower of Hanoi problem f(i) */
|
||||
void dfs(int i, List<Integer> src, List<Integer> buf, List<Integer> tar) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
// If only one disc remains on src, move it to tar
|
||||
if (i == 1) {
|
||||
move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
// Subproblem f(i-1): move the top i-1 discs from src with the help of tar to buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
// Subproblem f(1): move the remaining one disc from src to tar
|
||||
move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
// Subproblem f(i-1): move the top i-1 discs from buf with the help of src to tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
/* Solve the Tower of Hanoi problem */
|
||||
void solveHanota(List<Integer> A, List<Integer> B, List<Integer> C) {
|
||||
int n = A.size();
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
// Move the top n discs from A with the help of B to C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
```
|
||||
@@ -198,313 +173,91 @@ In the code, we declare a recursive function `dfs(i, src, buf, tar)` whose role
|
||||
=== "C#"
|
||||
|
||||
```csharp title="hanota.cs"
|
||||
/* 移动一个圆盘 */
|
||||
void Move(List<int> src, List<int> tar) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
int pan = src[^1];
|
||||
src.RemoveAt(src.Count - 1);
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.Add(pan);
|
||||
}
|
||||
[class]{hanota}-[func]{Move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
void DFS(int i, List<int> src, List<int> buf, List<int> tar) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i == 1) {
|
||||
Move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
DFS(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
Move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
DFS(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{hanota}-[func]{DFS}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
void SolveHanota(List<int> A, List<int> B, List<int> C) {
|
||||
int n = A.Count;
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
DFS(n, A, B, C);
|
||||
}
|
||||
[class]{hanota}-[func]{SolveHanota}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="hanota.go"
|
||||
/* 移动一个圆盘 */
|
||||
func move(src, tar *list.List) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
pan := src.Back()
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.PushBack(pan.Value)
|
||||
// 移除 src 顶部圆盘
|
||||
src.Remove(pan)
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
func dfsHanota(i int, src, buf, tar *list.List) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if i == 1 {
|
||||
move(src, tar)
|
||||
return
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfsHanota(i-1, src, tar, buf)
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar)
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfsHanota(i-1, buf, src, tar)
|
||||
}
|
||||
[class]{}-[func]{dfsHanota}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
func solveHanota(A, B, C *list.List) {
|
||||
n := A.Len()
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfsHanota(n, A, B, C)
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="hanota.swift"
|
||||
/* 移动一个圆盘 */
|
||||
func move(src: inout [Int], tar: inout [Int]) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
let pan = src.popLast()!
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.append(pan)
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
func dfs(i: Int, src: inout [Int], buf: inout [Int], tar: inout [Int]) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if i == 1 {
|
||||
move(src: &src, tar: &tar)
|
||||
return
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i: i - 1, src: &src, buf: &tar, tar: &buf)
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src: &src, tar: &tar)
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i: i - 1, src: &buf, buf: &src, tar: &tar)
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
func solveHanota(A: inout [Int], B: inout [Int], C: inout [Int]) {
|
||||
let n = A.count
|
||||
// 列表尾部是柱子顶部
|
||||
// 将 src 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(i: n, src: &A, buf: &B, tar: &C)
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="hanota.js"
|
||||
/* 移动一个圆盘 */
|
||||
function move(src, tar) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
const pan = src.pop();
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.push(pan);
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
function dfs(i, src, buf, tar) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i === 1) {
|
||||
move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
function solveHanota(A, B, C) {
|
||||
const n = A.length;
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="hanota.ts"
|
||||
/* 移动一个圆盘 */
|
||||
function move(src: number[], tar: number[]): void {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
const pan = src.pop();
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.push(pan);
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
function dfs(i: number, src: number[], buf: number[], tar: number[]): void {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i === 1) {
|
||||
move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
function solveHanota(A: number[], B: number[], C: number[]): void {
|
||||
const n = A.length;
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="hanota.dart"
|
||||
/* 移动一个圆盘 */
|
||||
void move(List<int> src, List<int> tar) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
int pan = src.removeLast();
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.add(pan);
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
void dfs(int i, List<int> src, List<int> buf, List<int> tar) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i == 1) {
|
||||
move(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
void solveHanota(List<int> A, List<int> B, List<int> C) {
|
||||
int n = A.length;
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="hanota.rs"
|
||||
/* 移动一个圆盘 */
|
||||
fn move_pan(src: &mut Vec<i32>, tar: &mut Vec<i32>) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
let pan = src.remove(src.len() - 1);
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.push(pan);
|
||||
}
|
||||
[class]{}-[func]{move_pan}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
fn dfs(i: i32, src: &mut Vec<i32>, buf: &mut Vec<i32>, tar: &mut Vec<i32>) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if i == 1 {
|
||||
move_pan(src, tar);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move_pan(src, tar);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
fn solve_hanota(A: &mut Vec<i32>, B: &mut Vec<i32>, C: &mut Vec<i32>) {
|
||||
let n = A.len() as i32;
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C);
|
||||
}
|
||||
[class]{}-[func]{solve_hanota}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="hanota.c"
|
||||
/* 移动一个圆盘 */
|
||||
void move(int *src, int *srcSize, int *tar, int *tarSize) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
int pan = src[*srcSize - 1];
|
||||
src[*srcSize - 1] = 0;
|
||||
(*srcSize)--;
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar[*tarSize] = pan;
|
||||
(*tarSize)++;
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
void dfs(int i, int *src, int *srcSize, int *buf, int *bufSize, int *tar, int *tarSize) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i == 1) {
|
||||
move(src, srcSize, tar, tarSize);
|
||||
return;
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, srcSize, tar, tarSize, buf, bufSize);
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, srcSize, tar, tarSize);
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, bufSize, src, srcSize, tar, tarSize);
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
void solveHanota(int *A, int *ASize, int *B, int *BSize, int *C, int *CSize) {
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(*ASize, A, ASize, B, BSize, C, CSize);
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="hanota.kt"
|
||||
/* 移动一个圆盘 */
|
||||
fun move(src: MutableList<Int>, tar: MutableList<Int>) {
|
||||
// 从 src 顶部拿出一个圆盘
|
||||
val pan = src.removeAt(src.size - 1)
|
||||
// 将圆盘放入 tar 顶部
|
||||
tar.add(pan)
|
||||
}
|
||||
[class]{}-[func]{move}
|
||||
|
||||
/* 求解汉诺塔问题 f(i) */
|
||||
fun dfs(i: Int, src: MutableList<Int>, buf: MutableList<Int>, tar: MutableList<Int>) {
|
||||
// 若 src 只剩下一个圆盘,则直接将其移到 tar
|
||||
if (i == 1) {
|
||||
move(src, tar)
|
||||
return
|
||||
}
|
||||
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
|
||||
dfs(i - 1, src, tar, buf)
|
||||
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
|
||||
move(src, tar)
|
||||
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
|
||||
dfs(i - 1, buf, src, tar)
|
||||
}
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
/* 求解汉诺塔问题 */
|
||||
fun solveHanota(A: MutableList<Int>, B: MutableList<Int>, C: MutableList<Int>) {
|
||||
val n = A.size
|
||||
// 将 A 顶部 n 个圆盘借助 B 移到 C
|
||||
dfs(n, A, B, C)
|
||||
}
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
@@ -527,11 +280,6 @@ In the code, we declare a recursive function `dfs(i, src, buf, tar)` whose role
|
||||
[class]{}-[func]{solveHanota}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20move%28src%3A%20list%5Bint%5D,%20tar%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%22%22%22%0A%20%20%20%20%23%20%E4%BB%8E%20src%20%E9%A1%B6%E9%83%A8%E6%8B%BF%E5%87%BA%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%0A%20%20%20%20pan%20%3D%20src.pop%28%29%0A%20%20%20%20%23%20%E5%B0%86%E5%9C%86%E7%9B%98%E6%94%BE%E5%85%A5%20tar%20%E9%A1%B6%E9%83%A8%0A%20%20%20%20tar.append%28pan%29%0A%0A%0Adef%20dfs%28i%3A%20int,%20src%3A%20list%5Bint%5D,%20buf%3A%20list%5Bint%5D,%20tar%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E6%B1%82%E8%A7%A3%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98%20f%28i%29%22%22%22%0A%20%20%20%20%23%20%E8%8B%A5%20src%20%E5%8F%AA%E5%89%A9%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%EF%BC%8C%E5%88%99%E7%9B%B4%E6%8E%A5%E5%B0%86%E5%85%B6%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20if%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20move%28src,%20tar%29%0A%20%20%20%20%20%20%20%20return%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i-1%29%20%EF%BC%9A%E5%B0%86%20src%20%E9%A1%B6%E9%83%A8%20i-1%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20tar%20%E7%A7%BB%E5%88%B0%20buf%0A%20%20%20%20dfs%28i%20-%201,%20src,%20tar,%20buf%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%281%29%20%EF%BC%9A%E5%B0%86%20src%20%E5%89%A9%E4%BD%99%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20move%28src,%20tar%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i-1%29%20%EF%BC%9A%E5%B0%86%20buf%20%E9%A1%B6%E9%83%A8%20i-1%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20src%20%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20dfs%28i%20-%201,%20buf,%20src,%20tar%29%0A%0A%0Adef%20solve_hanota%28A%3A%20list%5Bint%5D,%20B%3A%20list%5Bint%5D,%20C%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E6%B1%82%E8%A7%A3%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98%22%22%22%0A%20%20%20%20n%20%3D%20len%28A%29%0A%20%20%20%20%23%20%E5%B0%86%20A%20%E9%A1%B6%E9%83%A8%20n%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20B%20%E7%A7%BB%E5%88%B0%20C%0A%20%20%20%20dfs%28n,%20A,%20B,%20C%29%0A%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%E5%88%97%E8%A1%A8%E5%B0%BE%E9%83%A8%E6%98%AF%E6%9F%B1%E5%AD%90%E9%A1%B6%E9%83%A8%0A%20%20%20%20A%20%3D%20%5B5,%204,%203,%202,%201%5D%0A%20%20%20%20B%20%3D%20%5B%5D%0A%20%20%20%20C%20%3D%20%5B%5D%0A%20%20%20%20print%28%22%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81%E4%B8%8B%EF%BC%9A%22%29%0A%20%20%20%20print%28f%22A%20%3D%20%7BA%7D%22%29%0A%20%20%20%20print%28f%22B%20%3D%20%7BB%7D%22%29%0A%20%20%20%20print%28f%22C%20%3D%20%7BC%7D%22%29%0A%0A%20%20%20%20solve_hanota%28A,%20B,%20C%29%0A%0A%20%20%20%20print%28%22%E5%9C%86%E7%9B%98%E7%A7%BB%E5%8A%A8%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%9A%22%29%0A%20%20%20%20print%28f%22A%20%3D%20%7BA%7D%22%29%0A%20%20%20%20print%28f%22B%20%3D%20%7BB%7D%22%29%0A%20%20%20%20print%28f%22C%20%3D%20%7BC%7D%22%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=12&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
|
||||
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=def%20move%28src%3A%20list%5Bint%5D,%20tar%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%22%22%22%0A%20%20%20%20%23%20%E4%BB%8E%20src%20%E9%A1%B6%E9%83%A8%E6%8B%BF%E5%87%BA%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%0A%20%20%20%20pan%20%3D%20src.pop%28%29%0A%20%20%20%20%23%20%E5%B0%86%E5%9C%86%E7%9B%98%E6%94%BE%E5%85%A5%20tar%20%E9%A1%B6%E9%83%A8%0A%20%20%20%20tar.append%28pan%29%0A%0A%0Adef%20dfs%28i%3A%20int,%20src%3A%20list%5Bint%5D,%20buf%3A%20list%5Bint%5D,%20tar%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E6%B1%82%E8%A7%A3%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98%20f%28i%29%22%22%22%0A%20%20%20%20%23%20%E8%8B%A5%20src%20%E5%8F%AA%E5%89%A9%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%EF%BC%8C%E5%88%99%E7%9B%B4%E6%8E%A5%E5%B0%86%E5%85%B6%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20if%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20move%28src,%20tar%29%0A%20%20%20%20%20%20%20%20return%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i-1%29%20%EF%BC%9A%E5%B0%86%20src%20%E9%A1%B6%E9%83%A8%20i-1%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20tar%20%E7%A7%BB%E5%88%B0%20buf%0A%20%20%20%20dfs%28i%20-%201,%20src,%20tar,%20buf%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%281%29%20%EF%BC%9A%E5%B0%86%20src%20%E5%89%A9%E4%BD%99%E4%B8%80%E4%B8%AA%E5%9C%86%E7%9B%98%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20move%28src,%20tar%29%0A%20%20%20%20%23%20%E5%AD%90%E9%97%AE%E9%A2%98%20f%28i-1%29%20%EF%BC%9A%E5%B0%86%20buf%20%E9%A1%B6%E9%83%A8%20i-1%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20src%20%E7%A7%BB%E5%88%B0%20tar%0A%20%20%20%20dfs%28i%20-%201,%20buf,%20src,%20tar%29%0A%0A%0Adef%20solve_hanota%28A%3A%20list%5Bint%5D,%20B%3A%20list%5Bint%5D,%20C%3A%20list%5Bint%5D%29%3A%0A%20%20%20%20%22%22%22%E6%B1%82%E8%A7%A3%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98%22%22%22%0A%20%20%20%20n%20%3D%20len%28A%29%0A%20%20%20%20%23%20%E5%B0%86%20A%20%E9%A1%B6%E9%83%A8%20n%20%E4%B8%AA%E5%9C%86%E7%9B%98%E5%80%9F%E5%8A%A9%20B%20%E7%A7%BB%E5%88%B0%20C%0A%20%20%20%20dfs%28n,%20A,%20B,%20C%29%0A%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%E5%88%97%E8%A1%A8%E5%B0%BE%E9%83%A8%E6%98%AF%E6%9F%B1%E5%AD%90%E9%A1%B6%E9%83%A8%0A%20%20%20%20A%20%3D%20%5B5,%204,%203,%202,%201%5D%0A%20%20%20%20B%20%3D%20%5B%5D%0A%20%20%20%20C%20%3D%20%5B%5D%0A%20%20%20%20print%28%22%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81%E4%B8%8B%EF%BC%9A%22%29%0A%20%20%20%20print%28f%22A%20%3D%20%7BA%7D%22%29%0A%20%20%20%20print%28f%22B%20%3D%20%7BB%7D%22%29%0A%20%20%20%20print%28f%22C%20%3D%20%7BC%7D%22%29%0A%0A%20%20%20%20solve_hanota%28A,%20B,%20C%29%0A%0A%20%20%20%20print%28%22%E5%9C%86%E7%9B%98%E7%A7%BB%E5%8A%A8%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%9A%22%29%0A%20%20%20%20print%28f%22A%20%3D%20%7BA%7D%22%29%0A%20%20%20%20print%28f%22B%20%3D%20%7BB%7D%22%29%0A%20%20%20%20print%28f%22C%20%3D%20%7BC%7D%22%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=12&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
As shown in Figure 12-15, the Tower of Hanoi forms a recursive tree with a height of $n$, each node representing a subproblem, corresponding to an open `dfs()` function, **thus the time complexity is $O(2^n)$, and the space complexity is $O(n)$**.
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
Reference in New Issue
Block a user