-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp34.rs
99 lines (88 loc) · 3.06 KB
/
p34.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#[cfg(test)]
mod tests {
use super::method1::search_range;
#[test]
fn test() {
let v1: Vec<i32> = vec![5, 7, 7, 8, 8, 8, 10, 12, 15];
search_range(v1, 8);
let v1: Vec<i32> = vec![5, 7, 7, 8, 8, 10];
assert_eq!(search_range(v1, 8), vec![3, 4]);
let v2: Vec<i32> = vec![5, 7, 7, 8, 8, 10];
assert_eq!(search_range(v2, 6), vec![-1, -1]);
let v3: Vec<i32> = vec![];
assert_eq!(search_range(v3, 0), vec![-1, -1])
}
}
#[allow(unused)]
mod method1 {
// 尽可能往左找的二分查找,也叫lower_bound
pub fn binary_search(nums: &Vec<i32>, target: i32) -> usize {
let mut left: usize = 0;
let mut right: usize = nums.len();
// [left, right)
while left < right {
let mid: usize = left + (right - left) / 2;
if nums[mid] < target {
left = mid + 1;
} else {
right = mid;
}
}
// left = right,return任意一个
left
}
// 找下界(>=target)等同于找第一个>=target的位置
// 找上界(<=target)等同于找第一个>=(target+1)的位置,然后-1的位置
// 因此,无论是找下界还是上界,都可以用lower_bound的二分查找解决
pub fn search_range(nums: Vec<i32>, target: i32) -> Vec<i32> {
let start: usize = binary_search(&nums, target);
if start == nums.len() || nums[start as usize] != target {
return vec![-1, -1];
}
let end: usize = binary_search(&nums, target + 1) - 1;
vec![start as i32, end as i32]
}
}
#[allow(unused)]
mod method2 {
pub fn search_range(nums: Vec<i32>, target: i32) -> Vec<i32> {
let l: usize = find_left(&nums, target);
let r: usize = find_right(&nums, target);
if l <= r && r < nums.len() && nums[l] == target && nums[r] == target {
return vec![l as i32, r as i32];
} else {
return vec![-1, -1];
}
}
// 由于数组存在重复元素,因此关键在于,找到target后不能返回,而是要继续往左或右找另一个target
pub fn find_right(nums: &Vec<i32>, target: i32) -> usize {
let (mut l, mut r, mut ans) = (0_usize, nums.len(), nums.len());
// [l, r)
while l < r {
let m: usize = l + (r - l) / 2;
// <= 缩左边界,尽可能往右找
if nums[m] <= target {
l = m + 1;
ans = m; // 标记尽可能右的答案
} else {
r = m;
}
}
ans
}
pub fn find_left(nums: &Vec<i32>, target: i32) -> usize {
let (mut l, mut r, mut ans) = (0_usize, nums.len(), nums.len());
// [l, r)
while l < r {
let m: usize = l + (r - l) / 2;
// >= 缩右边界,尽可能往左找
if nums[m] < target {
l = m + 1;
} else {
r = m;
ans = m; // 标记尽可能左的答案
}
}
ans
}
}