二分法

1、时间复杂度分析

T(n) = T(n/2) + O(1) = O(logn)

二分法:用O(1)时间将规模为n的问题变为n/2规模的问题。
O(n)->O(1)
推导
在这里插入图片描述

2、二分法解决的问题

  • 在一个数组中查找一个特定值,一般会是查找某个值(target)在该数组中第一次出现的位置,或者最后一次出现的位置,又或者是任何出现的位置。
  • 问题可以一分为二的解决,前一半满足一个特点,后一半满足又一个特点,进而可缩小一半去寻找。九章算法中的原话是,二分法之OOOOXXXX问题。
  • 问题规模总会一版一半的减少,从而达到O(log(n))的复杂度,也是真个二分的本质,这样的题不容易看出是二分问题。

另外,当你已经实现了复杂度为O(n)的算法,但有人还问你有没有更好的算法,那这个问题基本上就是让你用二分来实现,这属于用时间复杂度反推用什么算法。

3、算法模板

下面是九章算法课程中的一个二分法模板(C++实现):用于实现寻找第一个出现位置的问题。

/**
* 本参考程序由九章算法用户提供。版权所有,转发请注明出处。
* - 九章算法致力于帮助更多中国人找到好的工作,授课老师均来自硅谷和国内的一线大公司在职工程师。
* - 现有的求职课程包括:九章算法班 2020升级版,算法强化班,算法基础班,北美算法面试高频题班,Java 高级工程师 P6+ 小班课,面试软技能指导 - BQ / Resume / Project 2020版
* - Design类课程包括:系统设计 System Design,面向对象设计 OOD
* - 专题及项目类课程包括:动态规划专题班,Big Data - Spark 项目实战,Django 开发项目课
* - 更多详情请见官方网站:http://www.jiuzhang.com/?utm_source=code
*/
#include <vector>
using namespace std;

class Solution {
public:
    /**
     * @param array source array
     * @param target target to search
     * @return the first occurrence position of target 
     */
    int binarySearch(vector<int> &A, int target) {
        if (A.size() == 0) {
            return -1;
        }

        int start = 0;
        int end = A.size() - 1;
        int mid;

        while (start + 1 < end) {
            mid = start + (end - start) / 2;
            if (A[mid] == target) {
                end = mid;
            } else if (A[mid] < target) {
                start = mid;
            } else if (A[mid] > target) {
                end = mid;
            }
        }

        if (A[start] == target) {
            return start;
        }
        if (A[end] == target) {
            return end;
        }

        return -1;
    }
};

4、上面二分模板的说明

1、如果是寻找最后一个出现位置的问题的话,只需
(1)将上面

 if (A[mid] == target) {
     end = mid;
 }
 ...

这个部分中if语句中的语句换为start = mid
(2)将程序中最后两个if语句互换一下顺序。
2、如果是寻找任意出现位置的话,用寻找第一次出现位置或寻找最后一次出现位置的模板都可以。
3、注意程序中while语句的判断条件是start + 1 < end
还有mid = start + (end - start) / 2实际上是(start + end) / 2的几乎等价写法,之所以这样写是为了防止start + end太大会超过数值运算范围。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值