二分法攻略

news2024/12/23 17:01:41

本节内容只有通过例题来记录效果才是最好的,请看下面内容!

递归实现二分法

经典二分查找问题:LintCode 炼码

描述**:**在一个排序数组中找一个数,返回该数出现的任意位置,如果不存在,返回 -1。 输入:nums = [1,2,2,4,5,5], target = 2 输出:1 或者 2

     def findPosition(self, nums, target):
        def binarysearch(nums,start,end,target):
            middle = (start+end)//2

            # if((start==end and nums[start]!=target) or start>end):
                # return -1

            if(start>end): #这里是>还是>= ? 留给自己思考!
                return -1

            if(nums[middle]==target):
                return middle
            if(nums[middle]<target):
                return binarysearch(nums, middle+1, end, target)
            else:
                return binarysearch(nums, start, middle-1, target)

        # write your code here
        if(nums==[] or nums == None):
            return -1

        return binarysearch(nums, 0, len(nums)-1, target)

非递归实现二分法

请注意,非递归二分法非常常用,尤其在双指针里面。但是这类题目的一个难点就是搞不拎清到底是'>='('<=')还是'>'('<'),到底是 left = middle + 1 (right = middle - 1)还是 left = middle (right = middle)。那么,本章节将会彻底讲明白这些坑,并给出一个万能二分模板解决一系列问题。在进行下面的例题讲解时,先搞清楚这几种循环结束时条件的值(假设都是 +=1):while(left<right)、while(left<=right)、while(left+1<right),第一种结束时 left==right ,第二种是left = right + 1,第三种是 left ==right - 1;

经典二分查找问题:LintCode 炼码

描述**:**在一个排序数组中找一个数,返回该数出现的任意位置,如果不存在,返回 -1。 输入:nums = [1,2,2,4,5,5], target = 2 输出:1 或者 2 使用经典非递归算法实现:

def findPosition(nums, target): 
    # write your code here
    if(nums==[] or nums == None):
        return -1

    left = 0
    right = len(nums)-1

    while(left<=right): # 这里是'<='还是 '<' ?
        middle = (left+right)//2
        if(nums[middle]==target):
            return middle
        if(nums[middle]<target):
            left = middle+1
            if(nums[middle]>target):
                right = middle-1
    #if(nums[left]==target):
    #    return left;
    return -1

解释:那么上述代码中第9行到底要不要加上'='呢?答案是既可以使用"<=",也可以使用"<";这里举例说明,假设nums = [3] 只有一个元素,那么left = 0 ,right = 0 。如果加上"="号那么,这种情况依旧可以进入while中进行判断,也就是说while循环已经conver到了这种情况,所以可以加上。如果不加"=",那么需要单独判断这种特例,那就需要17,18行的代码。总结就是,当遇到这种情况搞不清楚时,举一个只有一个元素数组的特例,看看是否当用"<="时 while 循环能否cover到取等于的情况,如果能就加上等号,如果不能就针对特例另外写判断。一般建议写不加等于号的情况,将等于的情况单独拿出来判断,这样可以避免很多边界值问题。好的,接下来是难度大一点的二分查找,这里特别注意边界条件!不然,很容易错,可以先自己做做再看解析: 目标最后位置:LintCode 炼码 **描述:**给一个升序数组,找到 target 最后一次出现的位置,如果没出现过返回 -1 输入:nums = [1,2,2,4,5,5], target = 2 输出:2

    def last_position(self, nums: List[int], target: int) -> int:
        # write your code here

        if(nums==None or nums==[]):
            return -1

        left=0;right=len(nums)-1
        while(left+1<right):
            middle = (left+right)//2
            if(nums[middle]==target):
                left = middle   # 不能是middle+1,这样会跳过middle
            if(nums[middle]<target):
                left = middle+1
            if(nums[middle]>target):
                right = middle-1
        if(nums[right]==target):
            return right
        if(nums[left]==target):
            return left
        return -1

解析:这道题是要找到最后一个等于target值的数字的下标,这个时候只需要将第11行代码直接返回中间值改成让left = middle,也就是说当找到一个中间值等于target时我们并不直接返回,而是包含这个middle继续向后查找。注意,这里的判断条件必须要写出 left+1<right,不然当nums=[2,2],target=2时,则进入死循环(请自觉试试),第8行这样写的话,我们希望left = right -1时,也就是left与right相邻时结束。所以,最后第16到19行代码就必须单独判断这两个索引是否满足题意。当你会解这道题时,你应该会解下一道题: fisrt_position二分查找:LintCode 炼码 **描述:**给定一个排序的整数数组(升序)和一个要查找的整数 target,用O(logn)O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1。
解析:你只需要更改第11、16到19行代码即可完成!

最后给出一个二分查找题目的通用模板:

    def last_position(self, nums: List[int], target: int) -> int:
        # write your code here

        if(nums==None or nums==[]):
            return -1

        left=0;right=len(nums)-1
        while(left+1<right): # 保证循环一定会退出
            middle = (left+right)//2
            if(nums[middle]==target):
                left = middle   # 根据题意修改这里
            if(nums[middle]<target):
                left = middle  #不 +1 ,不影响结果 ,有时候+1反而错误
            if(nums[middle]>target):
                right = middle #不 -1 ,不影响结果 ,有时候-1反而错误

        # 因为循环提前一步退出了,所以最后一步自己判断
        if(nums[right]==target):
            return right
        if(nums[left]==target):
            return left
        return -1

使用通用目标解决以下问题: 排序数组中最接近元素:LintCode 炼码 **描述:**在一个排好序的数组 A 中找到 i 使得 A[i] 最接近 _target _如果数组中没有元素,则返回-1。

585· 山脉序列中的最大值:LintCode 炼码 **描述:**给 n 个整数的山脉数组,即先增后减的序列,找到山顶(最大值)。

from typing import (
    List,
)
class Solution:
    """
    @param nums: a mountain sequence which increase firstly and then decrease
    @return: then mountain top
    """
    def mountain_sequence(self, nums: List[int]) -> int:
        # write your code here
        if(nums==[] or nums==None):
            return []

        left = 0
        right = len(nums)-1
        while(left+1<right):
            middle = (left+right)//2
            if(nums[middle]>nums[middle+1]):
                right = middle
            else:
                left = middle
        return max(nums[left],nums[right])

62 · 搜索旋转排序数组:LintCode 炼码

    def search(self, a: List[int], target: int) -> int:
        # write your code here
        if(a==[] or a == None):
            return -1
        # 有一半的数一定是单调递增的,在单调的那边找就行
        left=0
        right=len(a)-1
        while(left+1<right):
            middle = (left+right)//2
            if(a[middle]>=a[left]):
                if(target>=a[left] and target<=a[middle]):
                    right = middle 
                else:
                    left = middle 

            if(a[middle]<a[right]):
                if(target>=a[middle] and target<=a[right]):
                    left = middle
                else:
                    right = middle

        if(a[left]==target):
            return left
        elif(a[right]==target):
            return right
        else:
            return -1

未排序的序列上的二分法

75 · 寻找峰值:LintCode 炼码 **描述:**给定一个整数数组(size为n),其具有以下特点:

  • 相邻位置的数字是不同的
  • A[0] < A[1] 并且 A[n - 2] > A[n - 1]

假定_P_是峰值的位置则满足A[P] > A[P-1]且A[P] > A[P+1],返回数组中任意一个峰值的位置。 输入:A = [1, 2, 1, 3, 4, 5, 7, 6] 输出:1

    def find_peak(self, a: List[int]) -> int:
        # write your code here
        if(a==[]):
            return -1
        left = 0 
        right = len(a)-1

        while(left+1<right):
            middle =(left+right)//2
            if(a[middle]>a[middle-1]):
                left = middle
            else:
                right = middle
        if(a[left]>a[right]):
            return left
        else:
            return right

在答案集合上进行二分

第一步:确定答案范围,第二步:验证答案大小 183 · 木材加工:LintCode 炼码 **描述:**有一些原木,现在想把这些木头切割成一些长度相同的小段木头,需要得到的小段的数目至少为 k。给定L和k,你需要计算能够得到的小段木头的最大长度。 输入: L = [232, 124, 456] k = 7 输出: 114 说明: 我们可以把它分成 114 的 7 段,而 115 不可以 ,对于 124 这根原木来说多余的部分没用可以舍弃,不需要完整利用

def wood_cut(self, l: List[int], k: int) -> int:
        # write your code here
        if(l==[]):
            return 0

        def cut(l,length):
            count = 0
            for i in l:
                count +=(i//length)
            return count

        start = 1
        end = sum(l)//k

        if(end<1):
            return 0

        while(start+1<end):
            middle = (start+end)//2
            if(cut(l,middle)>=k):
                start = middle
            else:
                end = middle

        if(cut(l,end)>=k):
            return end
        elif(cut(l,start)>=k):
            return start
        else:
            return -1

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/340069.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java spring完全注解开发

其实学习注解之后 我们也只有一个开启扫描需要xml的配置了 而 这一步 其实也是可以写到类里面的 我们这边先创建一个java项目 然后引入 spring需要的几个基本包 在src中创建一个包 叫 Bean Bean下创建 一个包 叫 UserData UserData 包下创建一个类 我这里叫 User 参考代码如…

Java List集合

6 List集合 List系列集合&#xff1a;添加的元素是有序&#xff0c;可重复&#xff0c;有索引 ArrayList: 添加的元素是有序&#xff0c;可重复&#xff0c;有索引LinkedList: 添加的元素是有序&#xff0c;可重复&#xff0c;有索引Vector &#xff1a;是线程安全的&#xff…

初识数据仓库

一、什么是数据仓库数据库 --> OLTP&#xff1a;&#xff08;on-line transaction processing&#xff09;翻译为联机事务处理记录某类业务事件的发生&#xff0c;如购买行为&#xff0c;银行交易行为&#xff0c;当行为产生后&#xff0c;系统会记录是谁在何时何地做了何事…

day11_python虚拟环境安装与配置

文章目录Windows下安装第一步&#xff0c;安装virtualenv改源参考第二步&#xff0c;安装virtualenvwrapper-winUbuntu下安装第一步、安装virtualenv和virtualenvwrapper第二步、配置.bashrc文件&#xff0c;添加下面三行第三步&#xff0c;用下列命令让修改后的.bashrc生效配置…

今天来聊一聊信息差,或许会刷新你的认知

有人会说&#xff1a;现在互联网信息这么发达&#xff0c;获取信息的渠道也越来越多&#xff0c;还会存在信息差吗&#xff1f;我的回答是&#xff1a;会&#xff0c;而且随着社会高速的发展&#xff0c;信息差会越来越明显。这里大家需要了解一个词&#xff1a;信息茧房信息茧…

植物育种中广义遗传力的定义

大家好&#xff0c; 我是邓飞。 今天聊一下广义遗传力的计算方法。 广义遗传力定义 广义遗传力&#xff08;H2H^2H2&#xff09;定义为归因于基因型总体遗传变异的表型变异比例。 通常他包括三个解释&#xff1a;&#xff08;详见我这篇博客的公式推导 回归系数 相关系数 遗…

微信小程序_调用openAi搭建虚拟伙伴聊天

微信小程序_调用openAi搭建虚拟伙伴聊天背景效果关于账号注册接口实现8行python搞定小程序实现页面结构数据逻辑结速背景 从2022年的年底&#xff0c;网上都是chagpt的传说&#xff0c;个人理解这个chatgpt是模型优化训练&#xff0c;我们在用chatgpt的时候就在优化这个模型&a…

九龙证券|连续13周净流入!北向资金爆买“中字头”股票

Wind数据显现&#xff0c;本周北向资金净流入A股达29.33亿元&#xff0c;其间周四净流入121亿元&#xff0c;其他四个交易日均为净流出状况。尽管本周北向资金流入A股力度放缓&#xff0c;可是仍然保持着周度接连净流入态势。 接连第13周净流入 Wind数据显现&#xff0c;从202…

Redis核心知识点

Redis核心知识点Redis核心知识点大全五种数据类型redis整合SpringBoot序列化问题渐进式扫描慢查询缓存相关问题数据库和缓存谁先更新缓存穿透缓存雪崩缓存击穿实际应用超卖问题分布式锁全局唯一ID充当消息队列Feed流附近商户签到HyperLogLog实现UV统计持久化RDBAOF持久化小结事…

整型提升+算术转换——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是之前操作符那篇博客中没有讲完的内容&#xff0c;整型提升这个小知识点也非常重要&#xff0c;那现在&#xff0c;就让我们进入操作符的世界吧 隐式类型转换 算术转换 操作符的属性 隐式类型转换 表达式求值的顺序一部…

opencv显示图像

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

带头节点的单链表的就地逆置

目录 1.题目背景 2.思路方法分析 2.1采用循环实现的就地逆置法 2.2 递归方式实现的逆置 3.金句省身 1.题目背景 本题要求编写函数实现带头结点的单链线性表的就地逆置操作函数。L是一个带头结点的单链表&#xff0c;函数ListReverse_L(LinkList &L)要求在不新开辟节点的…

使用自己的数据集,测试mmrotate新网络rotated_rtmdet,旋转目标检测

1.安装 &#xff01;&#xff01;&#xff01;&#xff01;一定不要安装mmrotate 1.版本需求 mmcv 2.0.0rc2 mmdet 3.0.0rc5 mmengine 0.5.0 不用安装mmcv-full 下载mmrotate 1.x 源码 &#xff08;不要下载默认的master&#xff0c;因为新的网络只在1.x版本中&#xff09; …

【前端】Vue项目:旅游App-(23)detail:房东介绍、热门评论、预定须知组件

文章目录目标过程与代码房东介绍landlord热门评论HotComment预定须知Book效果总代码修改或添加的文件detail.vuedetail-book.vuedetail-hotComment.vuedetail-landlord.vue参考本项目博客总结&#xff1a;【前端】Vue项目&#xff1a;旅游App-博客总结 目标 根据detail页面获…

我用python/C++调用ChatGPT自制了一个聊天问答机器人

目录1 ChatGPT完整版2 Python/C调用ChatGPT2.1 获取API秘钥2.2 测试API功能2.3 设计简单UI3 聊天问答1 ChatGPT完整版 2015年&#xff0c;OpenAI由马斯克、美国创业孵化器Y Combinator总裁阿尔特曼、全球在线支付平台PayPal联合创始人彼得蒂尔等硅谷科技大亨创立&#xff0c;公…

【脚本开发】运维人员必备技能图谱

脚本&#xff08;Script&#xff09;语言是一种动态的、解释性的语言&#xff0c;依据一定的格式编写的可执行文件&#xff0c;又称作宏或批处理文件。脚本语言具有小巧便捷、快速开发的特点&#xff1b;常见的脚本语言有Windows批处理脚本bat、Linux脚本语言shell以及python、…

Spring缓存Demo

Spring中的缓存用法:有说错请指正 启动类加EnableCache 注解很多,这里举例几个实用的 第一组 value和key都没什么特别的含义,随你自己取,注意key里面是包了一层的 Cacheable(value"user",key "findUsers") 第一次查询的时候,会查数据库,然后将返回结果…

【GlobalMapper精品教程】045:空间分析工具(2)——相交

GlobalMapper提供的空间分析(操作)的方法有:交集、并集、单并集、差异、对称差集、相交、重叠、接触、包含、等于、内部、分离等,本文主要讲述相交工具的使用。 文章目录 一、实验数据二、符号化设置三、相交运算四、结果展示五、心灵感悟一、实验数据 加载配套实验数据(…

Hadoop安装 --- 简易安装Hadoop

目录 1、使用xftp工具 在opt目录下创建install和soft文件 2、使用xftp工具 将压缩包上传到install文件 3、编写shell脚本 3.1、创建目录来放shell脚本 3.2、创建autoinsatll.sh文件并修改权限 3.3、编写autoinsatll.sh 文件 刷新资源 运行文件 格式化 启动所有进程 Ha…

ChatGPT到底有多牛?博主带你亲测

文章目录论文项目代码算法学习情感职业回答知乎ChatGpt网页版与客户端版个人评价论文 问他毕设框架&#xff1a; 让他帮我写一段毕设背景部分&#xff1a; 项目代码 我让他帮我用Django写一个demo网站&#xff1a; 算法 matlab写遗传算法&#xff1a; 问一个数据结构&…