首页 > 其他分享 >二分

二分

时间:2023-02-04 11:45:54浏览次数:48  
标签:二分 right target nums mid 数组 left

更加严谨的二分

  • 使用场景
    • 满足类似的条件,需要找的某个数>=target
    • 或者<=target
  • 一般的二分
    • 只会判断是否满足==的条件
    • 对于边界的点会舍弃
    • 造成有可能找不到正确的答案

二分模板

  • 判断>=target 的情况

	// 序列为0-n-1

	// 为什么设置n,n为不合法的情况,即没有比target还要大的
	let left=0
    let right=n

    while(left<right){

        let mid=(left+right)>>1

        if(nums[mid]>=target){
            right=mid
        }else{
            left=mid+1
        }
    }

	return right

    

  • 判断<=target的情况
	// 这里-1也是为了进行边界处理    
	left=-1
    right=nums.length-1

    while(left<right){
        let mid=(left+right+1)>>1

        if(nums[mid]<=target){
            left=mid
        }else{
            right=mid-1
        }
    }

	return right

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

给你一个按照非递减顺序排列的整数数组 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
解题思路
1. 其实是查找>=target 的第一个数
2. 和<=target 的最后一个数
完整代码
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
    // 问题本质在于求>=target 的第一个数
    // 和<=target 的最后一个数

    let left=0
    let right=nums.length

    let res=[]

    while(left<right){

        let mid=(left+right)>>1

        if(nums[mid]>=target){
            right=mid
        }else{
            left=mid+1
        }
    }

    
    if(nums[right]!==target) right=-1
    res.push(right)

    left=-1
    right=nums.length-1

    while(left<right){
        let mid=(left+right+1)>>1

        if(nums[mid]<=target){
            left=mid
        }else{
            right=mid-1
        }
    }

    if(nums[right]!==target) right=-1
    res.push(right)

    return res
    

    

};

153. 寻找旋转排序数组中的最小值(二分查找的变种)

已知一个长度为 n 的数组,预先按照升序排列,经由 1n旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

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

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。

示例 2:

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。

示例 3:

输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。

提示:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 中的所有整数 互不相同
  • nums 原来是一个升序排序的数组,并进行了 1n 次旋转
解题思路
1. 需要将题目抽象一下
2. 二分不仅仅只是在一个有序数组中查找某个值
3. 是一种思想,满足条件的放右边,不满足的放左边(舍弃)
4. 本题旋转后的数组,部分有序
5. 本质是找满足<=最后一个元素 的第一个元素(下标靠前的)
完整代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {

    // 旋转后的数组部分有序

    3,4,5|1,2

    // 观察可以得出二分的条件

    // 即<=2 的第一个元素

    4,5,6,7|0,1,2

    //  <=2 的第一个元素

    let left=0
    let right=nums.length-1

    while(left<right){

        let mid=Math.floor((left+right)/2)

        if(nums[mid]<=nums[nums.length-1]){

            // 当前的mid满足小于2
            // 是不是之前的也满足
            // 我们向左缩小范围
            right=mid
        }else{
            left=mid+1
        }
    }

    return nums[right]

};

标签:二分,right,target,nums,mid,数组,left
From: https://www.cnblogs.com/lingxin1123/p/17087605.html

相关文章

  • 三分-二分答案
    1.三分查找场景序列不满足单调增或者单调减但满足局部的单调性即只存在波峰或者只存在波谷求波峰和波谷我们并不字段波峰和波谷在哪里定义域l-r我们在定义域......
  • [数组]——二分查找
    [数组]——二分查找1.设定左右区间和数组长度,计算中间数的索引2.根据左右区间的距离开始循环,并判断目标数与中间数的大小关系,缩小区间3.返回目标数在数组中的索引注意......
  • 二分查找——C语言描述
    二分查找——C语言描述目录二分查找——C语言描述0测试用例框架1定义2代码4测试用例0测试用例框架https://blog.csdn.net/m0_59469991/article/details/127137119?......
  • 二分查找
    #include<iostream>usingnamespacestd;intbinarySearch(intarr[],intlow,inthigh,intkey){if(low>high){return-1;}intmid=low......
  • POJ 2253 Frogger(并查集+二分||Dijkstra)
    DescriptionFreddyFrogissittingonastoneinthemiddleofalake.SuddenlyhenoticesFionaFrogwhoissittingonanotherstone.Heplanstovisither,but......
  • Codeforces1201 B Maximum Median (二分)
    Description:Youaregivenanarray aa of nn integers,where nn isodd.Youcanmakethefollowingoperationwithit:Chooseoneoftheelementsofthearray......
  • Educational Codeforces Round 75 D. Salary Changing(二分)
    题意就是:给n个人发工资,总钱数为s。每个人有一个工资范围。要求一个发工资方案,使得工资中位数最大,求这个中位数。考虑到中位数最大,于是我们可以二分。但是每个人的工资......
  • 二分基础
    二分(类似于单调函数求零点)二分查找在一个单调有序的集合中查找元素,每次将集合分为左右两部分,判断解在哪个部分中并调整集合上下界,重复直到找到目标元素题目:给定一......
  • 前端算法之二分查找
    在数组中查找指定元素,如果存在就返回它的位置,如果不存在,就返回-1。这是一道非常经典的算法题,考的就是二分查找算法,首先分析二分查找的思路:假设一个数组为[3,5,19,22,......
  • 二分查找-力扣(Java)
    题目描述给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。来源:力扣(LeetCode)链接......