02-算法打卡-数组-二分查找-leetcode(35)-第二天

1 题目地址

35. 搜索插入位置 - 力扣(LeetCode)35. 搜索插入位置 - 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 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 <= 104https://leetcode.cn/problems/search-insert-position/

2 题目说明

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

你可以假设数组中无重复元素。

示例 1:

  • 输入: [1,3,5,6], 5
  • 输出: 2

示例 2:

  • 输入: [1,3,5,6], 2
  • 输出: 1

示例 3:

  • 输入: [1,3,5,6], 7
  • 输出: 4

示例 4:

  • 输入: [1,3,5,6], 0
  • 输出: 0

3 解题思路

目标值对应的位置可能会有四种情况:
1、目标值在数组所有元素之前        
2、目前值等于数组中的某一个元素 
3、目标值插入数组中的位置 
4、目标是在数据中的所有元素之后  

 基于这4种情况可以思考代码上如何实现。
暴力方式:遍历数组,从小到大遍历去查找第一个大于等于目标值的位置,则是待插入的位置(情况1 2 3都符合)。 情况4直接对应nums.length即可。
二分查找:定义left right,每次拿middle=(left+right)/2跟目标值比较, 相等则直接返回索引位置,如果大于target则向左移动(right=middle-1),如果是小于target则向右移动(left=middle+1),当left>=right退出循环,right+1则为返回的位置。

二分查找法过程:【左闭右闭】

二分查找法过程:【左闭右开】 

 

4 代码编写

4.1 暴力方式

按数组从左到右依次遍历:找到一个大于target的索引下标,循环内要是找不到就是在数组的最后

class Solution {
    public int searchInsert(int[] nums, int target) {
       for (int i=0; i<nums.length; i++) {
            // 分别处理如下三种情况
            // 目标值在数组所有元素之前
            // 目标值等于数组中某一个元素
            // 目标值插入数组中的位置
            if (nums[i]>=target) { // 一旦发现大于或者等于target的num[i],那么i就是我们要的结果
                return i;
            }
       }
       // 目标值在数组所有元素之后的情况
       return nums.length; // 如果target是最大的,或者 nums为空,则返回nums的长度
    }
}

4.2  二分法实现

每次都以中间的数据跟目标数据比较,直到找到对应的目标位置

class Solution {
    public int searchInsert(int[] nums, int target) {
       for (int i=0; i<nums.length; i++) {
            // 分别处理如下三种情况
            // 目标值在数组所有元素之前
            // 目标值等于数组中某一个元素
            // 目标值插入数组中的位置
            if (nums[i]>=target) { // 一旦发现大于或者等于target的num[i],那么i就是我们要的结果
                return i;
            }
       }
       // 目标值在数组所有元素之后的情况
       return nums.length; // 如果target是最大的,或者 nums为空,则返回nums的长度
    }
}

4.2.1  二分法[left,right]

[left,right],左闭右闭,左右数值都是有效的,当left=right也是有效的

class Solution {
    public int searchInsert(int[] nums, int target) {
      int left = 0;
      int right = nums.length-1;
      while(left<=right) {
        int middle = (left+right)/2;
        if (nums[middle] > target) {
            right = middle - 1; // 目标值在左区间
        } else if (nums[middle] < target) {
            left = middle + 1; // 目标值在右区间
        } else {
            return middle;
        }
      }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], 因为是右闭区间,所以 return right + 1
      return right + 1;
    }
}

 

4.2.2  二分法[left,right)

[left,right],左闭右开,左数值是有效的,右数值是无效的,当left=right是无效的

class Solution {
    public int searchInsert(int[] nums, int target) {
      int left = 0;
      int right = nums.length;
      while(left<right) {
        int middle = (left+right)/2;
        if (nums[middle] > target) {
            right = middle; // 目标值在左区间, 右区间是开
        } else if (nums[middle] < target) {
            left = middle + 1; // 目标值在右区间
        } else {
            return middle;
        }
      }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], 因为是右闭区间,所以 return right + 1
      return right;
    }
}

 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值