【每日算法】搜索插入位置 LeetCode
这段代码实现了一个高效的二分查找算法,用于在有序数组中查找目标值的插入位置。
public int SearchInsert(int[] nums, int target){if (nums == null || nums.Length == 0)return 0;int left = 0;int right = nums.Length - 1;while (left <= right){//避免整数溢出int mid = left + (right - left) / 2;if (nums[mid] == target){return mid;}else if (nums[mid] < target){left = mid + 1;}else{right = mid - 1;}}return left;}
以下是逐步解析:
1. 方法功能
- 输入:一个升序排列的整数数组
nums
和目标值target
。 - 输出:
- 如果
target
存在于数组中,返回其索引。 - 如果
target
不存在,返回它应该插入的位置(保持数组有序)。
- 如果
2. 代码逐行解析
(1) 边界检查
if (nums == null || nums.Length == 0)return 0;
- 作用:处理空数组或
null
输入。 - 逻辑:如果数组为空,
target
应插入到索引0
的位置。
(2) 初始化指针
int left = 0;
int right = nums.Length - 1;
- 作用:初始化二分查找的左右边界。
left
:搜索区间的起始索引(初始为0
)。right
:搜索区间的结束索引(初始为数组最后一个元素的索引)。
(3) 二分查找循环
while (left <= right)
- 条件:当
left <= right
时继续搜索,确保搜索区间有效。
(4) 计算中间索引
int mid = left + (right - left) / 2;
- 作用:计算当前搜索区间的中间索引。
- 优化:使用
left + (right - left) / 2
而非(left + right) / 2
,避免整数溢出。
(5) 比较中间值与目标值
Csharp
if (nums[mid] == target)
{return mid;
}
- 逻辑:如果中间值等于
target
,直接返回其索引。
(6) 调整搜索区间
else if (nums[mid] < target)
{left = mid + 1;
}
else
{right = mid - 1;
}
- 逻辑:
- 如果中间值小于
target
,说明target
在右半区间,将left
移动到mid + 1
。 - 如果中间值大于
target
,说明target
在左半区间,将right
移动到mid - 1
。
- 如果中间值小于
(7) 返回插入位置
return left;
- 作用:如果未找到
target
,left
指向第一个大于target
的元素位置,即插入位置。
3. 关键点分析
(1) 为什么返回 left
?
- 二分查找结束时,
left
和right
的关系为left = right + 1
。 left
的位置是target
应该插入的位置(保持数组有序)。
(2) 时间复杂度
- O(log n):每次迭代将搜索区间减半。
(3) 空间复杂度
- O(1):仅使用常数级别的额外空间。
4. 示例验证
示例 1:目标值存在
int[] nums = {1, 3, 5, 7};
int target = 5;
// 输出:2(5的索引为2)
示例 2:目标值不存在
int[] nums = {1, 3, 5, 7};
int target = 4;
// 输出:2(4应插入到索引2的位置)
示例 3:目标值大于所有元素
int[] nums = {1, 3, 5, 7};
int target = 8;
// 输出:4(8应插入到末尾)
示例 4:空数组
int[] nums = {};
int target = 1;
// 输出:0
5. 总结
- 高效性:利用二分查找快速定位目标值或插入位置。
- 鲁棒性:显式处理空数组和整数溢出问题。
- 通用性:适用于所有升序排列的数组场景。