算法训练——二分专题

二分算法

是对索引进行二分呢,还是对值进行二分。
查找数组中是否存在某数,一般对索引二分。

计算一个未知的数字,比如珂珂吃香蕉,完全二叉树的结点个数,得分最高的路径这类就是对值进行二分,即找到最小值和最大值,然后折半查找,这种我们一般要left≤right,因为我们要确保left和right也要取到。

240.搜索二维矩阵 II

每行没列都是升序的,问是否存在target。
错解:我拿起这道题就把矩阵拉通成一维进行二分查找了,发现不行,又对首列进行二分查找所在的行,又对这一行进行二分查找。结果答案都是错的。
分析: 这道题只是行和列分别升序的,并没有保证行的第一个值大于前一行的最后一个值,所以不能拉通成一维进行二分。也不能对行列分别二分,比如i行的值为2,5,7,8,j行的的值为3,4,9,10,那么二分查找target=5可能所在的行可能导致我返回第j行,进而导致无法查找5。
改正: 这道题,要对每一行的第一个值进行判断,如果这个值<target,那么就对这一行进行二分查找,如果在这一行里没找到,就继续判断下一行的第一个值是否<target,满足就二分,之后做相同处理,直到找到target或者所有行都处理完。
在这里插入图片描述

222 完全二叉树的结点个数

在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。
解析:最后一个节点编号即为节点数量,最底层节点的编号最小为left,最大为right,在这个区间里二分枚举最后一个节点的编号k,只需要检测节点k是否存在即可。怎么判断k是否存在呢? 主要是找到编号的二进制表达和层数的关系。
(注意下图中计算高度和我的不一样,我的是节点层数即为高度,他的是节点层数-1为高度,所以在关于节点k的描述和我的代码有些许出入,但是不影响理解)
在这里插入图片描述

475. 供暖器

逻辑:每个房子选最近的热水器,再在这些最近距离中选最大的距离,即为答案。
实现:如何为房子找到最近的热水器距离,可以将heaters升序排序,之后二分查找。当当前热水器位置大于房子位置时,我们可以再期待有距离房子更近的热水器,即right=mid-1。当当前热水器位置小于房子位置时候,left=mid+1。换句话说,总是期待更接近房子位置的热水器。heater[left]–>house<–heater[right]。

int findRadius(vector<int>& houses, vector<int>& heaters) {
        sort(heaters.begin(),heaters.end());
        int houseMinDis=INT_MIN;
        for(auto ho:houses){//二分查找距离每个房子最近的热水器,并在这些最近距离中选最大距离
            houseMinDis=max(FindHouseMinDis(0,heaters.size()-1,ho,heaters),houseMinDis);
        }
        return houseMinDis;
    }

    int FindHouseMinDis(int left,int right,int ho,const vector<int>& heaters){
        int ans=INT_MAX;
        while(left<=right){
            int mid=left+(right-left)/2;
            int dis=heaters[mid]-ho;
            ans=min(ans,abs(dis));
            if(dis>=0){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        cout<< -1/2<<" ";
        return ans;
    }

1102题,得分最高的路径

这个题也是二分,先二分再dfs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值