首页 > 其他分享 >LeetCode习题——在排序数组中查找元素的第一个和最后一个位置(二分查找)

LeetCode习题——在排序数组中查找元素的第一个和最后一个位置(二分查找)

时间:2023-04-08 09:01:12浏览次数:97  
标签:right target nums int mid 查找 习题 LeetCode left

在排序数组中查找元素的第一个和最后一个位置

力扣链接:在排序数组中查找元素的第一个和最后一个位置

题目

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:
输入:nums = [], target = 0
输出:[-1,-1]

提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109

分析或原理

这题的难点在于target有可能会有多个,如何确定边界值。先说有两种类型的解法,一种是暴力,一种是二分法求边界,由于必须设计时间复杂度为 O(log n) 的算法解决此问题,所以选择二分法。

题解

暴力方法

通过遍历数组,存储第一个和最后一个,但是时间复杂度会到O(n),不符合题目要求的,但是力扣中可以通过。

class Solution {
    public int[] searchRange(int[] nums, int target) {
        // 暴力方法
        int [] index = {-1,-1}; 	// 初始值设置为[-1, -1]
        for(int i=0;i<nums.length;i++){  // 遍历nums数组
           if(nums[i] == target){		// 找到等于target的数
               if(index[0] == -1){	  // 如果当前索引等于-1说明,说明此之前没有找到一个相等的,所以最小的就是它
                   index[0] = i;
               }
               if(index[1]<=i){		  // 如果当前索引大于index[1],即可替换右边界
                   index[1] = i;
               }
           } 
        }
        return index;
    }
}
二分法

我们可以通过写几个方法帮我找到左右边界,通过调用方法寻找。

public int[] searchRange(int[] nums, int target) {
    // 二分法
    int len = nums.length;
    if(len == 0) {	// 如果数组为空则直接返回[-1, -1]
        return new int[]{-1, -1};
    }
    int leftPosition = findLeftPosition(nums, target);  // 寻找左边界
    if (leftPosition == -1) {		// 如果没找打左边界 则直接返回[-1, -1]
        return new int[]{-1, -1};
    }
    int rightPosition = findRightPosition(nums, target); // 寻找右边界
    return new int[]{leftPosition, rightPosition}; // 直接返回左右边界即可
}

查找左边界

private int findLeftPosition(int[] nums, int target) {
    // 二分法查找
    int left = 0;
    int right = nums.length - 1;
    while (left < right){
        int mid = (left + right)  1;
        if (nums[mid] < target){
            // 下一轮搜索的区间是 [mid + 1, right]
            left = mid + 1;
        } else if (nums[mid] == target) {
            // 下一轮搜索的区间是 [left, mid]
            right = mid;
        } else {
            // nums[mid] > target
            // 下一轮搜索的区间是 [left, mid - 1]
            right = mid - 1;
        }
    }
    // 上述循环可能找到的是插入位置而不一定是等于target所以需要判断一下
    if (nums[left] == target) {
        return left;
    } else {
        return -1;
    }
}

查找右边界

private int rightPosition(int[] nums, int target){
    int left = 0;
    int right = nums.length - 1;
    while (left < right){
        int mid = (left + right + 1) / 1;  // 这里选择向上取整
        if (nums[mid] < target){
            // 下一轮搜索的区间是 [mid + 1, right]
            left = mid + 1;
        } else if (nums[mid] == target) {
            // 下一轮搜索的区间是 [mid, right]
            left = mid;
        } else {
            // nums[mid] > target
            // 下一轮搜索的区间是 [left, mid - 1]
            right = mid - 1;
        }
    }
    return left;
}

当你面对困难时,不要害怕挑战。挑战并不可怕,重要的是你需要勇敢地面对它,积极寻找解决问题的方法。只要你努力不懈、持之以恒,最终你一定能够克服难关。

标签:right,target,nums,int,mid,查找,习题,LeetCode,left
From: https://www.cnblogs.com/Heyking/p/17297895.html

相关文章

  • leetcode-1109-差分
    classSolution{publicint[]corpFlightBookings(int[][]bookings,intn){int[]diff=newint[n];for(int[]booking:bookings){intfirst=booking[0],last=booking[1],seats=booking[2];diff[first-1]......
  • 4月7日leetcode随笔,异或的灵活运用
    给你一个非空整数数组nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。来源:力扣(LeetCode)链接:https://leetcode.cn/problems/single-number著作权归领扣......
  • python中的二分查找
    二分查找的前提是查找的数据按照顺序排序二分查找的核心思想是递归#arr:查找的对象#left:arr的左边界#right:arr的右边界#x:需要查找的数defbinary_search(arr,left,right,x):#左边界小于等于右边界ifleft<=right:#得到中位数mid=int((lef......
  • [每天例题] 查找输入整数二进制中1的个数
    查找输入整个二进制中1的个数题目 题目分析计算它在二进制下的1的个数。注意多组输入输出!!!!!! 数据范围:1≤n≤2^31 −1 思路分析1.多组数据的输入方法:1.EOF法因为在线评测系统的输入数据存放在一个文件中,因此可以通过文件是否结束的方式判断输入的数据是否结束。scanf......
  • pg数据库查找外键但没有索引的sql
    SELECTpg_index.indexrelid::regclass,'createindex'||relname||'_'||array_to_string(column_name_list,'_')||'_idxon'||conrelid||'('||array_to_string(column_name_list,......
  • #yyds干货盘点# LeetCode程序员面试金典:四数之和
    题目:给你一个由n个整数组成的数组 nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a],nums[b],nums[c],nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):0<=a,b,c,d <na、b、c和d互不相同nums[a]+nums[b]+nums[c]......
  • #yyds干货盘点# LeetCode面试题:x 的平方根
    1.简述:给你一个非负整数x,计算并返回 x 的算术平方根。由于返回类型是整数,结果只保留整数部分,小数部分将被舍去。注意:不允许使用任何内置指数函数和算符,例如pow(x,0.5)或者x**0.5。 示例1:输入:x=4输出:2示例2:输入:x=8输出:2解释:8的算术平方根是2.82842...,由......
  • 代码随想录Day22-Leetcode235. 二叉搜索树的最近公共祖先,701.二叉搜索树中的插入操作,4
    235.二叉搜索树的最近公共祖先题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/又玩了一天,手又生疏了好多;这道题看了题解,先用公共解法了,之前的题没刷,就给现在留坑了/***Definitionforabinarytreenode.*functionTree......
  • fragment的查找和移除
    FragmentManagerfragmentmanger=getSupportFragmentManager();FragmentTransactionfragmenttransaction=fragmentmanager.begintransaction();//这一步不进行也可以查找Fragmentfragment=fragmentManager.findFragmentById(R.id.fragment);if(fragment!==null){......
  • Java-Day-5(数组 + 排序 + 查找 + 二维数组)
    Java-Day-5数组可以存放多个同一类型的数据,属于引用类型动态初始化语法:数据类型数组名[]=new数据类型[大小]例:int[]a=newint[5]或:doublea[]=newdouble[n]使用(引用/访问/获取)时,初始下标(索引)是从0开始,第一个数=a[0]获取长度:数组名.length......