曾经找实习的过程中,某使用 C++ 的小厂对我进行八股文拷打后考了这道题的类型题型。
今天的题目:
题目描述:
题号:34
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
解题思路:
思路一:两次二分查找分别找出左右边界
-
可以使用两次二分查找来分别找到目标值的第一个位置和最后一个位置。
-
第一次二分查找用于找到目标值的任意一个位置(如果存在的话)。如果不存在,则直接返回
[-1, -1]
。 -
第二次二分查找用于在第一次找到的位置基础上,向左搜索找到第一个位置,向右搜索找到最后一个位置。
时间复杂度:O(log n)
空间复杂度:O(1)
C++
// C++
class Solution {
int findFirstPosition(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
int firstPosition = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
firstPosition = mid;
right = mid - 1; // 继续向左搜索
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return firstPosition;
}
int findLastPosition(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
int lastPosition = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
lastPosition = mid;
left = mid + 1; // 继续向右搜索
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return lastPosition;
}
public:
vector<int> searchRange(vector<int>& nums, int target) {
int firstPosition = findFirstPosition(nums, target);
if (firstPosition == -1) {
return {-1, -1};
}
int lastPosition = findLastPosition(nums, target);
return {firstPosition, lastPosition};
}
};
go
// go
func searchRange(nums []int, target int) []int {
firstPosition := findFirstPosition(nums, target)
if firstPosition == -1 {
return []int{-1, -1}
}
lastPosition := findLastPosition(nums, target)
return []int{firstPosition, lastPosition}
}
func findFirstPosition(nums []int, target int) int {
left, right := 0, len(nums)-1
firstPosition := -1
for left <= right {
mid := left + (right-left)/2
if nums[mid] == target {
firstPosition = mid
right = mid - 1 // 继续向左搜索
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return firstPosition
}
func findLastPosition(nums []int, target int) int {
left, right := 0, len(nums)-1
lastPosition := -1
for left <= right {
mid := left + (right-left)/2
if nums[mid] == target {
lastPosition = mid
left = mid + 1 // 继续向右搜索
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return lastPosition
}