算法基础(二分)

作者: 阁下_3258 | 来源:发表于2022-07-19 15:38 被阅读0次

二分的性质

若一组数有单调性则一定可以二分,但可以二分的题目不一定有单调性(有单调性则一定可以二分,没有单调性也有可能可以二分)

二分的本质(边界):若给定一组数据在这组数据上定义了某种性质,使得这个性质若在右半边满足则左半边一定不满足则可以使用二分

整数二分

代码模板

//区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用 模板1
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = (l + r) / 2;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
-----------------------------------------------------------------------------------------
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用 模板2
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = (l + r + 1) / 2;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

注(模板2):l = r-1时及lr只差一的时候若mid = (l + r) / 2代入特殊值l = 1,r = 2mid = (1+2)/2 = 1mid = l区间没变进入死循环

例题: 0到n-1中缺失的数字

题目描述

一个长度为 n−1n−1 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 00 到 n−1n−1 之内。在范围 00 到 n−1n−1 的 nn 个数字中有且只有一个数字不在该数组中,请找出这个数字。

数据范围: 1≤ n ≤1000

样例
输入:[0,1,2,4]

输出:3

算法分析

通过上述样例可以看出缺失数字左面的数字和下标相同,而缺失数字右面的数字和小标不同,而且区间[l, r]可以通过是否下标等于对应数字被划分成[l, mid]和[mid + 1, r],所有使用模板1。另外要注意特殊情况:当所有数都满足nums[i] == i时,表示缺失的是 n。

C代码

int getMissingNumber(int* nums, int numsSize) {
    int l = 0, r = numsSize - 1, mid ;
    if(numsSize == 0) return 0;
    while( l < r)
    {
        mid = l + r >> 1;
        if(mid == nums[mid])
            l = mid + 1;
        else
            r = mid;
    }
    if(nums[r]== r) r++;
    return r;
}

浮点数二分

代码模板

double bsearch_3(double l, double r)
{
    while (r - l > 1e-6)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

注:1e-6表示计算精度,一般题目若要求精确至小数点后4位用1e-6,及精确至小数点后n位用1e-(n+2)

例题: 剪绳子

题目描述

有 N 根绳子,第 3 根绳子长度为 L₃,现在需要 M 根等长的绳子,你可以对 N 根绳子进行任意裁剪(不能拼接),请你帮忙计算出这 M 根绳子最长的长度是多少。

数据范围

1≤N,M≤100000,
0<Li<10^9

输入格式

第一行包含 2 个正整数 N、M,表示原始绳子的数量和需求绳子的数量。

第二行包含 N 个整数,其中第 i 个整数 Li 表示第 i 根绳子的长度。

样例

3 4
3 5 4

输出格式

输出一个数字,表示裁剪后最长的长度,保留两位小数。

样例

2.50

样例解释

第一根和第三根分别裁剪出一根 2.50 长度的绳子,第二根剪成 2 根 2.50 长度的绳子,刚好 4 根。

算法分析

因为0<Li<10^9所有另l=0 r=1e9mid = (l + r) / 2定义一个函数判断按照长度为mid截取是否可以截取够需求的数量,若可以则证明mid左面的数均可以所以令l=mid用来判断右面的数以求出最优解;反之则证明mid右面的数均不满足,另令r=mid用来继续判断左面以找出满足的解。

C代码

#include<stdio.h>

int a[100010];
int n , m ;

int panduan(double mid)
{
    int num=0 , i;
    for(i = 0 ; i < n ; i ++)
        num += a[i] / mid;
    int t=0;
    if(num >= m) t = 1 ;
    return t;
}

main()
{
    int i;
    scanf("%d%d",&n,&m);
    for(i = 0 ; i < n ; i ++)
        scanf("%d",&a[i]);
    double l = 0 , r = 1e9 , mid ;
    while(r -l > 1e-4)
    {
        mid = (l + r) / 2 ;
        if(panduan(mid))
            l = mid;
        else
            r = mid;
    }
    printf("%.2f",l);
}

参考内容

AcWing 常用代码模板1——基础算法
AcWing 680. 剪绳子-视频讲解
AcWing 68. 0到n-1中缺失的数字 - 题解

相关文章

  • 算法

    一.算法基础--算法的特性 二.算法基础--算法的复杂度 三.顺序查找和二分查找 顺序查找 二分查找(前提是有序的...

  • 『算法』『数据结构』 浅谈二分算法,理解程序员必懂必会的计算机常

    基本认识 二分算法,又名二分查找、折半查找,是一种查找算法,是最基础的,最简单易学且高效实用的算法之一。二分算法的...

  • 29.算法入门

    算法与数据结构基础 一、基础算法思想二分: 递推: 枚举: 递归: 分治: 贪心: 试探: 模拟: 二、简单数据结...

  • 数据结构与算法-排序/二分查找

    算法中基础中的基础,排序/二分查找 排序 1.快排QuickSort 归并排序 堆排序 1. 二分查找

  • 数据结构与算法之美笔记——二分查找(下)

    摘要: 基础的二分查找算法无论是概念还是实现都比较简单(关于 二分查找基础实现文章 可点击此处查看),但二分查找存...

  • 算法-二分搜索算法

    算法:二分搜索算法(折半查找算法)时间复杂度: 二分搜索算法概述 二分搜索算法伪代码 二分搜索算法实现 二分搜索算...

  • 排序算法

    算法与数据结构基础 查找算法: 二分查找法: 简介:二分查找法又被称为折半查找法,用于预排序的查找问题 过程: 如...

  • 算法汇总

    关于算法: 基础技巧:分治、二分、贪心排序算法:快速排序、归并排序、计数排序搜索算法:回溯、递归、深度优先遍历,广...

  • 算法(一):二分查找法

    算法(一):二分查找法 算法基础: 一、大O表示法: 指示算法的速度有多快,用于指出随数量的增大,算法的所需步骤增...

  • 算法与数据结构简介

    0x01 算法 基础技巧:分治、二分、贪心 排序算法:快速排序、归并排序、计数排序 搜索算法:回溯、递归、深度优先...

网友评论

    本文标题:算法基础(二分)

    本文链接:https://www.haomeiwen.com/subject/mntsirtx.html