数组 - 34. 在排序数组中查找元素的第一个和最后一个位置(C#和C实现)
题目描述
给定一个按升序排序的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的起始位置和结束位置。如果目标值不在数组中,则返回 [-1, -1]。
解题思路
-
该问题可以通过两次二分查找来解决。第一次二分查找用于找到目标值的起始位置,第二次二分查找用于找到目标值的结束位置。
-
定义两个变量 left 和 right,初始值分别为 0 和 nums 数组的长度减一。
-
第一次二分查找,找到目标值的起始位置。循环条件为 left <= right :
- 计算中间位置 mid,通过left + (right - left) / 2 求得。
- 如果 nums[mid] 大于目标值 target,则更新 right 为 mid - 1,继续向左查找。
- 如果 nums[mid] 小于目标值 target,则更新 left 为 mid + 1,继续向右查找。
- 如果 nums[mid] 等于目标值 target,则更新 right 为 mid - 1,继续向左查找。
-
进行第二次二分查找,找到目标值的结束位置。重置变量 left 为 0,right 为 nums 数组的长度减一。
循环条件为 left <= right 。- 计算中间位置 mid,通过left + (right - left) / 2 求得。
- 如果 nums[mid] 大于目标值 target,则更新 right 为 mid - 1,继续向左查找。
- 如果 nums[mid] 小于目标值 target,则更新 left为 mid + 1,继续向右查找。
- 如果 nums[mid] 等于目标值 target,则更新 left为 mid + 1,继续向右查找。
返回结果 [left, right ],即为目标值在数组中的起始位置和结束位置。
解题实现
C#
public int[] SearchRange(int[] nums, int target)
{
int[] result = { -1, -1 };
int left = 0;
int right = nums.Length - 1;
// 寻找起始位置
while (left <= right)
{
int mid = left + (right - left >> 1);
if (nums[mid] > target)
{
right = mid - 1;
}
else if (nums[mid] < target)
{
left = mid + 1;
}
else
{
result[0] = mid;
right = mid - 1; // 继续向左查找
}
}
// 寻找结束位置
left = 0;
end = nums.Length - 1;
while (left <= right)
{
int mid = left + (right - left >> 1);
if (nums[mid] > target)
{
right = mid - 1;
}
else if (nums[mid] < target)
{
left = mid + 1;
}
else
{
result[1] = mid;
left = mid + 1; // 继续向右查找
}
}
return result;
}
C
int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
int* result = (int*)malloc(2 * sizeof(int));
result[0] = -1;
result[1] = -1;
int left = 0;
int right = numsSize - 1;
// 寻找起始位置
while (left <= right)
{
int mid = left + (right - left) / 2;
if (nums[mid] > target)
{
right = mid - 1;
}
else if (nums[mid] < target)
{
left = mid + 1;
}
else
{
result[0] = mid;
right = mid - 1; // 继续向左查找
}
}
// 寻找结束位置
left = 0;
end = numsSize - 1;
while (left <= end)
{
int mid = left + (right - left) / 2;
if (nums[mid] > target)
{
right = mid - 1;
}
else if (nums[mid] < target)
{
left = mid + 1;
}
else
{
result[1] = mid;
left = mid + 1; // 继续向右查找
}
}
*returnSize = 2;
return result;
}
复杂度分析
- 时间复杂度:O(log n),其中 n 是数组的长度。每次二分查找可以将查找范围缩小一半,因此时间复杂度为对数级别。
- 空间复杂度:O(1)。除了返回的结果数组外,算法的额外空间复杂度是常数级别的。
参与点评
读者朋友们,如果您在阅读过程中,对文章的质量、易理解性有任何建议,欢迎在评论区指出,我会认真改进。