首页 > 其他分享 >二分查找精炼回顾-kevin

二分查找精炼回顾-kevin

时间:2024-09-03 11:53:14浏览次数:6  
标签:二分 right 精炼 target nums mid 搜索 kevin left

二分搜索回顾,由于习惯问题, 二分搜索问题都采用闭区间来思考 二分搜索总共就三类问题,统一规范如下, 由于都统一采用闭区间来思考,所以while的判定条件都是**left <= right ** mid 在都是在while循环之后再更新

left = 0, right = len(nums) - 1
#所以二分搜索区间是[left, right]

1,寻找一个数

def binarySearch(nums:List[int], target:int) -> int:
    left = 0
    # 注意
    right = len(nums) - 1

    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            # 注意
            left = mid + 1
        elif nums[mid] > target:
            # 注意
            right = mid - 1
  • 由于采用闭区间,[left, right]无意义的条件是是left = right + 1,所以while的判定条件是left <= right 时候进入循环,跳出循环的条件就是left = right + 1

  • 由于采用都是闭区间,也就是发现mid 不是要查找的目标时候,由于闭区间应该更新为[left, right - 1] 或者更新为 [mid + 1, right] ,只要更新一定有1

  • 更新自己总结的小口诀是, ‘大右,小左’ 解读是中间值比目标大,更新右侧边界 , 中间值比目标小更新左侧边界如果nums[mid] > target更新left = mid + 1

    如果nums[mid] < target 更新 right = mid - 1

找边界问题的关键点在于,对nums[mid] == target这种情况的处理, 总结起来就是要找左边界,就是在[left, mid - 1] 中持续收缩,直到找到左边界,也就是>=这种 要找右边界,就是在[mid + 1, right] 中持续收缩,直到找到有边界。 所以当碰到目标值的时候,两者操作不同,获得边界自然就不同

2,寻找左侧边界

找左侧边界的特殊情况,如果 target 不存在,搜索左侧边界的二分搜索返回的索引是大于 target 的最小索引

可见,找到 target 时不要立即返回,而是缩小「搜索区间」的上界 right,在区间 [left, mid - 1] 中继续搜索,即不断向左收缩,达到锁定左侧边界的目的。

if nums[mid] < target:
    # 搜索区间变为 [mid+1, right]
    left = mid + 1
elif nums[mid] > target:
    # 搜索区间变为 [left, mid-1]
    right = mid - 1
elif nums[mid] == target:
    # 收缩右侧边界
    right = mid - 1

3,寻找右侧边界

while left <= right:
    mid = left + (right - left) // 2
    if nums[mid] > target:
        right = mid - 1
    elif nums[mid] < target:
        left = mid + 1
    elif nums[mid] == target:
        left = mid + 1

总结

只要区间定义为闭区间,二分查找的判定条件就是 while left <= right ,其次,找边界问题与找点问题,不同点只在于num[mid] == target时候处理情况的不同。
用二分查找求最长递增子序列问题

class Solution:
    def lengthOfLIS(self, nums):
        top = [0] * len(nums)
        # 牌堆数初始化为 0
        piles = 0
        for i in range(len(nums)):
            # 要处理的扑克牌
            poker = nums[i]

            # 搜索左侧边界的二分查找(闭区间)
            left, right = 0, piles - 1#这个-1 经常遗漏。
            while left <= right:  # 注意这里是 <= 表示闭区间
                mid = (left + right) // 2
                if top[mid] > poker:
                    right = mid - 1  # 继续在左半部分搜索
                elif top[mid] < poker:
                    left = mid + 1  # 继续在右半部分搜索
                else:
                    right = mid - 1  # 继续向左搜索

            # 没找到合适的牌堆,新建一堆
            if left == piles:
                piles += 1
            # 把这张牌放到牌堆顶
            top[left] = poker

        # 牌堆数就是 LIS 长度
        return piles

标签:二分,right,精炼,target,nums,mid,搜索,kevin,left
From: https://blog.csdn.net/m0_48938554/article/details/141832556

相关文章

  • 代码随想录算法训练营|Day01 LeetCode 704.二分查找,27.移除元素,977.有序数组的平方
    数组理论基础数组是存放在连续空间上的相同类型数据的集合数组的元素是不能删的,只能覆盖704.二分查找LeetCode:704.有序数组的平方classSolution{public:intsearch(vector<int>&nums,inttarget){intlength=nums.size();inti=0......
  • CF 1994 C. Hungry Games (*1600) 思维+二分
    CF1994C.HungryGames(*1600)思维+二分题目链接题意:给你一个长度为\(n\)的关卡,和一个正整数\(x\),初始分数为\(0\),通过每个关卡就会获得对应的分数。但是分数如果超过\(x\),就会清零。现在让你求出满足最终得分不为零的所有子区间数量。思路:正难则反,改求最终得分为......
  • CF 2004 D. Colored Portals (*1600) 二分
    CF2004D.ColoredPortals(*1600)二分题目链接题意:有\(n\)座城市,编号从\(1\)到\(n\)。传送门一共有\(4\)种颜色,每个城市有两种不同颜色的传送门。若城市\(i\)和城市\(j\)有相同颜色的传送门。那么就可以花费\(|i-j|\)枚金币从城市\(i\)到城市\(j\)。\(q\)......
  • JavaSE-递归法解决二分查找、快速排序
    704.二分查找https://leetcode.cn/problems/binary-search/packagedemo;publicclassBinarySearch{publicstaticvoidmain(String[]args){BinarySearchbr=newBinarySearch();System.out.println(br.search(newint[]{1,2,3,4,5,6,7......
  • 二分查找
    题目:给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。解法一:左闭右闭区间。(left=0,right=nums.length-1)思路:对于这种问题,捕捉到数据类型是数组并且数组中元素是有序的并且是查找类......
  • 信息学奥赛初赛天天练-81-NOIP2015普及组-完善程序-二分答案、二分查找、中位数、二分
    1完善程序(单选题,每小题3分,共30分)中位数median给定n(n为奇数且小于1000)个整数,整数的范围在0∼m(0<m<2^31)之间,请使用二分法求这n个整数的中位数。所谓中位数,是指将这n个数排序之后,排在正中间的数。(第五空2分,其余3分)01#include<iostream>02usingnamespace......
  • 学习笔记(?):一类查询 kth 的整体二分 trick
    问题大概就是有若干次修改(也有可能没有)和若干次查询,查询形如查某个范围的kth。做法是,把可能成为答案的候选集合按照权值大小排序。询问集合可以不用管顺序。然后开始二分。我们令solve(l,r,L,R)表示第\(l\)到\(r\)个询问的kth一定在候选序列的第\(L\)到\(R\)个数。......
  • NC 二分查找-II
    系列文章目录文章目录系列文章目录前言前言前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。描述请实现有重复数字的升序数组的二分查找给定一个元素有序的(升序)长......
  • [Python手撕]二分法
    二分法二分法的几个位置比如01234567891233333456有时候想要寻找小于3的最大数字有时候想要寻找第一个满足>=3的数字,有时候想要寻找最后一个满足>=3的数字,有时候想要寻找小于4的最大数字nums=[1,2,3,4,5,5,5,5,5,6,7,8,9]n=......
  • F. Final Boss(二分,周期)
    题目来源:https://codeforces.com/contest/1985/problem/F//题意:你有n种攻击,每种攻击有周期和攻击力,如果当前回合是x,以为着第i种攻击,下次攻击是x+ci回合。现在有Boss,生命值为h,当h<=0的时候,Boss死亡。一开始所有攻击都没有冷却时间,问最少第几回合Boss死亡。//思路:“最开始无脑模......