mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-24 02:21:30 +08:00
build
This commit is contained in:
@@ -57,62 +57,46 @@ The code is as follows:
|
||||
|
||||
```python title="binary_search.py"
|
||||
def binary_search(nums: list[int], target: int) -> int:
|
||||
"""二分查找(双闭区间)"""
|
||||
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
"""Binary search (double closed interval)"""
|
||||
# Initialize double closed interval [0, n-1], i.e., i, j point to the first element and last element of the array respectively
|
||||
i, j = 0, len(nums) - 1
|
||||
# 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
# Loop until the search interval is empty (when i > j, it is empty)
|
||||
while i <= j:
|
||||
# 理论上 Python 的数字可以无限大(取决于内存大小),无须考虑大数越界问题
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
# Theoretically, Python's numbers can be infinitely large (depending on memory size), so there is no need to consider large number overflow
|
||||
m = (i + j) // 2 # Calculate midpoint index m
|
||||
if nums[m] < target:
|
||||
i = m + 1 # 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1 # This situation indicates that target is in the interval [m+1, j]
|
||||
elif nums[m] > target:
|
||||
j = m - 1 # 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1 # This situation indicates that target is in the interval [i, m-1]
|
||||
else:
|
||||
return m # 找到目标元素,返回其索引
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
return m # Found the target element, thus return its index
|
||||
return -1 # Did not find the target element, thus return -1
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search.cpp"
|
||||
/* 二分查找(双闭区间) */
|
||||
int binarySearch(vector<int> &nums, int target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
int i = 0, j = nums.size() - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search.java"
|
||||
/* 二分查找(双闭区间) */
|
||||
/* Binary search (double closed interval) */
|
||||
int binarySearch(int[] nums, int target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
// Initialize double closed interval [0, n-1], i.e., i, j point to the first element and last element of the array respectively
|
||||
int i = 0, j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
// Loop until the search interval is empty (when i > j, it is empty)
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
int m = i + (j - i) / 2; // Calculate midpoint index m
|
||||
if (nums[m] < target) // This situation indicates that target is in the interval [m+1, j]
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
else if (nums[m] > target) // This situation indicates that target is in the interval [i, m-1]
|
||||
j = m - 1;
|
||||
else // 找到目标元素,返回其索引
|
||||
else // Found the target element, thus return its index
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
// Did not find the target element, thus return -1
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
@@ -120,277 +104,69 @@ The code is as follows:
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search.cs"
|
||||
/* 二分查找(双闭区间) */
|
||||
int BinarySearch(int[] nums, int target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
int i = 0, j = nums.Length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{binary_search}-[func]{BinarySearch}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search.go"
|
||||
/* 二分查找(双闭区间) */
|
||||
func binarySearch(nums []int, target int) int {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
i, j := 0, len(nums)-1
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
for i <= j {
|
||||
m := i + (j-i)/2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search.swift"
|
||||
/* 二分查找(双闭区间) */
|
||||
func binarySearch(nums: [Int], target: Int) -> Int {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
var i = nums.startIndex
|
||||
var j = nums.endIndex - 1
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search.js"
|
||||
/* 二分查找(双闭区间) */
|
||||
function binarySearch(nums, target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
let i = 0,
|
||||
j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
// 计算中点索引 m ,使用 parseInt() 向下取整
|
||||
const m = parseInt(i + (j - i) / 2);
|
||||
if (nums[m] < target)
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target)
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
else return m; // 找到目标元素,返回其索引
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search.ts"
|
||||
/* 二分查找(双闭区间) */
|
||||
function binarySearch(nums: number[], target: number): number {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
let i = 0,
|
||||
j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
// 计算中点索引 m
|
||||
const m = Math.floor(i + (j - i) / 2);
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return -1; // 未找到目标元素,返回 -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search.dart"
|
||||
/* 二分查找(双闭区间) */
|
||||
int binarySearch(List<int> nums, int target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
int i = 0, j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) ~/ 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search.rs"
|
||||
/* 二分查找(双闭区间) */
|
||||
fn binary_search(nums: &[i32], target: i32) -> i32 {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
let mut i = 0;
|
||||
let mut j = nums.len() as i32 - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if nums[m as usize] < target {
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if nums[m as usize] > target {
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binary_search}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search.c"
|
||||
/* 二分查找(双闭区间) */
|
||||
int binarySearch(int *nums, int len, int target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
int i = 0, j = len - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search.kt"
|
||||
/* 二分查找(双闭区间) */
|
||||
fun binarySearch(nums: IntArray, target: Int): Int {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
var i = 0
|
||||
var j = nums.size - 1
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
val m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
else // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search.rb"
|
||||
### 二分查找(双闭区间) ###
|
||||
def binary_search(nums, target)
|
||||
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
i, j = 0, nums.length - 1
|
||||
|
||||
# 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while i <= j
|
||||
# 理论上 Ruby 的数字可以无限大(取决于内存大小),无须考虑大数越界问题
|
||||
m = (i + j) / 2 # 计算中点索引 m
|
||||
|
||||
if nums[m] < target
|
||||
i = m + 1 # 此情况说明 target 在区间 [m+1, j] 中
|
||||
elsif nums[m] > target
|
||||
j = m - 1 # 此情况说明 target 在区间 [i, m-1] 中
|
||||
else
|
||||
return m # 找到目标元素,返回其索引
|
||||
end
|
||||
end
|
||||
|
||||
-1 # 未找到目标元素,返回 -1
|
||||
end
|
||||
[class]{}-[func]{binary_search}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="binary_search.zig"
|
||||
// 二分查找(双闭区间)
|
||||
fn binarySearch(comptime T: type, nums: std.ArrayList(T), target: T) T {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
var i: usize = 0;
|
||||
var j: usize = nums.items.len - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
var m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums.items[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if (nums.items[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return @intCast(m);
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[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%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%EF%BC%88%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%EF%BC%89%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%20%EF%BC%8C%E5%8D%B3%20i,%20j%20%E5%88%86%E5%88%AB%E6%8C%87%E5%90%91%E6%95%B0%E7%BB%84%E9%A6%96%E5%85%83%E7%B4%A0%E3%80%81%E5%B0%BE%E5%85%83%E7%B4%A0%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%EF%BC%8C%E5%BD%93%E6%90%9C%E7%B4%A2%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E8%B7%B3%E5%87%BA%EF%BC%88%E5%BD%93%20i%20%3E%20j%20%E6%97%B6%E4%B8%BA%E7%A9%BA%EF%BC%89%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20%23%20%E7%90%86%E8%AE%BA%E4%B8%8A%20Python%20%E7%9A%84%E6%95%B0%E5%AD%97%E5%8F%AF%E4%BB%A5%E6%97%A0%E9%99%90%E5%A4%A7%EF%BC%88%E5%8F%96%E5%86%B3%E4%BA%8E%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%EF%BC%89%EF%BC%8C%E6%97%A0%E9%A1%BB%E8%80%83%E8%99%91%E5%A4%A7%E6%95%B0%E8%B6%8A%E7%95%8C%E9%97%AE%E9%A2%98%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%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%20return%20-1%20%20%23%20%E6%9C%AA%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%20-1%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%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=5&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%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%EF%BC%88%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%EF%BC%89%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%20%EF%BC%8C%E5%8D%B3%20i,%20j%20%E5%88%86%E5%88%AB%E6%8C%87%E5%90%91%E6%95%B0%E7%BB%84%E9%A6%96%E5%85%83%E7%B4%A0%E3%80%81%E5%B0%BE%E5%85%83%E7%B4%A0%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%EF%BC%8C%E5%BD%93%E6%90%9C%E7%B4%A2%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E8%B7%B3%E5%87%BA%EF%BC%88%E5%BD%93%20i%20%3E%20j%20%E6%97%B6%E4%B8%BA%E7%A9%BA%EF%BC%89%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20%23%20%E7%90%86%E8%AE%BA%E4%B8%8A%20Python%20%E7%9A%84%E6%95%B0%E5%AD%97%E5%8F%AF%E4%BB%A5%E6%97%A0%E9%99%90%E5%A4%A7%EF%BC%88%E5%8F%96%E5%86%B3%E4%BA%8E%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%EF%BC%89%EF%BC%8C%E6%97%A0%E9%A1%BB%E8%80%83%E8%99%91%E5%A4%A7%E6%95%B0%E8%B6%8A%E7%95%8C%E9%97%AE%E9%A2%98%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%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%20return%20-1%20%20%23%20%E6%9C%AA%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%20-1%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%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=5&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
**Time complexity is $O(\log n)$** : In the binary loop, the interval reduces by half each round, hence the number of iterations is $\log_2 n$.
|
||||
|
||||
**Space complexity is $O(1)$** : Pointers $i$ and $j$ use constant size space.
|
||||
@@ -405,61 +181,45 @@ We can implement a binary search algorithm with the same functionality based on
|
||||
|
||||
```python title="binary_search.py"
|
||||
def binary_search_lcro(nums: list[int], target: int) -> int:
|
||||
"""二分查找(左闭右开区间)"""
|
||||
# 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
"""Binary search (left closed right open interval)"""
|
||||
# Initialize left closed right open interval [0, n), i.e., i, j point to the first element and the last element +1 of the array respectively
|
||||
i, j = 0, len(nums)
|
||||
# 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
# Loop until the search interval is empty (when i = j, it is empty)
|
||||
while i < j:
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
m = (i + j) // 2 # Calculate midpoint index m
|
||||
if nums[m] < target:
|
||||
i = m + 1 # 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1 # This situation indicates that target is in the interval [m+1, j)
|
||||
elif nums[m] > target:
|
||||
j = m # 此情况说明 target 在区间 [i, m) 中
|
||||
j = m # This situation indicates that target is in the interval [i, m)
|
||||
else:
|
||||
return m # 找到目标元素,返回其索引
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
return m # Found the target element, thus return its index
|
||||
return -1 # Did not find the target element, thus return -1
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search.cpp"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
int binarySearchLCRO(vector<int> &nums, int target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
int i = 0, j = nums.size();
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search.java"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
/* Binary search (left closed right open interval) */
|
||||
int binarySearchLCRO(int[] nums, int target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
// Initialize left closed right open interval [0, n), i.e., i, j point to the first element and the last element +1 of the array respectively
|
||||
int i = 0, j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
// Loop until the search interval is empty (when i = j, it is empty)
|
||||
while (i < j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
int m = i + (j - i) / 2; // Calculate midpoint index m
|
||||
if (nums[m] < target) // This situation indicates that target is in the interval [m+1, j)
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
else if (nums[m] > target) // This situation indicates that target is in the interval [i, m)
|
||||
j = m;
|
||||
else // 找到目标元素,返回其索引
|
||||
else // Found the target element, thus return its index
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
// Did not find the target element, thus return -1
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
@@ -467,278 +227,69 @@ We can implement a binary search algorithm with the same functionality based on
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search.cs"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
int BinarySearchLCRO(int[] nums, int target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
int i = 0, j = nums.Length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{binary_search}-[func]{BinarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search.go"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
func binarySearchLCRO(nums []int, target int) int {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
i, j := 0, len(nums)
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
for i < j {
|
||||
m := i + (j-i)/2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search.swift"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
func binarySearchLCRO(nums: [Int], target: Int) -> Int {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
var i = nums.startIndex
|
||||
var j = nums.endIndex
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while i < j {
|
||||
let m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search.js"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
function binarySearchLCRO(nums, target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
let i = 0,
|
||||
j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
// 计算中点索引 m ,使用 parseInt() 向下取整
|
||||
const m = parseInt(i + (j - i) / 2);
|
||||
if (nums[m] < target)
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target)
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
// 找到目标元素,返回其索引
|
||||
else return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search.ts"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
function binarySearchLCRO(nums: number[], target: number): number {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
let i = 0,
|
||||
j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
// 计算中点索引 m
|
||||
const m = Math.floor(i + (j - i) / 2);
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return -1; // 未找到目标元素,返回 -1
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search.dart"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
int binarySearchLCRO(List<int> nums, int target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
int i = 0, j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
int m = i + (j - i) ~/ 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search.rs"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
fn binary_search_lcro(nums: &[i32], target: i32) -> i32 {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
let mut i = 0;
|
||||
let mut j = nums.len() as i32;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while i < j {
|
||||
let m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if nums[m as usize] < target {
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if nums[m as usize] > target {
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binary_search_lcro}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search.c"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
int binarySearchLCRO(int *nums, int len, int target) {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
int i = 0, j = len;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search.kt"
|
||||
/* 二分查找(左闭右开区间) */
|
||||
fun binarySearchLCRO(nums: IntArray, target: Int): Int {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
var i = 0
|
||||
var j = nums.size
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
val m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m
|
||||
else // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search.rb"
|
||||
### 二分查找(左闭右开区间) ###
|
||||
def binary_search_lcro(nums, target)
|
||||
# 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
i, j = 0, nums.length
|
||||
|
||||
# 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while i < j
|
||||
# 计算中点索引 m
|
||||
m = (i + j) / 2
|
||||
|
||||
if nums[m] < target
|
||||
i = m + 1 # 此情况说明 target 在区间 [m+1, j) 中
|
||||
elsif nums[m] > target
|
||||
j = m - 1 # 此情况说明 target 在区间 [i, m) 中
|
||||
else
|
||||
return m # 找到目标元素,返回其索引
|
||||
end
|
||||
end
|
||||
|
||||
-1 # 未找到目标元素,返回 -1
|
||||
end
|
||||
[class]{}-[func]{binary_search_lcro}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="binary_search.zig"
|
||||
// 二分查找(左闭右开区间)
|
||||
fn binarySearchLCRO(comptime T: type, nums: std.ArrayList(T), target: T) T {
|
||||
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
var i: usize = 0;
|
||||
var j: usize = nums.items.len;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i <= j) {
|
||||
var m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums.items[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if (nums.items[m] > target) { // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return @intCast(m);
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLCRO}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20binary_search_lcro%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%EF%BC%88%E5%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%EF%BC%89%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%20%5B0,%20n%29%20%EF%BC%8C%E5%8D%B3%20i,%20j%20%E5%88%86%E5%88%AB%E6%8C%87%E5%90%91%E6%95%B0%E7%BB%84%E9%A6%96%E5%85%83%E7%B4%A0%E3%80%81%E5%B0%BE%E5%85%83%E7%B4%A0%2B1%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%EF%BC%8C%E5%BD%93%E6%90%9C%E7%B4%A2%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E8%B7%B3%E5%87%BA%EF%BC%88%E5%BD%93%20i%20%3D%20j%20%E6%97%B6%E4%B8%BA%E7%A9%BA%EF%BC%89%0A%20%20%20%20while%20i%20%3C%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%29%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m%29%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%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%20return%20-1%20%20%23%20%E6%9C%AA%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%20-1%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%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%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%EF%BC%89%0A%20%20%20%20index%20%3D%20binary_search_lcro%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=5&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%20binary_search_lcro%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%EF%BC%88%E5%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%EF%BC%89%22%22%22%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%20%5B0,%20n%29%20%EF%BC%8C%E5%8D%B3%20i,%20j%20%E5%88%86%E5%88%AB%E6%8C%87%E5%90%91%E6%95%B0%E7%BB%84%E9%A6%96%E5%85%83%E7%B4%A0%E3%80%81%E5%B0%BE%E5%85%83%E7%B4%A0%2B1%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%EF%BC%8C%E5%BD%93%E6%90%9C%E7%B4%A2%E5%8C%BA%E9%97%B4%E4%B8%BA%E7%A9%BA%E6%97%B6%E8%B7%B3%E5%87%BA%EF%BC%88%E5%BD%93%20i%20%3D%20j%20%E6%97%B6%E4%B8%BA%E7%A9%BA%EF%BC%89%0A%20%20%20%20while%20i%20%3C%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%29%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20%20%23%20%E6%AD%A4%E6%83%85%E5%86%B5%E8%AF%B4%E6%98%8E%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m%29%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%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%20return%20-1%20%20%23%20%E6%9C%AA%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%20-1%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%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%B7%A6%E9%97%AD%E5%8F%B3%E5%BC%80%E5%8C%BA%E9%97%B4%EF%BC%89%0A%20%20%20%20index%20%3D%20binary_search_lcro%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=5&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 10-3, in the two types of interval representations, the initialization of the binary search algorithm, the loop condition, and the narrowing interval operation are different.
|
||||
|
||||
Since both boundaries in the "closed interval" representation are defined as closed, the operations to narrow the interval through pointers $i$ and $j$ are also symmetrical. This makes it less prone to errors, **therefore, it is generally recommended to use the "closed interval" approach**.
|
||||
|
||||
@@ -23,44 +23,34 @@ In these cases, simply return $-1$. The code is as follows:
|
||||
|
||||
```python title="binary_search_edge.py"
|
||||
def binary_search_left_edge(nums: list[int], target: int) -> int:
|
||||
"""二分查找最左一个 target"""
|
||||
# 等价于查找 target 的插入点
|
||||
"""Binary search for the leftmost target"""
|
||||
# Equivalent to finding the insertion point of target
|
||||
i = binary_search_insertion(nums, target)
|
||||
# 未找到 target ,返回 -1
|
||||
# Did not find target, thus return -1
|
||||
if i == len(nums) or nums[i] != target:
|
||||
return -1
|
||||
# 找到 target ,返回索引 i
|
||||
# Found target, return index i
|
||||
return i
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search_edge.cpp"
|
||||
/* 二分查找最左一个 target */
|
||||
int binarySearchLeftEdge(vector<int> &nums, int target) {
|
||||
// 等价于查找 target 的插入点
|
||||
int i = binarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i == nums.size() || nums[i] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search_edge.java"
|
||||
/* 二分查找最左一个 target */
|
||||
/* Binary search for the leftmost target */
|
||||
int binarySearchLeftEdge(int[] nums, int target) {
|
||||
// 等价于查找 target 的插入点
|
||||
// Equivalent to finding the insertion point of target
|
||||
int i = binary_search_insertion.binarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
// Did not find target, thus return -1
|
||||
if (i == nums.length || nums[i] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
// Found target, return index i
|
||||
return i;
|
||||
}
|
||||
```
|
||||
@@ -68,160 +58,61 @@ In these cases, simply return $-1$. The code is as follows:
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search_edge.cs"
|
||||
/* 二分查找最左一个 target */
|
||||
int BinarySearchLeftEdge(int[] nums, int target) {
|
||||
// 等价于查找 target 的插入点
|
||||
int i = binary_search_insertion.BinarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i == nums.Length || nums[i] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{binary_search_edge}-[func]{BinarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search_edge.go"
|
||||
/* 二分查找最左一个 target */
|
||||
func binarySearchLeftEdge(nums []int, target int) int {
|
||||
// 等价于查找 target 的插入点
|
||||
i := binarySearchInsertion(nums, target)
|
||||
// 未找到 target ,返回 -1
|
||||
if i == len(nums) || nums[i] != target {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_edge.swift"
|
||||
/* 二分查找最左一个 target */
|
||||
func binarySearchLeftEdge(nums: [Int], target: Int) -> Int {
|
||||
// 等价于查找 target 的插入点
|
||||
let i = binarySearchInsertion(nums: nums, target: target)
|
||||
// 未找到 target ,返回 -1
|
||||
if i == nums.endIndex || nums[i] != target {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search_edge.js"
|
||||
/* 二分查找最左一个 target */
|
||||
function binarySearchLeftEdge(nums, target) {
|
||||
// 等价于查找 target 的插入点
|
||||
const i = binarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i === nums.length || nums[i] !== target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search_edge.ts"
|
||||
/* 二分查找最左一个 target */
|
||||
function binarySearchLeftEdge(nums: Array<number>, target: number): number {
|
||||
// 等价于查找 target 的插入点
|
||||
const i = binarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i === nums.length || nums[i] !== target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search_edge.dart"
|
||||
/* 二分查找最左一个 target */
|
||||
int binarySearchLeftEdge(List<int> nums, int target) {
|
||||
// 等价于查找 target 的插入点
|
||||
int i = binarySearchInsertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i == nums.length || nums[i] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search_edge.rs"
|
||||
/* 二分查找最左一个 target */
|
||||
fn binary_search_left_edge(nums: &[i32], target: i32) -> i32 {
|
||||
// 等价于查找 target 的插入点
|
||||
let i = binary_search_insertion(nums, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if i == nums.len() as i32 || nums[i as usize] != target {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
i
|
||||
}
|
||||
[class]{}-[func]{binary_search_left_edge}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search_edge.c"
|
||||
/* 二分查找最左一个 target */
|
||||
int binarySearchLeftEdge(int *nums, int numSize, int target) {
|
||||
// 等价于查找 target 的插入点
|
||||
int i = binarySearchInsertion(nums, numSize, target);
|
||||
// 未找到 target ,返回 -1
|
||||
if (i == numSize || nums[i] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search_edge.kt"
|
||||
/* 二分查找最左一个 target */
|
||||
fun binarySearchLeftEdge(nums: IntArray, target: Int): Int {
|
||||
// 等价于查找 target 的插入点
|
||||
val i = binarySearchInsertion(nums, target)
|
||||
// 未找到 target ,返回 -1
|
||||
if (i == nums.size || nums[i] != target) {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search_edge.rb"
|
||||
### 二分查找最左一个 target ###
|
||||
def binary_search_left_edge(nums, target)
|
||||
# 等价于查找 target 的插入点
|
||||
i = binary_search_insertion(nums, target)
|
||||
|
||||
# 未找到 target ,返回 -1
|
||||
return -1 if i == nums.length || nums[i] != target
|
||||
|
||||
i # 找到 target ,返回索引 i
|
||||
end
|
||||
[class]{}-[func]{binary_search_left_edge}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
@@ -230,11 +121,6 @@ In these cases, simply return $-1$. The code is as follows:
|
||||
[class]{}-[func]{binarySearchLeftEdge}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%0A%0Adef%20binary_search_left_edge%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%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%20target%22%22%22%0A%20%20%20%20%23%20%E7%AD%89%E4%BB%B7%E4%BA%8E%E6%9F%A5%E6%89%BE%20target%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20i%20%3D%20binary_search_insertion%28nums,%20target%29%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20i%20%3D%3D%20len%28nums%29%20or%20nums%5Bi%5D%20!%3D%20target%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%B4%A2%E5%BC%95%20i%0A%20%20%20%20return%20i%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E5%B7%A6%E8%BE%B9%E7%95%8C%E5%92%8C%E5%8F%B3%E8%BE%B9%E7%95%8C%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_left_edge%28nums,%20target%29%0A%20%20%20%20print%28f%22%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%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%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%0A%0Adef%20binary_search_left_edge%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%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%20target%22%22%22%0A%20%20%20%20%23%20%E7%AD%89%E4%BB%B7%E4%BA%8E%E6%9F%A5%E6%89%BE%20target%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20i%20%3D%20binary_search_insertion%28nums,%20target%29%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20i%20%3D%3D%20len%28nums%29%20or%20nums%5Bi%5D%20!%3D%20target%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%B4%A2%E5%BC%95%20i%0A%20%20%20%20return%20i%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E5%B7%A6%E8%BE%B9%E7%95%8C%E5%92%8C%E5%8F%B3%E8%BE%B9%E7%95%8C%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_left_edge%28nums,%20target%29%0A%20%20%20%20print%28f%22%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%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>
|
||||
|
||||
## 10.3.2 Find the right boundary
|
||||
|
||||
So how do we find the rightmost `target`? The most straightforward way is to modify the code, replacing the pointer contraction operation in the case of `nums[m] == target`. The code is omitted here, but interested readers can implement it on their own.
|
||||
@@ -257,50 +143,38 @@ Please note, the insertion point returned is $i$, therefore, it should be subtra
|
||||
|
||||
```python title="binary_search_edge.py"
|
||||
def binary_search_right_edge(nums: list[int], target: int) -> int:
|
||||
"""二分查找最右一个 target"""
|
||||
# 转化为查找最左一个 target + 1
|
||||
"""Binary search for the rightmost target"""
|
||||
# Convert to finding the leftmost target + 1
|
||||
i = binary_search_insertion(nums, target + 1)
|
||||
# j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
# j points to the rightmost target, i points to the first element greater than target
|
||||
j = i - 1
|
||||
# 未找到 target ,返回 -1
|
||||
# Did not find target, thus return -1
|
||||
if j == -1 or nums[j] != target:
|
||||
return -1
|
||||
# 找到 target ,返回索引 j
|
||||
# Found target, return index j
|
||||
return j
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search_edge.cpp"
|
||||
/* 二分查找最右一个 target */
|
||||
int binarySearchRightEdge(vector<int> &nums, int target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
int i = binarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
int j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search_edge.java"
|
||||
/* 二分查找最右一个 target */
|
||||
/* Binary search for the rightmost target */
|
||||
int binarySearchRightEdge(int[] nums, int target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
// Convert to finding the leftmost target + 1
|
||||
int i = binary_search_insertion.binarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
// j points to the rightmost target, i points to the first element greater than target
|
||||
int j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
// Did not find target, thus return -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
// Found target, return index j
|
||||
return j;
|
||||
}
|
||||
```
|
||||
@@ -308,181 +182,61 @@ Please note, the insertion point returned is $i$, therefore, it should be subtra
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search_edge.cs"
|
||||
/* 二分查找最右一个 target */
|
||||
int BinarySearchRightEdge(int[] nums, int target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
int i = binary_search_insertion.BinarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
int j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{binary_search_edge}-[func]{BinarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search_edge.go"
|
||||
/* 二分查找最右一个 target */
|
||||
func binarySearchRightEdge(nums []int, target int) int {
|
||||
// 转化为查找最左一个 target + 1
|
||||
i := binarySearchInsertion(nums, target+1)
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
j := i - 1
|
||||
// 未找到 target ,返回 -1
|
||||
if j == -1 || nums[j] != target {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_edge.swift"
|
||||
/* 二分查找最右一个 target */
|
||||
func binarySearchRightEdge(nums: [Int], target: Int) -> Int {
|
||||
// 转化为查找最左一个 target + 1
|
||||
let i = binarySearchInsertion(nums: nums, target: target + 1)
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
let j = i - 1
|
||||
// 未找到 target ,返回 -1
|
||||
if j == -1 || nums[j] != target {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search_edge.js"
|
||||
/* 二分查找最右一个 target */
|
||||
function binarySearchRightEdge(nums, target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
const i = binarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
const j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j === -1 || nums[j] !== target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search_edge.ts"
|
||||
/* 二分查找最右一个 target */
|
||||
function binarySearchRightEdge(nums: Array<number>, target: number): number {
|
||||
// 转化为查找最左一个 target + 1
|
||||
const i = binarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
const j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j === -1 || nums[j] !== target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search_edge.dart"
|
||||
/* 二分查找最右一个 target */
|
||||
int binarySearchRightEdge(List<int> nums, int target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
int i = binarySearchInsertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
int j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search_edge.rs"
|
||||
/* 二分查找最右一个 target */
|
||||
fn binary_search_right_edge(nums: &[i32], target: i32) -> i32 {
|
||||
// 转化为查找最左一个 target + 1
|
||||
let i = binary_search_insertion(nums, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
let j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if j == -1 || nums[j as usize] != target {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
j
|
||||
}
|
||||
[class]{}-[func]{binary_search_right_edge}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search_edge.c"
|
||||
/* 二分查找最右一个 target */
|
||||
int binarySearchRightEdge(int *nums, int numSize, int target) {
|
||||
// 转化为查找最左一个 target + 1
|
||||
int i = binarySearchInsertion(nums, numSize, target + 1);
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
int j = i - 1;
|
||||
// 未找到 target ,返回 -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1;
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j;
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search_edge.kt"
|
||||
/* 二分查找最右一个 target */
|
||||
fun binarySearchRightEdge(nums: IntArray, target: Int): Int {
|
||||
// 转化为查找最左一个 target + 1
|
||||
val i = binarySearchInsertion(nums, target + 1)
|
||||
// j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
val j = i - 1
|
||||
// 未找到 target ,返回 -1
|
||||
if (j == -1 || nums[j] != target) {
|
||||
return -1
|
||||
}
|
||||
// 找到 target ,返回索引 j
|
||||
return j
|
||||
}
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search_edge.rb"
|
||||
### 二分查找最右一个 target ###
|
||||
def binary_search_right_edge(nums, target)
|
||||
# 转化为查找最左一个 target + 1
|
||||
i = binary_search_insertion(nums, target + 1)
|
||||
|
||||
# j 指向最右一个 target ,i 指向首个大于 target 的元素
|
||||
j = i - 1
|
||||
|
||||
# 未找到 target ,返回 -1
|
||||
return -1 if j == -1 || nums[j] != target
|
||||
|
||||
j # 找到 target ,返回索引 j
|
||||
end
|
||||
[class]{}-[func]{binary_search_right_edge}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
@@ -491,11 +245,6 @@ Please note, the insertion point returned is $i$, therefore, it should be subtra
|
||||
[class]{}-[func]{binarySearchRightEdge}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%0A%0Adef%20binary_search_right_edge%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%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%20target%22%22%22%0A%20%20%20%20%23%20%E8%BD%AC%E5%8C%96%E4%B8%BA%E6%9F%A5%E6%89%BE%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%20target%20%2B%201%0A%20%20%20%20i%20%3D%20binary_search_insertion%28nums,%20target%20%2B%201%29%0A%20%20%20%20%23%20j%20%E6%8C%87%E5%90%91%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%20target%20%EF%BC%8Ci%20%E6%8C%87%E5%90%91%E9%A6%96%E4%B8%AA%E5%A4%A7%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%0A%20%20%20%20j%20%3D%20i%20-%201%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20j%20%3D%3D%20-1%20or%20nums%5Bj%5D%20!%3D%20target%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%B4%A2%E5%BC%95%20j%0A%20%20%20%20return%20j%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E5%B7%A6%E8%BE%B9%E7%95%8C%E5%92%8C%E5%8F%B3%E8%BE%B9%E7%95%8C%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_right_edge%28nums,%20target%29%0A%20%20%20%20print%28f%22%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%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%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%0A%0Adef%20binary_search_right_edge%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%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%20target%22%22%22%0A%20%20%20%20%23%20%E8%BD%AC%E5%8C%96%E4%B8%BA%E6%9F%A5%E6%89%BE%E6%9C%80%E5%B7%A6%E4%B8%80%E4%B8%AA%20target%20%2B%201%0A%20%20%20%20i%20%3D%20binary_search_insertion%28nums,%20target%20%2B%201%29%0A%20%20%20%20%23%20j%20%E6%8C%87%E5%90%91%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%20target%20%EF%BC%8Ci%20%E6%8C%87%E5%90%91%E9%A6%96%E4%B8%AA%E5%A4%A7%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%0A%20%20%20%20j%20%3D%20i%20-%201%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%20-1%0A%20%20%20%20if%20j%20%3D%3D%20-1%20or%20nums%5Bj%5D%20!%3D%20target%3A%0A%20%20%20%20%20%20%20%20return%20-1%0A%20%20%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%B4%A2%E5%BC%95%20j%0A%20%20%20%20return%20j%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E5%B7%A6%E8%BE%B9%E7%95%8C%E5%92%8C%E5%8F%B3%E8%BE%B9%E7%95%8C%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_right_edge%28nums,%20target%29%0A%20%20%20%20print%28f%22%E6%9C%80%E5%8F%B3%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%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>
|
||||
|
||||
### 2. Transforming into an element search
|
||||
|
||||
We know that when the array does not contain `target`, $i$ and $j$ will eventually point to the first element greater and smaller than `target` respectively.
|
||||
|
||||
@@ -32,58 +32,43 @@ Therefore, at the end of the binary, it is certain that: $i$ points to the first
|
||||
|
||||
```python title="binary_search_insertion.py"
|
||||
def binary_search_insertion_simple(nums: list[int], target: int) -> int:
|
||||
"""二分查找插入点(无重复元素)"""
|
||||
i, j = 0, len(nums) - 1 # 初始化双闭区间 [0, n-1]
|
||||
"""Binary search for insertion point (no duplicate elements)"""
|
||||
i, j = 0, len(nums) - 1 # Initialize double closed interval [0, n-1]
|
||||
while i <= j:
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
m = (i + j) // 2 # Calculate midpoint index m
|
||||
if nums[m] < target:
|
||||
i = m + 1 # target 在区间 [m+1, j] 中
|
||||
i = m + 1 # Target is in interval [m+1, j]
|
||||
elif nums[m] > target:
|
||||
j = m - 1 # target 在区间 [i, m-1] 中
|
||||
j = m - 1 # Target is in interval [i, m-1]
|
||||
else:
|
||||
return m # 找到 target ,返回插入点 m
|
||||
# 未找到 target ,返回插入点 i
|
||||
return m # Found target, return insertion point m
|
||||
# Did not find target, return insertion point i
|
||||
return i
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search_insertion.cpp"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
int binarySearchInsertionSimple(vector<int> &nums, int target) {
|
||||
int i = 0, j = nums.size() - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search_insertion.java"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
/* Binary search for insertion point (no duplicate elements) */
|
||||
int binarySearchInsertionSimple(int[] nums, int target) {
|
||||
int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
int i = 0, j = nums.length - 1; // Initialize double closed interval [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
int m = i + (j - i) / 2; // Calculate midpoint index m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
i = m + 1; // Target is in interval [m+1, j]
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
j = m - 1; // Target is in interval [i, m-1]
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
return m; // Found target, return insertion point m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
// Did not find target, return insertion point i
|
||||
return i;
|
||||
}
|
||||
```
|
||||
@@ -91,228 +76,61 @@ Therefore, at the end of the binary, it is certain that: $i$ points to the first
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search_insertion.cs"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
int BinarySearchInsertionSimple(int[] nums, int target) {
|
||||
int i = 0, j = nums.Length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{binary_search_insertion}-[func]{BinarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search_insertion.go"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
func binarySearchInsertionSimple(nums []int, target int) int {
|
||||
// 初始化双闭区间 [0, n-1]
|
||||
i, j := 0, len(nums)-1
|
||||
for i <= j {
|
||||
// 计算中点索引 m
|
||||
m := i + (j-i)/2
|
||||
if nums[m] < target {
|
||||
// target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target {
|
||||
// target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
} else {
|
||||
// 找到 target ,返回插入点 m
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_insertion.swift"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
func binarySearchInsertionSimple(nums: [Int], target: Int) -> Int {
|
||||
// 初始化双闭区间 [0, n-1]
|
||||
var i = nums.startIndex
|
||||
var j = nums.endIndex - 1
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if nums[m] < target {
|
||||
i = m + 1 // target 在区间 [m+1, j] 中
|
||||
} else if nums[m] > target {
|
||||
j = m - 1 // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search_insertion.js"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
function binarySearchInsertionSimple(nums, target) {
|
||||
let i = 0,
|
||||
j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m, 使用 Math.floor() 向下取整
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search_insertion.ts"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
function binarySearchInsertionSimple(
|
||||
nums: Array<number>,
|
||||
target: number
|
||||
): number {
|
||||
let i = 0,
|
||||
j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m, 使用 Math.floor() 向下取整
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search_insertion.dart"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
int binarySearchInsertionSimple(List<int> nums, int target) {
|
||||
int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) ~/ 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search_insertion.rs"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
fn binary_search_insertion_simple(nums: &[i32], target: i32) -> i32 {
|
||||
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if nums[m as usize] < target {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if nums[m as usize] > target {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
i
|
||||
}
|
||||
[class]{}-[func]{binary_search_insertion_simple}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search_insertion.c"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
int binarySearchInsertionSimple(int *nums, int numSize, int target) {
|
||||
int i = 0, j = numSize - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m; // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search_insertion.kt"
|
||||
/* 二分查找插入点(无重复元素) */
|
||||
fun binarySearchInsertionSimple(nums: IntArray, target: Int): Int {
|
||||
var i = 0
|
||||
var j = nums.size - 1 // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
val m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1 // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1 // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
return m // 找到 target ,返回插入点 m
|
||||
}
|
||||
}
|
||||
// 未找到 target ,返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search_insertion.rb"
|
||||
### 二分查找插入点(无重复元素) ###
|
||||
def binary_search_insertion_simple(nums, target)
|
||||
# 初始化双闭区间 [0, n-1]
|
||||
i, j = 0, nums.length - 1
|
||||
|
||||
while i <= j
|
||||
# 计算中点索引 m
|
||||
m = (i + j) / 2
|
||||
|
||||
if nums[m] < target
|
||||
i = m + 1 # target 在区间 [m+1, j] 中
|
||||
elsif nums[m] > target
|
||||
j = m - 1 # target 在区间 [i, m-1] 中
|
||||
else
|
||||
return m # 找到 target ,返回插入点 m
|
||||
end
|
||||
end
|
||||
|
||||
i # 未找到 target ,返回插入点 i
|
||||
end
|
||||
[class]{}-[func]{binary_search_insertion_simple}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
@@ -321,11 +139,6 @@ Therefore, at the end of the binary, it is certain that: $i$ points to the first
|
||||
[class]{}-[func]{binarySearchInsertionSimple}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20binary_search_insertion_simple%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E6%97%A0%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20m%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%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%E6%97%A0%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%208,%2012,%2015,%2023,%2026,%2031,%2035%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_insertion_simple%28nums,%20target%29%0A%20%20%20%20print%28f%22%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=5&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%20binary_search_insertion_simple%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E6%97%A0%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20m%20%20%23%20%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20m%0A%20%20%20%20%23%20%E6%9C%AA%E6%89%BE%E5%88%B0%20target%20%EF%BC%8C%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%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%E6%97%A0%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%208,%2012,%2015,%2023,%2026,%2031,%2035%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_insertion_simple%28nums,%20target%29%0A%20%20%20%20print%28f%22%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=5&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
## 10.2.2 Case with duplicate elements
|
||||
|
||||
!!! question
|
||||
@@ -386,58 +199,43 @@ Even so, we can still keep the conditions expanded, as their logic is clearer an
|
||||
|
||||
```python title="binary_search_insertion.py"
|
||||
def binary_search_insertion(nums: list[int], target: int) -> int:
|
||||
"""二分查找插入点(存在重复元素)"""
|
||||
i, j = 0, len(nums) - 1 # 初始化双闭区间 [0, n-1]
|
||||
"""Binary search for insertion point (with duplicate elements)"""
|
||||
i, j = 0, len(nums) - 1 # Initialize double closed interval [0, n-1]
|
||||
while i <= j:
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
m = (i + j) // 2 # Calculate midpoint index m
|
||||
if nums[m] < target:
|
||||
i = m + 1 # target 在区间 [m+1, j] 中
|
||||
i = m + 1 # Target is in interval [m+1, j]
|
||||
elif nums[m] > target:
|
||||
j = m - 1 # target 在区间 [i, m-1] 中
|
||||
j = m - 1 # Target is in interval [i, m-1]
|
||||
else:
|
||||
j = m - 1 # 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
# 返回插入点 i
|
||||
j = m - 1 # First element less than target is in interval [i, m-1]
|
||||
# Return insertion point i
|
||||
return i
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title="binary_search_insertion.cpp"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
int binarySearchInsertion(vector<int> &nums, int target) {
|
||||
int i = 0, j = nums.size() - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="binary_search_insertion.java"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
/* Binary search for insertion point (with duplicate elements) */
|
||||
int binarySearchInsertion(int[] nums, int target) {
|
||||
int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
int i = 0, j = nums.length - 1; // Initialize double closed interval [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
int m = i + (j - i) / 2; // Calculate midpoint index m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
i = m + 1; // Target is in interval [m+1, j]
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
j = m - 1; // Target is in interval [i, m-1]
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
j = m - 1; // First element less than target is in interval [i, m-1]
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
// Return insertion point i
|
||||
return i;
|
||||
}
|
||||
```
|
||||
@@ -445,225 +243,61 @@ Even so, we can still keep the conditions expanded, as their logic is clearer an
|
||||
=== "C#"
|
||||
|
||||
```csharp title="binary_search_insertion.cs"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
int BinarySearchInsertion(int[] nums, int target) {
|
||||
int i = 0, j = nums.Length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{binary_search_insertion}-[func]{BinarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="binary_search_insertion.go"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
func binarySearchInsertion(nums []int, target int) int {
|
||||
// 初始化双闭区间 [0, n-1]
|
||||
i, j := 0, len(nums)-1
|
||||
for i <= j {
|
||||
// 计算中点索引 m
|
||||
m := i + (j-i)/2
|
||||
if nums[m] < target {
|
||||
// target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target {
|
||||
// target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
} else {
|
||||
// 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_insertion.swift"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
func binarySearchInsertion(nums: [Int], target: Int) -> Int {
|
||||
// 初始化双闭区间 [0, n-1]
|
||||
var i = nums.startIndex
|
||||
var j = nums.endIndex - 1
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if nums[m] < target {
|
||||
i = m + 1 // target 在区间 [m+1, j] 中
|
||||
} else if nums[m] > target {
|
||||
j = m - 1 // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1 // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="binary_search_insertion.js"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
function binarySearchInsertion(nums, target) {
|
||||
let i = 0,
|
||||
j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m, 使用 Math.floor() 向下取整
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="binary_search_insertion.ts"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
function binarySearchInsertion(nums: Array<number>, target: number): number {
|
||||
let i = 0,
|
||||
j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m, 使用 Math.floor() 向下取整
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="binary_search_insertion.dart"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
int binarySearchInsertion(List<int> nums, int target) {
|
||||
int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) ~/ 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="binary_search_insertion.rs"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
pub fn binary_search_insertion(nums: &[i32], target: i32) -> i32 {
|
||||
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
|
||||
while i <= j {
|
||||
let m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if nums[m as usize] < target {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if nums[m as usize] > target {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
i
|
||||
}
|
||||
[class]{}-[func]{binary_search_insertion}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="binary_search_insertion.c"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
int binarySearchInsertion(int *nums, int numSize, int target) {
|
||||
int i = 0, j = numSize - 1; // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
int m = i + (j - i) / 2; // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1; // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1; // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i;
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="binary_search_insertion.kt"
|
||||
/* 二分查找插入点(存在重复元素) */
|
||||
fun binarySearchInsertion(nums: IntArray, target: Int): Int {
|
||||
var i = 0
|
||||
var j = nums.size - 1 // 初始化双闭区间 [0, n-1]
|
||||
while (i <= j) {
|
||||
val m = i + (j - i) / 2 // 计算中点索引 m
|
||||
if (nums[m] < target) {
|
||||
i = m + 1 // target 在区间 [m+1, j] 中
|
||||
} else if (nums[m] > target) {
|
||||
j = m - 1 // target 在区间 [i, m-1] 中
|
||||
} else {
|
||||
j = m - 1 // 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
}
|
||||
}
|
||||
// 返回插入点 i
|
||||
return i
|
||||
}
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="binary_search_insertion.rb"
|
||||
### 二分查找插入点(存在重复元素) ###
|
||||
def binary_search_insertion(nums, target)
|
||||
# 初始化双闭区间 [0, n-1]
|
||||
i, j = 0, nums.length - 1
|
||||
|
||||
while i <= j
|
||||
# 计算中点索引 m
|
||||
m = (i + j) / 2
|
||||
|
||||
if nums[m] < target
|
||||
i = m + 1 # target 在区间 [m+1, j] 中
|
||||
elsif nums[m] > target
|
||||
j = m - 1 # target 在区间 [i, m-1] 中
|
||||
else
|
||||
j = m - 1 # 首个小于 target 的元素在区间 [i, m-1] 中
|
||||
end
|
||||
end
|
||||
|
||||
i # 返回插入点 i
|
||||
end
|
||||
[class]{}-[func]{binary_search_insertion}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
@@ -672,11 +306,6 @@ Even so, we can still keep the conditions expanded, as their logic is clearer an
|
||||
[class]{}-[func]{binarySearchInsertion}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_insertion%28nums,%20target%29%0A%20%20%20%20print%28f%22%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=5&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%20binary_search_insertion%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%E6%8F%92%E5%85%A5%E7%82%B9%EF%BC%88%E5%AD%98%E5%9C%A8%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%EF%BC%89%22%22%22%0A%20%20%20%20i,%20j%20%3D%200,%20len%28nums%29%20-%201%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E9%97%AD%E5%8C%BA%E9%97%B4%20%5B0,%20n-1%5D%0A%20%20%20%20while%20i%20%3C%3D%20j%3A%0A%20%20%20%20%20%20%20%20m%20%3D%20%28i%20%2B%20j%29%20//%202%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%20%20%20%20%20if%20nums%5Bm%5D%20%3C%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%3D%20m%20%2B%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bm%2B1,%20j%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20elif%20nums%5Bm%5D%20%3E%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20target%20%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20j%20%3D%20m%20-%201%20%20%23%20%E9%A6%96%E4%B8%AA%E5%B0%8F%E4%BA%8E%20target%20%E7%9A%84%E5%85%83%E7%B4%A0%E5%9C%A8%E5%8C%BA%E9%97%B4%20%5Bi,%20m-1%5D%20%E4%B8%AD%0A%20%20%20%20%23%20%E8%BF%94%E5%9B%9E%E6%8F%92%E5%85%A5%E7%82%B9%20i%0A%20%20%20%20return%20i%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%8C%85%E5%90%AB%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E7%9A%84%E6%95%B0%E7%BB%84%0A%20%20%20%20nums%20%3D%20%5B1,%203,%206,%206,%206,%206,%206,%2010,%2012,%2015%5D%0A%20%20%20%20%23%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E6%8F%92%E5%85%A5%E7%82%B9%0A%20%20%20%20target%20%3D%206%0A%20%20%20%20index%20%3D%20binary_search_insertion%28nums,%20target%29%0A%20%20%20%20print%28f%22%E5%85%83%E7%B4%A0%20%7Btarget%7D%20%E7%9A%84%E6%8F%92%E5%85%A5%E7%82%B9%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%BA%20%7Bindex%7D%22%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=5&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
!!! tip
|
||||
|
||||
The code in this section uses "closed intervals". Readers interested can implement the "left-closed right-open" method themselves.
|
||||
|
||||
@@ -24,8 +24,8 @@ The code is shown below:
|
||||
|
||||
```python title="two_sum.py"
|
||||
def two_sum_brute_force(nums: list[int], target: int) -> list[int]:
|
||||
"""方法一:暴力枚举"""
|
||||
# 两层循环,时间复杂度为 O(n^2)
|
||||
"""Method one: Brute force enumeration"""
|
||||
# Two-layer loop, time complexity is O(n^2)
|
||||
for i in range(len(nums) - 1):
|
||||
for j in range(i + 1, len(nums)):
|
||||
if nums[i] + nums[j] == target:
|
||||
@@ -36,27 +36,16 @@ The code is shown below:
|
||||
=== "C++"
|
||||
|
||||
```cpp title="two_sum.cpp"
|
||||
/* 方法一:暴力枚举 */
|
||||
vector<int> twoSumBruteForce(vector<int> &nums, int target) {
|
||||
int size = nums.size();
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
if (nums[i] + nums[j] == target)
|
||||
return {i, j};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="two_sum.java"
|
||||
/* 方法一:暴力枚举 */
|
||||
/* Method one: Brute force enumeration */
|
||||
int[] twoSumBruteForce(int[] nums, int target) {
|
||||
int size = nums.length;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
// Two-layer loop, time complexity is O(n^2)
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
if (nums[i] + nums[j] == target)
|
||||
@@ -70,202 +59,69 @@ The code is shown below:
|
||||
=== "C#"
|
||||
|
||||
```csharp title="two_sum.cs"
|
||||
/* 方法一:暴力枚举 */
|
||||
int[] TwoSumBruteForce(int[] nums, int target) {
|
||||
int size = nums.Length;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
if (nums[i] + nums[j] == target)
|
||||
return [i, j];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{two_sum}-[func]{TwoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="two_sum.go"
|
||||
/* 方法一:暴力枚举 */
|
||||
func twoSumBruteForce(nums []int, target int) []int {
|
||||
size := len(nums)
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for i := 0; i < size-1; i++ {
|
||||
for j := i + 1; j < size; j++ {
|
||||
if nums[i]+nums[j] == target {
|
||||
return []int{i, j}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="two_sum.swift"
|
||||
/* 方法一:暴力枚举 */
|
||||
func twoSumBruteForce(nums: [Int], target: Int) -> [Int] {
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for i in nums.indices.dropLast() {
|
||||
for j in nums.indices.dropFirst(i + 1) {
|
||||
if nums[i] + nums[j] == target {
|
||||
return [i, j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return [0]
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="two_sum.js"
|
||||
/* 方法一:暴力枚举 */
|
||||
function twoSumBruteForce(nums, target) {
|
||||
const n = nums.length;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (let i = 0; i < n; i++) {
|
||||
for (let j = i + 1; j < n; j++) {
|
||||
if (nums[i] + nums[j] === target) {
|
||||
return [i, j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="two_sum.ts"
|
||||
/* 方法一:暴力枚举 */
|
||||
function twoSumBruteForce(nums: number[], target: number): number[] {
|
||||
const n = nums.length;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (let i = 0; i < n; i++) {
|
||||
for (let j = i + 1; j < n; j++) {
|
||||
if (nums[i] + nums[j] === target) {
|
||||
return [i, j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="two_sum.dart"
|
||||
/* 方法一: 暴力枚举 */
|
||||
List<int> twoSumBruteForce(List<int> nums, int target) {
|
||||
int size = nums.length;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (var i = 0; i < size - 1; i++) {
|
||||
for (var j = i + 1; j < size; j++) {
|
||||
if (nums[i] + nums[j] == target) return [i, j];
|
||||
}
|
||||
}
|
||||
return [0];
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="two_sum.rs"
|
||||
/* 方法一:暴力枚举 */
|
||||
pub fn two_sum_brute_force(nums: &Vec<i32>, target: i32) -> Option<Vec<i32>> {
|
||||
let size = nums.len();
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for i in 0..size - 1 {
|
||||
for j in i + 1..size {
|
||||
if nums[i] + nums[j] == target {
|
||||
return Some(vec![i as i32, j as i32]);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
[class]{}-[func]{two_sum_brute_force}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="two_sum.c"
|
||||
/* 方法一:暴力枚举 */
|
||||
int *twoSumBruteForce(int *nums, int numsSize, int target, int *returnSize) {
|
||||
for (int i = 0; i < numsSize; ++i) {
|
||||
for (int j = i + 1; j < numsSize; ++j) {
|
||||
if (nums[i] + nums[j] == target) {
|
||||
int *res = malloc(sizeof(int) * 2);
|
||||
res[0] = i, res[1] = j;
|
||||
*returnSize = 2;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
*returnSize = 0;
|
||||
return NULL;
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="two_sum.kt"
|
||||
/* 方法一:暴力枚举 */
|
||||
fun twoSumBruteForce(nums: IntArray, target: Int): IntArray {
|
||||
val size = nums.size
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
for (i in 0..<size - 1) {
|
||||
for (j in i + 1..<size) {
|
||||
if (nums[i] + nums[j] == target) return intArrayOf(i, j)
|
||||
}
|
||||
}
|
||||
return IntArray(0)
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="two_sum.rb"
|
||||
### 方法一:暴力枚举 ###
|
||||
def two_sum_brute_force(nums, target)
|
||||
# 两层循环,时间复杂度为 O(n^2)
|
||||
for i in 0...(nums.length - 1)
|
||||
for j in (i + 1)...nums.length
|
||||
return [i, j] if nums[i] + nums[j] == target
|
||||
end
|
||||
end
|
||||
|
||||
[]
|
||||
end
|
||||
[class]{}-[func]{two_sum_brute_force}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="two_sum.zig"
|
||||
// 方法一:暴力枚举
|
||||
fn twoSumBruteForce(nums: []i32, target: i32) ?[2]i32 {
|
||||
var size: usize = nums.len;
|
||||
var i: usize = 0;
|
||||
// 两层循环,时间复杂度为 O(n^2)
|
||||
while (i < size - 1) : (i += 1) {
|
||||
var j = i + 1;
|
||||
while (j < size) : (j += 1) {
|
||||
if (nums[i] + nums[j] == target) {
|
||||
return [_]i32{@intCast(i), @intCast(j)};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 441px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20two_sum_brute_force%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20list%5Bint%5D%3A%0A%20%20%20%20%22%22%22%E6%96%B9%E6%B3%95%E4%B8%80%EF%BC%9A%E6%9A%B4%E5%8A%9B%E6%9E%9A%E4%B8%BE%22%22%22%0A%20%20%20%20%23%20%E4%B8%A4%E5%B1%82%E5%BE%AA%E7%8E%AF%EF%BC%8C%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%5E2%29%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%20-%201%29%3A%0A%20%20%20%20%20%20%20%20for%20j%20in%20range%28i%20%2B%201,%20len%28nums%29%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20nums%5Bi%5D%20%2B%20nums%5Bj%5D%20%3D%3D%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Bi,%20j%5D%0A%20%20%20%20return%20%5B%5D%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20nums%20%3D%20%5B2,%207,%2011,%2015%5D%0A%20%20%20%20target%20%3D%2013%0A%20%20%20%20res%20%3D%20two_sum_brute_force%28nums,%20target%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=5&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%20two_sum_brute_force%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20list%5Bint%5D%3A%0A%20%20%20%20%22%22%22%E6%96%B9%E6%B3%95%E4%B8%80%EF%BC%9A%E6%9A%B4%E5%8A%9B%E6%9E%9A%E4%B8%BE%22%22%22%0A%20%20%20%20%23%20%E4%B8%A4%E5%B1%82%E5%BE%AA%E7%8E%AF%EF%BC%8C%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%5E2%29%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%20-%201%29%3A%0A%20%20%20%20%20%20%20%20for%20j%20in%20range%28i%20%2B%201,%20len%28nums%29%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20nums%5Bi%5D%20%2B%20nums%5Bj%5D%20%3D%3D%20target%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Bi,%20j%5D%0A%20%20%20%20return%20%5B%5D%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20nums%20%3D%20%5B2,%207,%2011,%2015%5D%0A%20%20%20%20target%20%3D%2013%0A%20%20%20%20res%20%3D%20two_sum_brute_force%28nums,%20target%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=5&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
This method has a time complexity of $O(n^2)$ and a space complexity of $O(1)$, which is very time-consuming with large data volumes.
|
||||
|
||||
## 10.4.2 Hash search: trading space for time
|
||||
@@ -292,10 +148,10 @@ The implementation code is shown below, requiring only a single loop:
|
||||
|
||||
```python title="two_sum.py"
|
||||
def two_sum_hash_table(nums: list[int], target: int) -> list[int]:
|
||||
"""方法二:辅助哈希表"""
|
||||
# 辅助哈希表,空间复杂度为 O(n)
|
||||
"""Method two: Auxiliary hash table"""
|
||||
# Auxiliary hash table, space complexity is O(n)
|
||||
dic = {}
|
||||
# 单层循环,时间复杂度为 O(n)
|
||||
# Single-layer loop, time complexity is O(n)
|
||||
for i in range(len(nums)):
|
||||
if target - nums[i] in dic:
|
||||
return [dic[target - nums[i]], i]
|
||||
@@ -306,31 +162,18 @@ The implementation code is shown below, requiring only a single loop:
|
||||
=== "C++"
|
||||
|
||||
```cpp title="two_sum.cpp"
|
||||
/* 方法二:辅助哈希表 */
|
||||
vector<int> twoSumHashTable(vector<int> &nums, int target) {
|
||||
int size = nums.size();
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
unordered_map<int, int> dic;
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (dic.find(target - nums[i]) != dic.end()) {
|
||||
return {dic[target - nums[i]], i};
|
||||
}
|
||||
dic.emplace(nums[i], i);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="two_sum.java"
|
||||
/* 方法二:辅助哈希表 */
|
||||
/* Method two: Auxiliary hash table */
|
||||
int[] twoSumHashTable(int[] nums, int target) {
|
||||
int size = nums.length;
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
// Auxiliary hash table, space complexity is O(n)
|
||||
Map<Integer, Integer> dic = new HashMap<>();
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
// Single-layer loop, time complexity is O(n)
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (dic.containsKey(target - nums[i])) {
|
||||
return new int[] { dic.get(target - nums[i]), i };
|
||||
@@ -344,244 +187,71 @@ The implementation code is shown below, requiring only a single loop:
|
||||
=== "C#"
|
||||
|
||||
```csharp title="two_sum.cs"
|
||||
/* 方法二:辅助哈希表 */
|
||||
int[] TwoSumHashTable(int[] nums, int target) {
|
||||
int size = nums.Length;
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
Dictionary<int, int> dic = [];
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (dic.ContainsKey(target - nums[i])) {
|
||||
return [dic[target - nums[i]], i];
|
||||
}
|
||||
dic.Add(nums[i], i);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{two_sum}-[func]{TwoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
```go title="two_sum.go"
|
||||
/* 方法二:辅助哈希表 */
|
||||
func twoSumHashTable(nums []int, target int) []int {
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
hashTable := map[int]int{}
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for idx, val := range nums {
|
||||
if preIdx, ok := hashTable[target-val]; ok {
|
||||
return []int{preIdx, idx}
|
||||
}
|
||||
hashTable[val] = idx
|
||||
}
|
||||
return nil
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="two_sum.swift"
|
||||
/* 方法二:辅助哈希表 */
|
||||
func twoSumHashTable(nums: [Int], target: Int) -> [Int] {
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
var dic: [Int: Int] = [:]
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for i in nums.indices {
|
||||
if let j = dic[target - nums[i]] {
|
||||
return [j, i]
|
||||
}
|
||||
dic[nums[i]] = i
|
||||
}
|
||||
return [0]
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="two_sum.js"
|
||||
/* 方法二:辅助哈希表 */
|
||||
function twoSumHashTable(nums, target) {
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
let m = {};
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
if (m[target - nums[i]] !== undefined) {
|
||||
return [m[target - nums[i]], i];
|
||||
} else {
|
||||
m[nums[i]] = i;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title="two_sum.ts"
|
||||
/* 方法二:辅助哈希表 */
|
||||
function twoSumHashTable(nums: number[], target: number): number[] {
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
let m: Map<number, number> = new Map();
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
let index = m.get(target - nums[i]);
|
||||
if (index !== undefined) {
|
||||
return [index, i];
|
||||
} else {
|
||||
m.set(nums[i], i);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="two_sum.dart"
|
||||
/* 方法二: 辅助哈希表 */
|
||||
List<int> twoSumHashTable(List<int> nums, int target) {
|
||||
int size = nums.length;
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
Map<int, int> dic = HashMap();
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (var i = 0; i < size; i++) {
|
||||
if (dic.containsKey(target - nums[i])) {
|
||||
return [dic[target - nums[i]]!, i];
|
||||
}
|
||||
dic.putIfAbsent(nums[i], () => i);
|
||||
}
|
||||
return [0];
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
```rust title="two_sum.rs"
|
||||
/* 方法二:辅助哈希表 */
|
||||
pub fn two_sum_hash_table(nums: &Vec<i32>, target: i32) -> Option<Vec<i32>> {
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
let mut dic = HashMap::new();
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (i, num) in nums.iter().enumerate() {
|
||||
match dic.get(&(target - num)) {
|
||||
Some(v) => return Some(vec![*v as i32, i as i32]),
|
||||
None => dic.insert(num, i as i32),
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
[class]{}-[func]{two_sum_hash_table}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="two_sum.c"
|
||||
/* 哈希表 */
|
||||
typedef struct {
|
||||
int key;
|
||||
int val;
|
||||
UT_hash_handle hh; // 基于 uthash.h 实现
|
||||
} HashTable;
|
||||
[class]{HashTable}-[func]{}
|
||||
|
||||
/* 哈希表查询 */
|
||||
HashTable *find(HashTable *h, int key) {
|
||||
HashTable *tmp;
|
||||
HASH_FIND_INT(h, &key, tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* 哈希表元素插入 */
|
||||
void insert(HashTable *h, int key, int val) {
|
||||
HashTable *t = find(h, key);
|
||||
if (t == NULL) {
|
||||
HashTable *tmp = malloc(sizeof(HashTable));
|
||||
tmp->key = key, tmp->val = val;
|
||||
HASH_ADD_INT(h, key, tmp);
|
||||
} else {
|
||||
t->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* 方法二:辅助哈希表 */
|
||||
int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) {
|
||||
HashTable *hashtable = NULL;
|
||||
for (int i = 0; i < numsSize; i++) {
|
||||
HashTable *t = find(hashtable, target - nums[i]);
|
||||
if (t != NULL) {
|
||||
int *res = malloc(sizeof(int) * 2);
|
||||
res[0] = t->val, res[1] = i;
|
||||
*returnSize = 2;
|
||||
return res;
|
||||
}
|
||||
insert(hashtable, nums[i], i);
|
||||
}
|
||||
*returnSize = 0;
|
||||
return NULL;
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title="two_sum.kt"
|
||||
/* 方法二:辅助哈希表 */
|
||||
fun twoSumHashTable(nums: IntArray, target: Int): IntArray {
|
||||
val size = nums.size
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
val dic = HashMap<Int, Int>()
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
for (i in 0..<size) {
|
||||
if (dic.containsKey(target - nums[i])) {
|
||||
return intArrayOf(dic[target - nums[i]]!!, i)
|
||||
}
|
||||
dic[nums[i]] = i
|
||||
}
|
||||
return IntArray(0)
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title="two_sum.rb"
|
||||
### 方法二:辅助哈希表 ###
|
||||
def two_sum_hash_table(nums, target)
|
||||
# 辅助哈希表,空间复杂度为 O(n)
|
||||
dic = {}
|
||||
# 单层循环,时间复杂度为 O(n)
|
||||
for i in 0...nums.length
|
||||
return [dic[target - nums[i]], i] if dic.has_key?(target - nums[i])
|
||||
|
||||
dic[nums[i]] = i
|
||||
end
|
||||
|
||||
[]
|
||||
end
|
||||
[class]{}-[func]{two_sum_hash_table}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="two_sum.zig"
|
||||
// 方法二:辅助哈希表
|
||||
fn twoSumHashTable(nums: []i32, target: i32) !?[2]i32 {
|
||||
var size: usize = nums.len;
|
||||
// 辅助哈希表,空间复杂度为 O(n)
|
||||
var dic = std.AutoHashMap(i32, i32).init(std.heap.page_allocator);
|
||||
defer dic.deinit();
|
||||
var i: usize = 0;
|
||||
// 单层循环,时间复杂度为 O(n)
|
||||
while (i < size) : (i += 1) {
|
||||
if (dic.contains(target - nums[i])) {
|
||||
return [_]i32{dic.get(target - nums[i]).?, @intCast(i)};
|
||||
}
|
||||
try dic.put(nums[i], @intCast(i));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
??? pythontutor "Code Visualization"
|
||||
|
||||
<div style="height: 477px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20two_sum_hash_table%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20list%5Bint%5D%3A%0A%20%20%20%20%22%22%22%E6%96%B9%E6%B3%95%E4%BA%8C%EF%BC%9A%E8%BE%85%E5%8A%A9%E5%93%88%E5%B8%8C%E8%A1%A8%22%22%22%0A%20%20%20%20%23%20%E8%BE%85%E5%8A%A9%E5%93%88%E5%B8%8C%E8%A1%A8%EF%BC%8C%E7%A9%BA%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%29%0A%20%20%20%20dic%20%3D%20%7B%7D%0A%20%20%20%20%23%20%E5%8D%95%E5%B1%82%E5%BE%AA%E7%8E%AF%EF%BC%8C%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%29%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%29%3A%0A%20%20%20%20%20%20%20%20if%20target%20-%20nums%5Bi%5D%20in%20dic%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Bdic%5Btarget%20-%20nums%5Bi%5D%5D,%20i%5D%0A%20%20%20%20%20%20%20%20dic%5Bnums%5Bi%5D%5D%20%3D%20i%0A%20%20%20%20return%20%5B%5D%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20nums%20%3D%20%5B2,%207,%2011,%2015%5D%0A%20%20%20%20target%20%3D%2013%0A%20%20%20%20res%20%3D%20two_sum_hash_table%28nums,%20target%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=5&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%20two_sum_hash_table%28nums%3A%20list%5Bint%5D,%20target%3A%20int%29%20-%3E%20list%5Bint%5D%3A%0A%20%20%20%20%22%22%22%E6%96%B9%E6%B3%95%E4%BA%8C%EF%BC%9A%E8%BE%85%E5%8A%A9%E5%93%88%E5%B8%8C%E8%A1%A8%22%22%22%0A%20%20%20%20%23%20%E8%BE%85%E5%8A%A9%E5%93%88%E5%B8%8C%E8%A1%A8%EF%BC%8C%E7%A9%BA%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%29%0A%20%20%20%20dic%20%3D%20%7B%7D%0A%20%20%20%20%23%20%E5%8D%95%E5%B1%82%E5%BE%AA%E7%8E%AF%EF%BC%8C%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E4%B8%BA%20O%28n%29%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%29%3A%0A%20%20%20%20%20%20%20%20if%20target%20-%20nums%5Bi%5D%20in%20dic%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Bdic%5Btarget%20-%20nums%5Bi%5D%5D,%20i%5D%0A%20%20%20%20%20%20%20%20dic%5Bnums%5Bi%5D%5D%20%3D%20i%0A%20%20%20%20return%20%5B%5D%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20nums%20%3D%20%5B2,%207,%2011,%2015%5D%0A%20%20%20%20target%20%3D%2013%0A%20%20%20%20res%20%3D%20two_sum_hash_table%28nums,%20target%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=5&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
|
||||
|
||||
This method reduces the time complexity from $O(n^2)$ to $O(n)$ by using hash search, greatly improving the running efficiency.
|
||||
|
||||
As it requires maintaining an additional hash table, the space complexity is $O(n)$. **Nevertheless, this method has a more balanced time-space efficiency overall, making it the optimal solution for this problem**.
|
||||
|
||||
Reference in New Issue
Block a user