二分算法学习

这篇具有很好参考价值的文章主要介绍了二分算法学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🌼 扎着马尾的姑娘,笑容温柔很善良
自在的少年 - 要不要买菜 - 单曲 - 网易云音乐

前言

本来打算做蓝桥杯2022C++A组省赛F题青蛙过河的,看到标签显示"二分",第一时间竟然想不到二分是什么,所以来学习下

目录

🌼二分是什么 

🌼一,砍树

🌼二,手写快排

🌼三,阶乘末尾0的个数

🌼四,序列合并

代码1    优先队列 

代码2    二分 

🌼五,银行贷款

🌼六,1137: 灯泡的高度

🌼七,P1918 保龄球

📚总结


🌼二分是什么 

概念

部分知识来自    二分 - OI Wiki (oi-wiki.org)

挺好的算法搜索网站,大家可放到收藏夹,专门搜算法用

二分查找(binary search),也称折半搜索(half-interval search)或对数搜索(logarithmic search)

用来在有序数组(单调增减)中查找某一元素的算法

比如,在升序数组中

每次查找当前部分中间元素,如果中间元素是要找的,结束搜索

如果小于所查找的值,左侧只会更小,所以在右侧查找

如果大于,则在左侧查找

二分查找最优时间和空间复杂度都是O(1),最差时间和空间复杂度都是O(logn

模板 

模板只提供一个思路,不能照搬 

int binary_search(int left, int right, int key) 
{
    int ret = -1; //未搜索到数据返回-1下标
    int mid;
    while(left <= right) {
        mid = left + ((right - left) >> 1); //避免溢出,用该算法
        if(key > a[mid]) left = mid + 1;
        else if(key < a[mid]) right = mid - 1;
        else { //最后检测相等
            ret = mid;
            break;
        }
    }
    return ret; //单一出口
}

 对于一个长度为n的数组,若n是有符号数,当n >= 0, n >> 1比 n / 2更快,且只能用于整数

使用条件 

1,有序(广义有序,查找满足某种条件的最大最小值)

2,比如要找最大值,首先想到从小到大枚举,若答案单调,可使用二分提高效率

3,固定区间; 判断某个值是否符合条件; 可行解对于区间满足一定单调性

题目加深理解

🌼一,砍树

P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

二分算法学习

二分算法学习

标签: 二分, 普及/提高-

1,可以在1~10^9枚举,但是这种朴素写法会超时,只适合在蓝桥杯骗分

2,可以sort()排序再优化砍多少米

3,由于要学习二分,我们采用二分 

发现的问题 

1,right不要声明为全局变量,会与#include<iostream>库里的属性或方法重名

2,大数组,比如long long a[1000010];  要声明在主函数外作为全局变量,因为主函数内用存储,栈的空间没那么大,会溢出,导致调试时,无法输入,而全局变量在静态存储区分配,空间很大

3, left <= right  right = mid - 1  mid + 1  printf("%lld", mid - 1)这几行代码,需要自己多弄几组数据测试

否则会出现Ac30% 或50%等情况

4,最好将所有整型声明为long long,避免后续操作导致的溢出(注意,因为习惯性int i ,可能出错)

代码1  AC50% 

#include<iostream>
#include<cstdio> //scanf()
using namespace std;
long long n, m, sum, mid, a[1000010];
int main()
{
    long long right = 0, left = 0; //初始左右边界
    scanf("%lld%lld", &n, &m);
    for(int i = 0; i < n; ++i) {
        scanf("%lld", &a[i]);
        right = max(a[i], right); //最高的树作为初始右边界
    }
    while(left <= right) {
        sum = 0; //更新
        mid = (left + right) >> 1; //mid为伐木高度
        for(int i = 0; i < n; ++i)
            if(a[i] > mid) sum += a[i] - mid;
        if(sum < m) right = mid - 1;
        else left = mid + 1;
    }
    printf("%lld", mid - 1);
    return 0;
}

 代码1过了两个样例,但是在下面例子中输出了0,应该输出1才是

5 20
1 3 5 7 10

问题出在最后的printf(),不是mid - 1(50%),不是mid(50%),也不是left(wa),是right(100%)

代码逐行解析:

mid为伐木高度,但不是最终输出答案

left左边界,right右边界,数组a存储所有树木高度

sum为砍伐后获得树木总长度

关键1

第16行mid = (left + right) >> 1等价于mid = (left + right) / 2,位运算速度更快

关键2

第19~20行right = mid - 1和left = mid + 1

这三行实现了砍树高度的二分

由于题目要求的是,刚好能得到>=m米木材的临界点,所以输出right

Ac 100%代码 

#include<iostream>
#include<cstdio> //scanf()
using namespace std;
long long n, m, sum, mid, a[1000010];
int main()
{
    long long right = 0;
    scanf("%lld%lld", &n, &m);
    for(int i = 0; i < n; ++i) {
        scanf("%lld", &a[i]);
        right = max(a[i], right); //最高的树作为初始右边界
    }
    long long left = 0; //初始左边界
    while(left <= right) {
        sum = 0; //更新
        mid = (left + right) >> 1; //mid为伐木高度
        for(int i = 0; i < n; ++i)
            if(a[i] > mid) sum += a[i] - mid;
        if(sum < m) right = mid - 1;
        else left = mid + 1;
    }
    printf("%lld", right);
    return 0;
}

🌼二,手写快排

P1026 - 排序 - New Online Judge (ecustacm.cn)

二分算法学习​ 

标签: 入门题 

因为快排 = 二分 + 递归,所以通过再次手写快排加深对二分的理解

快速排序最好的时间复杂度和二分平均时间复杂度一样,都是O(logn),而最差时间复杂度为O(n^2) 

#include<iostream>
using namespace std;
int a[100010]; //声明为全局,不用传参
void quick_sort(int left, int right)
{
    if(left > right) return;
    int i = left, j = right, base = a[left];
    while(i < j) {
        while(i < j && a[j] >= base) j--; //j游标先行
        while(i < j && a[i] <= base) i++; //i游标后走
        //退出上面两循环后,i,j分别指向大于base和小于base的值
        if(i < j) {
            a[i] = a[i]^a[j];
            a[j] = a[i]^a[j];
            a[i] = a[i]^a[j]; //异或交换两数
        }
    }
    a[left] = a[j]; //j先行,此时i,j指向的元素必要小于基数
    a[j] = base; //交换完毕后,左边都小于base,右边都大于base
    quick_sort(left, j - 1); //对左边递归
    quick_sort(j + 1, right); //对右边递归
}
int main()
{
    int n;
    cin>>n;
    for(int i = 0; i < n; ++i) cin>>a[i];
    quick_sort(0, n - 1);
    for(int i = 0; i < n; ++i) cout<<a[i]<<" ";
    return 0;
}

核心代码也就十几行

🌼三,阶乘末尾0的个数

(一)标签:入门题

二分算法学习

因为n!中的n可达10^9,直接递归肯定超时,我们转换个思路

1,求0的个数,也就是求n!能被10整除多少次

2,由于10 = 5 * 2,5 * 任意偶数都能得到10

3,所以转化为求n中5因子的个数

#include<iostream>
using namespace std;
int main()
{
    long long n;
    while(cin>>n) {
        int sum = 0; //sum = 0要放在外层while里
        while(n) {
            sum += n / 5;
            n /= 5;
        }
        cout<<sum<<endl;
    }
    return 0;
}

(二)标签:基础题,二分

二分算法学习

首先,基于上一题,我们可以写个函数求n!中0的个数

其次,想要用二分来提高效率,首先得明确右边界,就是最大值

容易知道 100! 有24个0,同理 1000! 大约有240个0,所以要求10^8个0,大约得4*10^8阶乘

所以右边界给它算10^12,往大了开,反正long long到10^8

有一个坑,题目要求的是最小的N,比如输入2后,10!和12!都有2个0,这时你输出13就不对,因为不是最小的

第一次好歹还能输出个答案,虽然不是最小N,为了输出最小N,我加了一个限制条件,就输出了一堆屁 

一堆屁 

#include<iostream>
using namespace std;
long long q, flag = 1, ans, temp;
long long zero(long long n)
{
    int sum = 0;
    while(n) {
        sum += n / 5;
        n /= 5;
    }
    return sum;
}
long long check(long long q)
{
    long long left = 0, right = 1000000000000, mid; //10^12
    while(left <= right) {
        mid = (left + right) >> 1; //中间值
        if(zero(mid) < q) left = mid + 1;
        else if(zero(mid) > q) right = mid - 1;
        else {//检测相等
            return mid;
        }
    }
}
int main()
{
    cin>>q;
    while(1) {
        ans = check(q);
        temp = ans;
        while(zero(--temp) == q) ans--;
        cout<<ans;
        break;
    }
    return 0;
}
2
429496729635

 以前也遇到过类似情况,一时想不起来了

思路:同样是上一个代码的想法,找 n! 中 0 的个数,就是求 n 中 因子5的数量,忽略了这个思路,代码就复杂许多,各种出错AC不了不足为奇 

AC代码之❌ 

#include<cstdio> //scanf(), printf()
long long zero(long long n)
{
    long long sum = 0;
    while(n) {
        sum += n / 5;
        n /= 5;
    }
    return sum; //0的个数
}
int main()
{
    long long q;
    scanf("%lld", &q);
    for(int i = 1;; ++i) {
        if(zero(i * 5) == q) { //遍历时只需对5的倍数遍历即可
            printf("%lld", i * 5);
            break;
        }
        else if(zero(i * 5) < q && zero(i * 5 + 5) > q) {
            printf("No solution");
            break;
        }
    }
    return 0;
}
2
-8589934582

发现问题了吗,代码第15行,int i放入zero(long long)是不匹配的

AC代码之 

#include<cstdio> //scanf(), printf()
long long zero(long long n)
{
    long long sum = 0;
    while(n) {
        sum += n / 5;
        n /= 5;
    }
    return sum; //0的个数
}
int main()
{
    long long q;
    scanf("%lld", &q);
    for(long long i = 1;; ++i) {
        if(zero(i * 5) == q) { //遍历时只需对5的倍数遍历即可
            printf("%lld", i * 5);
            break;
        }
        else if(zero(i * 5) < q && zero(i * 5 + 5) > q) {
            printf("No solution");
            break;
        }
    }
    return 0;
}

不用二分了,有点麻烦,,,但是锻炼的效果已经达到了(好歹写了一堆屁出来) 

🌼四,序列合并

P1102 - 序列合并 - New Online Judge (ecustacm.cn)

二分算法学习​ 二分算法学习

标签:基础题,二分

可以用优先队列,也可以用二分

思路1    优先队列

我也第一次接触,先来个科普文

(6条消息) C++优先队列priority_queue详解_是一只派大鑫的博客-CSDN博客_priority_queue头文件

因为要输出前n个最小值,利用优先队列自动排序的特点很好做

默认是最大值优先队列,即最大值在顶端

priority_queue<int,vector<int>,less<int>>p2;//最大值优先队列
priority_queue<int,vector<int>,greater<int>>p3;//最小值优先队列

在这里,我们作个比较,的声明是这样的:

#include<stack> //st.pop(), st.push() 
int main()
{
    stack<int>st;
}

 而优先队列的声明,是这样的:

(注意,#include<queue>using namespace std;两行要配合使用)

#include<queue> 
using namespace std;
int main()
{
    priority_queue<int>q;
}

核心代码第24,25行,利用了最大值优先队列中,最大值始终在队首的特点

代码第17,18行,对数组a, b排序,是为了第27行可以break,不至于超时

代码1    优先队列 

#include<cstdio> //scanf(), printf()
#include<algorithm> //sort()
#include<queue> //1
using namespace std; //2

int a[100010], b[100010];
int main()
{
    priority_queue<int>q; //3
    int n, i, j;
    scanf("%d", &n);
    for(i = 0; i < n; ++i)
        scanf("%d", &a[i]);
    for(i = 0; i < n; ++i)
        scanf("%d", &b[i]); //输入
    sort(a, a + n);
    sort(b, b + n); //排序

    for(i = 0; i < n; ++i) q.push(a[0] + b[i]); //入队n个元素
    for(i = 1; i < n; ++i)
        for(j = 0; j < n; ++j) {
            if(a[i] + b[j] < q.top()) {
                q.pop(); //核心代码
                q.push(a[i] + b[j]); //核心代码
            }
            else break; //后面必定更大,可以直接break
        }
    //最大值优先队列,最大值在顶端,所以逆序保存
    for(i = n - 1; i >= 0; --i) {
        a[i] = q.top(); //最大值放最后
        q.pop(); //出队
    }
    for(int i = 0; i < n; ++i)
        printf("%d ", a[i]);
    return 0;
}

--------------------------------------------------------------------------------------------------------- 

思路2    二分 

代码中两层for遍历时,出现2次else break; 这步很重要,因为排序后单调递增,所以后续没必要比较,不用就超时

第二,由于要使用二分,加上单个数10^9,右边界最大2*10^9,左边界最大也可能接近2*10^9,所以相加时int会超限,所以用long long

当然,也可以mid = left + (right - left) >> 1,这样用int也是可以的

第一次敲出来后,在第40行报错 error: invalid types long long int ... ... for subscript

百度说

1,数组变量名敲错 / 未定义

2,数组超限

3,变量名数组名重复定义

4,个人变量名与C++库的变量名冲突

if(a[i][j] <= right) c[num++] = a[i][j];

原来是把a[i] + b[j]写成了a[i][j]🤦‍ 

注意!!! 不要照搬模板,比如下面核心代码中,第33,35,36行,

第33行要left < right,如果加上 = 会时间超限 AC 0%

第35,36行,如果改成right = mid, left = mid会超限并AC 20%

代码2    二分 

#include<iostream>
#include<cstdio> //scanf(), printf()
#include<algorithm> //sort()
using namespace std;
typedef long long LL;
LL a[100010], b[100010], c[100010], n, i, j;

bool check(long long x) //return false这样的,用bool
{
    LL ans = 0;
    for(i = 0; i < n; ++i)
        for(j = 0; j < n; ++j) {
            if(a[i] + b[j] <= x) ans++;
            else break; //这步很重要

            if(ans == n) return true; //x可能小了
        }
    return false; //x大了
}

int main()
{
    scanf("%d", &n);
    for(i = 0; i < n; ++i)
        scanf("%lld", &a[i]); //lld
    for(i = 0; i < n; ++i)
        scanf("%lld", &b[i]); //lld
    sort(a, a + n);
    sort(b, b + n);
    //初始左右边界
    LL left = a[0] + b[0], right = a[n - 1] + b[n - 1];
    //二分核心代码
    while(left < right) { //<
        LL mid = (left + right) >> 1;
        if(check(mid)) right = mid - 1; //mid - 1
        else left = mid + 1; //mid + 1
    }
    LL num = 0;
    for(i = 0; i < n; ++i)
        for(j = 0; j < n; ++j) {
            if(a[i] + b[j] <= right) c[num++] = a[i] + b[j];
            if(num == n) break;
        }
    sort(c, c + n);
    for(i = 0; i < n; ++i) printf("%lld ", c[i]); //记得用lld
    return 0;
}

🌼五,银行贷款

P1163 银行贷款 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

如果是正向(提供月利率求还清款项的月数),很简单

无奈本题反向,需要二分,无非就是写个正向的check()函数,主函数里二分即可 

二分算法学习

标签:普及-,数学,二分

第一次敲出来了,但输出不对,debug半小时也没找到原因,写写改改太混乱了,所以重写

需要注意的是

1,先计算复利再还钱(第一个

2,printf()输出双精度要用%f,不能用%lf (第二个

3,因为求得是百分数,最后的mid要*100

AC 代码 

#include<cstdio> //scanf()
using namespace std; //cout
double debt, p, num; //欠款, 每月还款, 还清月数
double check(double m) //monthly interest月利率
{
    double d = debt, pp = p, n = num;
    while(n--) {
        d += d * m; //先计算复利, += 欠债 * 月利率
        d -= pp; //再还钱, -= 每月还款
    }
    return d; //返回剩余欠款
}
int main()
{
    scanf("%lf%lf%lf", &debt, &p, &num);
    double left = 0, right = 10; //1000%
    while(1) {
        double mid = (left + right) / 2;
        if(check(mid) < 0) left = mid;
        if(check(mid) > 0) right = mid;
        if(check(mid) == 0 || right - left < 0.0001) //精度
        {
            printf("%.1f", mid * 100); //输出%f就好
            break;
        }
    }
    return 0;
}

🌼六,1137: 灯泡的高度

P1137 - 灯泡的高度 - New Online Judge (ecustacm.cn)

标签:基础题,二分

二分算法学习

二分算法学习

思路

1,在二分模板里加了个for循环,根据给定的公式,从左往右推,直到第n个灯泡

2,注意,除了n和flag是int,其他都声明为double(最大10^308,小数上似乎可以到1e-16)

3,初始要设置一个精度eps

4,关于精度eps和右边界r的设置,你们可以尝试下,r = 1e3只能AC95%,而eps = 1e-4只能AC55%

分析

二分算法学习

AC  代码

明显的二分模板

#include<iostream>
#include<iomanip> //setprecision(), setiosflags(ios::fixed)
#include<cstdio> //printf()
using namespace std;
const double eps = 1e-8; //精度
double ans;
int main()
{   //注意, 除了n, flag是int, 其他都是double
    int n;
    double a;
    cin>>n>>a;
    double l = 0, r = 1e10; //left,right 左右边界
    //二分
    while(r - l > eps) {
        double mid = (l + r) / 2;
        double pre1 = a, pre2 = mid;
        int flag = 1;
        for(int i = 2; i < n; ++i) { //最后到下一位, 所以i到n - 1
            double temp = pre2;
            pre2 = pre2 * 2 - pre1 + 2; //pre2前进一位
            pre1 = temp; //pre1前进一位
            if(pre2 < eps) {
                flag = 0;
                break; //不满足高度大于0条件
            }
        }
        if(flag) { //B可能的答案, 但B仍需变小
            ans = pre2;
            r = mid; //右边界左移
        }
        else //出现了高度小于0的情况
            l = mid; //左边界右移
    }
    //cout<<setprecision(2)<<setiosflags(ios::fixed)<<ans;
    printf("%.2f", ans);
    return 0;
}

我尝试将代码第14,29,32行按模板常规做法修改,输出的不是最小值了

while(r - l > eps) --> while(r - l > 0)
r = mid; --> r = mid - 1;
l = mid; --> l = mid + 1;
8 15
10.19

而正确答案应该是9.75,先记套路吧

🌼七,P1918 保龄球

P1918 保龄球 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

标签:模拟,二分,普及-

二分算法学习

二分算法学习

2个月没碰二分,又忘光了,,所幸经过这题的回顾,又记起来了

思路

刚开始做,忘记结构体和排序了,,,难怪那么多能找到的都输出了0,,太久没做了实在是

1,结构体int value, id; 将编号和对应的值联系起来

2,对数组升序排序

3,套二分模板,当然具体的left < right还是<=,以及left = mid + 1,right = mid - 1还是

left = mid,right = mid,需要自己多测几组数据(包含奇偶数)

额外的测试

7 4 3 8 16 20 13 82 17 34 50 1
12
7
1
4
2
3
3
8
4
16
5
1
12
50
11
34
10
17
9
82
8
13
7
20
6

AC  代码

#include<iostream>
#include<cstdio> //scanf()
#include<algorithm> //sort()
using namespace std;
struct node
{
    int v, id; //value和id
}a[1000010];

bool cmp(node x, node y)
{
    return x.v < y.v;
}
int main()
{
    int n, q;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {//下标1开始
        scanf("%d", &a[i].v);
        a[i].id = i;
    }
    sort(a + 1, a + n + 1, cmp); //对1~n按value升序排序
    scanf("%d", &q);
    int num;
    for(int i = 0; i < q; ++i) {
        scanf("%d", &num);
        int flag = 1;
        //二分
        int l = 1, r = n; //左右边界
        while(l <= r) {
            int mid = (l + r) / 2;
            if(num < a[mid].v) r = mid - 1;
            else if(num > a[mid].v) l = mid + 1;
            else if(num == a[mid].v) {
                cout<<a[mid].id<<endl;
                flag = 0; //有解
                break;
            }
        }
        if(flag) cout<<0<<endl;
    }
    return 0;
}

📚总结

1,了解了二分模板和概念,比如使用于有序数组,比如明确左右边界

2,加强了对枚举遍历骗分的认识

3,大数组要声明为全局变量,long long可防止后续操作爆int

4,有简便方法就换简便方法,思路一变天地宽

5,输入的数,要与函数形参的类型对应

6,优先队列的声明

#include<queue> 
using namespace std;
priority_queue<int>q; //默认最大值优先队列
priority_queue<int,vector<int>,less<int>>p2;//最大值优先队列
priority_queue<int,vector<int>,greater<int>>p3;//最小值优先队列

7,二分遇到不需要再比较的情况,及时break

8,printf()输出双精度%f就行,%lf不行 文章来源地址https://www.toymoban.com/news/detail-411464.html

到了这里,关于二分算法学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法】二分查找(整数二分和浮点数二分)

    大家好!今天我们来学习二分查找算法,这是一种效率很高的算法哦! 目录 1. 整数二分 2. 整数二分模板 3. 整数二分模板题 3.1 洛谷 P2249 【深基13.例1】查找 3.2 Acwing789. 数的范围 4. 浮点数二分 5. 浮点数二分模板 6. 浮点数二分模板题 6.1 Acwing 790.数的三次方根 6.2 洛谷 P1024 [

    2024年02月10日
    浏览(52)
  • 【算法系列篇】二分查找——这还是你所知道的二分查找算法吗?

    在生活中,我们往往会遇到在数组中查找某个确定的元素的时候,通常我们会选择使用暴力解法,这样虽然简单,但是时间复杂度是O(N),时间效率比较低。那么是否有方法可以使得在具有二段性的数组中找某一特定的元素的时间复杂度低于0(N)呢?答案是肯定的,当我们可以

    2024年02月11日
    浏览(52)
  • 【算法】简单的二分查找算法

    一个简单的二分查找算法:         简单描述:算法由静态方法rank()实现,它接受一个整数键和一个有序的int数组作为参数,如果整数存在于数组,返回它的索引,否则返回-1,算法使用两个变量lo和hi,并保证整数如果存在于数组中则它一定存在于a[lo...hi]中,然后通过循

    2024年01月21日
    浏览(57)
  • 【算法小课堂】二分查找算法

    当我们要从一个序列中查找一个元素的时候,最快想到的方法就是顺序查找法(即:从前到后依次查找)。但这种方法过于无脑,就是暴力的把每个元素都排查一遍。元素个数少的时候还行,一旦元素个数多起来,效率是非常低下,所以在实际中这种查找的方法是被摒弃的。

    2024年02月08日
    浏览(39)
  • 【算法杂货铺】二分算法

    目录 🌈前言🌈 📁 朴素二分查找  📂 朴素二分模板 📁 查找区间端点处 细节(重要)  📂 区间左端点处模板  📂 区间右端点处模板 📁 习题 1. 35. 搜索插入位置 - 力扣(LeetCode) 2. 69. x 的平方根 - 力扣(LeetCode) 3.153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

    2024年04月13日
    浏览(45)
  • 二分查找算法 | 你真的搞懂二分了吗?

    我身边的人都认为二分查找很简单,但事实真是如此吗?不,并不简单。二分算法有着许多的 边界问题 ,当你写着代码一不小心就会陷入死循环。本篇文章会深入细节详细介绍 整数二分算法 以及使用 二分算法步骤 和 力扣题目练习 ,并且还会给出 二分查找算法模板 ,下面

    2023年04月10日
    浏览(46)
  • 【算法基础:搜索与图论】3.6 二分图(染色法判定二分图&匈牙利算法)

    https://oi-wiki.org/graph/bi-graph/ 二分图是图论中的一个概念, 它的所有节点可以被分为两个独立的集合,每个边的两个端点分别来自这两个不同的集合 。 换句话说, 二分图中不存在连接同一集合内两个节点的边 。 如何判断一个图是二分图? 当且仅当图中不含奇数环 。(奇数

    2024年02月16日
    浏览(43)
  • 扫地机器人(二分算法+贪心算法)

    1.  if(robot[i]-len=sweep)这个代码的意思是——如果机器人向左移动len个长度后,比现在sweep的位置(现在已经覆盖的范围)还要靠左,就是覆盖连续不起来,呢么这个len就是有问题的,退出函数,再继续循环。 2.  显然当每个机器人清扫的范围相同时,所用时间最小,所以这时

    2024年01月20日
    浏览(46)
  • 【算法集训】基础算法:二分查找 | 概念篇

    二分枚举,也叫二分查找,指的就是给定一个区间,每次选择区间的中点,并且判断区间中点是否满足某个条件,从而选择左区间继续求解还是右区间继续求解,直到区间长度不能再切分为止。 由于每次都是把区间折半,又叫折半查找,时间复杂度为 O(logn),和线性枚举的求

    2024年04月11日
    浏览(46)
  • Python数据结构与算法篇(五)-- 二分查找与二分答案

    1.1 定义         二分查找又称折半查找、二分搜索、折半搜索等,是一种在静态查找表中查找特定元素的算法。         所谓静态查找表,即只能对表内的元素做查找和读取操作,不允许插入或删除元素。         使用二分查找算法,必须保证查找表中存放的是有

    2023年04月20日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包