35. 搜索插入位置 - 力扣(LeetCode)

基础知识要求:

Java:方法、while循环、if else语句、数组

Python: 方法、while循环、if else语句、列表

题目: 

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

 

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

 

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

思路解析:

这个问题是一个典型的二分查找问题,但有一个额外的要求:如果目标值不存在于数组中,需要返回它应该被插入的位置。这意味着我们不仅要找到目标值是否存在于数组中,还要找到它应该被插入的位置,即使它不存在。

以下是解决这个问题的思路:

  1. 初始化搜索边界:将搜索的左边界 left 设置为数组的起始位置(索引0),将右边界 right 设置为数组的最后一个位置(索引len(nums) - 1)。

  2. 进行二分查找

    • 计算中间位置的索引 mid,使用 mid = left + (right - left) / 2(整除以避免整数溢出)。
    • 比较 nums[mid] 和 target
      • 如果 nums[mid] == target,则找到了目标值,直接返回 mid
      • 如果 nums[mid] < target,则目标值(如果存在)一定在 mid 的右侧,更新 left = mid + 1
      • 如果 nums[mid] > target,则目标值(如果存在)一定在 mid 的左侧或就是 mid(但由于我们已经检查了 mid,所以知道它不等于 target),更新 right = mid - 1
  3. 处理目标值不存在的情况

    • 如果循环结束后仍未找到目标值(即 left > right),则目标值应该被插入在 left 的位置。这是因为在最后一次迭代中,nums[mid] 必然大于 target,且 mid 被更新为了 right(即 mid - 1),而 left 保持不变。因此,left 的位置是第一个大于 target 的元素的位置,也是 target 应该被插入的位置。
  4. 返回结果:返回 left 作为结果,它要么是目标值的索引,要么是目标值应该被插入的位置。

这个算法的关键在于理解二分查找过程中如何更新 left 和 right,以及在何时知道目标值不存在于数组中,并确定其应该被插入的位置。

Java代码示例:

public class Solution {  
      
    /**  
     * 在有序数组中查找目标值,如果不存在则返回应该插入的位置  
     *  
     * @param nums 有序数组  
     * @param target 目标值  
     * @return 目标值的索引(如果存在),否则为应该插入的位置  
     */  
    public int searchInsert(int[] nums, int target) {  
        int left = 0;  // 初始化左边界为数组起始位置  
        int right = nums.length - 1;  // 初始化右边界为数组末尾位置  
  
        // 当左边界小于等于右边界时,进行二分查找  
        while (left <= right) {  
            // 防止溢出,计算中间索引位置  
            int mid = left + (right - left) / 2;  
  
            // 如果中间元素等于目标值,返回其索引  
            if (nums[mid] == target) {  
                return mid;  
            // 如果中间元素小于目标值,说明目标值(如果存在)一定在mid的右侧,更新左边界  
            } else if (nums[mid] < target) {  
                left = mid + 1;  
            // 如果中间元素大于目标值,说明目标值(如果存在)一定在mid的左侧或就是mid(但已经检查过mid不等于target),更新右边界  
            } else {  
                right = mid - 1;  
            }  
        }  
  
        // 如果循环结束,说明目标值不存在于数组中,left将会是target应该被插入的位置  
        // 这是因为当left > right时,left指向了下一个应该被插入的位置  
        return left;  
    }  
  
    /**  
     * 主方法,用于测试searchInsert方法  
     *  
     * @param args 命令行参数(本例中未使用)  
     */  
    public static void main(String[] args) {  
        Solution solution = new Solution();  
        int[] nums = {1, 3, 5, 6};  // 初始化一个有序数组  
  
        // 测试目标值为5的情况  
        int target = 5;  
        System.out.println(solution.searchInsert(nums, target)); // 输出: 2  
  
        // 测试目标值为2的情况  
        target = 2;  
        System.out.println(solution.searchInsert(nums, target)); // 输出: 1  
  
        // 测试目标值为7的情况  
        target = 7;  
        System.out.println(solution.searchInsert(nums, target)); // 输出: 4  
    }  
}

 

Python代码示例:

def searchInsert(nums, target):  
    # 初始化搜索的左右边界,left为数组的开始位置,right为数组的结束位置  
    left, right = 0, len(nums) - 1    
  
    # 当左边界小于等于右边界时,进行循环搜索  
    while left <= right:    
        # 计算中间索引位置  
        mid = (left + right) // 2    
  
        # 如果中间元素等于目标值,直接返回其索引  
        if nums[mid] == target:    
            return mid    
  
        # 如果中间元素小于目标值,说明目标值(如果存在)一定在mid的右侧,更新左边界  
        elif nums[mid] < target:    
            left = mid + 1    
  
        # 如果中间元素大于目标值,说明目标值(如果存在)一定在mid的左侧或就是mid(但已经检查过mid不等于target),更新右边界  
        else:    
            right = mid - 1    
  
    # 如果循环结束,说明目标值不存在于数组中  
    # 由于我们是通过 left > right 退出的循环,且最后一次比较时 nums[mid] > target  
    # 所以 target 应该被插入在 left 的位置(此时left是第一个大于target的元素的位置)  
    # 返回left作为插入位置  
    return left    
  
# 测试  
nums = [1,3,5,6]    
target = 5    
print(searchInsert(nums, target))  # 输出: 2  # 目标值5在索引2处  
  
target = 2    
print(searchInsert(nums, target))  # 输出: 1  # 目标值2应该被插入在索引1处  
  
target = 7    
print(searchInsert(nums, target))  # 输出: 4  # 目标值7应该被插入在索引4处(数组末尾之后)

 

 

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千小凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值