二分算法 再次理解

二分算法 再次理解

详解二分查找算法

这篇博客很详细介绍了二分算法的一些细节问题

寻找一个数,也是最基本的二分搜索

//代码示例如下
int bsearch(int []nums, int target)
{
    int left=0, right=nums.length-1;//这里的数组长度用法可以是其他的形式
    while(left<=right)
    {
        int mid = left + (right - left) / 2;
        if(num[mid] == target)
            return mid;
        else if(num[mid] > target)
            right = mid - 1;
        else left = mid + 1;
    }
    return -1;//没有找到
}

寻找左侧边界的二分搜索

这里的代码实现和lower_bound(begin,end+1, target)相同,都是找到第一个大于等于target的数组下标。

int left_bound(int[] nums, int target)
{
    if(nums.length == 0) return -1;
    int left = 0, right = nums.length; //注意这里的边界设置是左闭右开的。
    while(left < right)
    {
        int mid = left + (right - left) / 2;
        if(nums[mid] >= target)
            right = mid;//有边界进行压缩,依旧保持左开右闭的形式
        else left = mid+1;
    }
    return left; //注意这里的left不一定是准确位置,这里的left有特殊含义
}
nums: 1 2 2 4
index: 0 1 2 3

如果使用这个左侧二分搜索2,那么将会返回1,表示在nums数组中有一个元素小于2,其他的类似。但是这样也存在一些问题,如果我们搜索1或者-1的时候,返回的值都是0,但是两者的含义是不同的,所以再收到结果后需要进行判断,以免出错。当然这里如果搜索的值为8的时候返回为值为4,也就是数组最后一个元素的下一个元素,这里也需要进行注意。

寻找右侧边界的二分查找

int right_bound(int[] nums, int target)
{
    if(nums.length==0) return -1;
    int left = 0, right = nums.length;
    whlie(left < right)
    {
        int mid = left + (right - left) / 2;
        if(nums[mid] <= target)
            left = mid + 1; //左边界进行压缩
        else right=mid; //右边都是直接等于mid
    }
    return left - 1;//这里有点不同,这里需要进行减一,特殊需要进行记忆。
}

这里的注意点就是返回值需要进行减一

这篇文章是自己看到那篇博客的一些领会,详细参阅还是需要看看原文章,链接再最上面

原文地址:https://www.cnblogs.com/alking1001/p/12242408.html

时间: 2024-10-12 23:46:26

二分算法 再次理解的相关文章

对二分算法的理解及结对编程情况

一.对二分算法理解 二分算法,又称折半算法,是应用分治策略的典型例子.二分查找主要对有序序列进行对所指定数字的查找,通过不断缩小搜查范围,在比较中间的数后对左右两个数组进行相同操作,以得到最终的带查找数字.时间复杂度logn,对数组较大时能显著提高程序效率. 二.算法代码 #include <iostream>using namespace std;int main(){ int n,x; cin >> n; if(1<=n<=100){  int a[n];  for

C语言实现直接插入排序,冒泡排序以及二分查找(巩固理解记忆)

C语言实现直接插入排序,冒泡排序以及二分查找(巩固理解记忆) 虽然直接插入排序,冒泡排序以及二分查找是算法中最为基础以及老掉牙的话题,但作为一名算法的深爱者,有时候无聊时候总会将这些简单的话题重新理解并敲写一番,目的只是为了得到理解娴熟的程度.而且,我觉得越是简单基础的东西,有时候更应该反复的去敲写,深化它,并最终让其中的思想内化为自己的一部分.待到他日一提起之时,会相当娴熟的"刷刷刷..."几分钟搞定,那就很有成就感了! 因为我喜欢对于一个问题进行实例的剖析,进而再转化为特有的用某种

KPM算法初步理解

一个字符串"FBCABCDABABCDABCDABYW"中是否包含另外一个字符串"ABCDABY"? 上面这道题目是一个经典的字符串匹配的题目,对于字符串匹配,比较好的算法里很容易想到KPM算法,那KPM算法是干什么的?为什么说KPM比较优秀? 给定一个字符串O和F,长度分别是m.n,判断F是否在O中出现,如果出现则返回出现的位置.常规方法是遍历O的每一个字符,与F的每一个字符进行比较,但是这种方法的时间复杂度是T(m*n),但是KPM算法使得时间复杂度为T(m+n

对动态规划算法的理解及相关题目分析

1.对动态规划算法的理解 (1)基本思想: 动态规划算法的基本思想与分治法类似:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中得到原问题的解.但是,与分治法不同的是,为了避免重复多次计算子问题,动态规划算法用一个表记录所有已解决的子问题的答案,不管该子问题以后是否被利用,只要它被计算过,就将其结果填入表中. (2)设计动态规划算法的步骤: ①找出最优解的性质,并刻画其结构特征 ②递归地定义最优值 ③以自底向上的方式计算最优值 ④根据计算最优值时得到的信息构造最优解 (3)

KMP算法详细理解

KMP算法详细理解 从昨天开始看KMP算法到今天凌晨..... 把一些知识点进行总结,其实KMP还是挺简单的(HHHHHH) 博客新地址:https://miraitowa2.top/ 1:BF(暴力匹配)算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如

递推算法与二分算法

递推算法: (一)斐波那契数列 以下数列0 1 1 2 3 5 8 13 21 …被称为斐波纳契数列. 这个数列从第3项开始,每一项都等于前两项之和. 输入一个整数N,请你输出这个序列的前N项. 输入格式 一个整数N. 输出格式 在一行中输出斐波那契数列的前N项,数字之间用空格隔开. 数据范围 0<N<460<N<46 输入样例: 5 输出样例: 0 1 1 2 3 #include<iostream> using namespace std; int f[100];

递归和二分算法

递归程序调用自身的编程方法称为递归(recursion) 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量.递归的能力在于用有限的语句来定义对象的无线的集合.一般来说,递归需要有边界条件.递归前进段和递归返回段.当边界条件不满足时,递归前进:当边界条件满足时,递归返回. 递归的两个条件: 1,每一次的调用都会使问题的规模有所减少 2,必须有一个明确的终止条件 python中测试的递归

POJ1523(求连用分量数目,tarjan算法原理理解)

SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7406   Accepted: 3363 Description Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a

01背包算法的理解

01背包问题: 有N件物品和一个最大重量限制为V的背包.第i件物品的重量是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的重量总和不超过V,且价值总和最大.每个物品只有1份,且不可分割 看了01背包算法,言简意赅,但理解起来头昏脑胀,不得要领.尝试解释下对该算法的理解,加深记忆. 假设最优解已经存在,怎么判断一个物品i是否在背包里?  简单,只要知道, 1.c[i]是否大于V, 2.F[i-1][V-c[i]],即没有i物品的情况下,最大重量限制为V-c[i]的最优解. 3.F[i