勘误一下,upper_bound的作用是找到第一个 > target的元素,而不是以前认为的小于或者等于target的最后一个元素。
lower_bound和upper_bound是c++里的二分查找函数,lower_bound找的是集合中第一个大于等于target的下标; upper_bound则相反,找的是第一个大于target的元素的下标。
实现的话也是用二分法,区别在于当找到等于的元素以后,不能马上退出循环,而是需要在另外一半的元素中继续搜索,直到搜索区间的长度收缩为1。有一个比较坑的地方在于Rust只能用usize,也就是u64作为数组下标,所以这里的left <= right有可能因为right - 1溢出,而无法退出循环。需要额外判断right = 0的情况。
let lower_bound = |nums: &Vec<i32>, target: i32| {
let (mut left, mut right) = (0, nums.len() - 1);
let mut res = right;
if nums.len() == 0 || nums[res] < target {
return usize::MAX;
}
while left <= right {
let mid = (left + right) / 2;
if nums[mid] == target {
res = usize::min(res, mid);
}
if nums[mid] >= target {
if mid == 0 {
break;
}
right = mid - 1;
} else {
left = mid + 1;
}
}
res
};