c++分治算法

分治算法的策略

简单来说,分治算法的基本思想就是:

把规模大的问题不断分解为子问题,使得问题规模减小到可以直接求解为止。


分治算法

基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。

求出子问题的解,就可得到原问题的解。

即一种分目标完成程序算法,简单问题可用二分法完成。


分治思想的经典应用

-二分查找

-归并排序

-快速排序

-大整数乘法

-Strassen矩阵乘法


二分查找

二分查找的定义

-二分查找(Binary Search)是一种在有序数组中查找特定元素的高效算法

-核心思想:每次将查找范围缩小一半,直到找到目标元素或确定目标元素不存在
二分查找的前提条件

-数组必须是有序的(升序或降序)

-数组元素支持随机访问(如数组,而不是链表)
二分查找的优势

-时间复杂度为O(log n),远优于线性查找的O(n)

-空间复杂度低,迭代实现为O(1).递归实现为O(log n)


二分查找算法原理

算法步骤

1.初始化查找范围:左边界left=0,右边界right=数组长度-1

2.当left ≤ right时,执行以下操作:

-计算中间位置mid = left +(right - left)/ 2(避免整数溢出)

-如果arrmid == 目标值,返回mid

-如果arrmid < 目标值,说明目标值在右半部分,更新left = mid + 1

-如果arrmid > 目标值,说明目标值在左半部分,更新right = mid - 1

3.如果循环结束仍未找到目标值,返回-1表示不存在


迭代实现

cpp 复制代码
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000];
int n;
int bfind(int,int,int);
int main()
{
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a+0,a+n);
    int x;
    cin>>x;
    cout<<bfind(x,0,n-1);
	return 0;
}
int bfind(int x,int l,int r)
{
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid] == x) return mid;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]>x) r = mid-1;
    }
    return -1;
}

递归实现

cpp 复制代码
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000];
int n;
int bfind(int,int,int);
int bfind2(int,int,int);
int main()
{
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a+0,a+n);
    int x;
    cin>>x;
    cout<<bfind2(x,0,n-1);
	return 0;
}
int bfind(int x,int l,int r)
{
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid] == x) return mid;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]>x) r = mid-1;
    }
    return -1;
}
int bfind2(int x,int l,int r)
{
    if(l>r) return -1;
    int mid = l + (r-l)/2;
    if(a[mid] == x) return mid;
    else if(a[mid]>x) return bfind2(x,l,mid-1);
    else if(a[mid]<x) return bfind2(x,mid+1,r);
}

练习题

查找最后一个出现的target

题目描述

给你有序一个数组,级一个target,数据量很大,请你使用二分查找法,查找最后一个出现的target所在的位置(数组索引)
输入格式

2行

第一行一个整数n,数组长度

第二行n个整数,数组元素,空格隔开

第三行---个整数target
输出格式

输出一个整数,最后一个出现的target所在的位置(数组索引),如果没有,输出-1
提示

找到以后,继续向右查找

用例输入

5

1 2 2 3 4

2
用例输出

2

cpp 复制代码
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000];
int n;
int bfind(int,int,int);
int bfind2(int,int,int);
int bfind3(int,int,int);
int main()
{
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a+0,a+n);
    int x;
    cin>>x;
    cout<<bfind2(x,0,n-1);
	return 0;
}
int bfind(int x,int l,int r)
{
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid] == x) return mid;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]>x) r = mid-1;
    }
    return -1;
}
int bfind2(int x,int l,int r)
{
    if(l>r) return -1;
    int mid = l + (r-l)/2;
    if(a[mid] == x) return mid;
    else if(a[mid]>x) return bfind2(x,l,mid-1);
    else if(a[mid]<x) return bfind2(x,mid+1,r);
}
int bfind3(int x,int l,int r)
{
    int result = -1;
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid]>x) r = mid-1;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]==x) 
        {
            if(a[mid-1]!=x) return mid;
            else l = mid+1;
        }
    }
    return result;
}

查找第一个大于等于target的数据

题目描述

给你有序一个数组,级一个target,数据量很大,请你使用二分查找法,查找第一个大于等于目标值的元素的索引
输入格式

2行

第一行一个整数n,数组长度

第二行n个整数,数组元素,空格隔开

第三行一个整数target
输出格式

输出一个整数,第一个大于等于目标值的元素的索引,如果没有,输出-1

用例输入

5

1 2 2 3 4

2
用例输出

1

cpp 复制代码
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000];
int n;
int bfind(int,int,int);
int bfind2(int,int,int);
int bfind3(int,int,int);
int main()
{
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a+0,a+n);
    int x;
    cin>>x;
    cout<<bfind3(x,0,n-1);
	return 0;
}
int bfind(int x,int l,int r)
{
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid] == x) return mid;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]>x) r = mid-1;
    }
    return -1;
}
int bfind2(int x,int l,int r)
{
    if(l>r) return -1;
    int mid = l + (r-l)/2;
    if(a[mid] == x) return mid;
    else if(a[mid]>x) return bfind2(x,l,mid-1);
    else if(a[mid]<x) return bfind2(x,mid+1,r);
}
int bfind3(int x,int l,int r)
{
    int result = -1;
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid]>x) r = mid-1;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]==x) 
        {
            if(a[mid-1]>=x) return mid;
            else l = mid+1;
        }
    }
    return result;
}

查找最后一个小于等于target的数据

题目描述

给你有序一个数组,级一个target,数据量很大,请你使用二分查找法,查找最后一个小于等于目标值的元素的索引
输入格式

2行

第一行一个整数n,数组长度

第二行n个整数,数组元素,空格隔开

第三行一个整数target
输出格式

输出一个整数,最后一个小于等于目标值的元素的索引,如果没有,输出-1

用例输入

5

1 2 2 3 4

2
用例输出

2

cpp 复制代码
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000];
int n;
int bfind(int,int,int);
int bfind2(int,int,int);
int bfind3(int,int,int);
int main()
{
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a+0,a+n);
    int x;
    cin>>x;
    cout<<bfind2(x,0,n-1);
	return 0;
}
int bfind(int x,int l,int r)
{
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid] == x) return mid;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]>x) r = mid-1;
    }
    return -1;
}
int bfind2(int x,int l,int r)
{
    if(l>r) return -1;
    int mid = l + (r-l)/2;
    if(a[mid] <= x) return mid;
    else if(a[mid]>x) return bfind2(x,l,mid-1);
    else if(a[mid]<x) return bfind2(x,mid+1,r);
}
int bfind3(int x,int l,int r)
{
    int result = -1;
    while(l<=r)
    {
        int mid = l + (r-l)/2;
        if(a[mid]>x) r = mid-1;
        else if(a[mid]<x) l = mid+1;
        else if(a[mid]==x) 
        {
            if(a[mid-1]>=x) return mid;
            else l = mid+1;
        }
    }
    return result;
}
相关推荐
Tyler_TXZ28 分钟前
C++C语言之——树
c语言·c++·算法·
旖旎夜光37 分钟前
LeetCode 30:串联所有单词的子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
星恒随风39 分钟前
C++ 红黑树封装(二):迭代器、const_iterator 与 operator[] 完整实现 mymap 和 myset
开发语言·c++·状态模式
小小龙学IT1 小时前
oneTBB 开源并行编程库深度解析:从工作窃取调度器到 flow graph 实战
c++·开源
ShineWinsu2 小时前
对于C++:缓冲区管理的详细解析
linux·c++·面试·编程·笔试·io·缓冲区
h_a_o777oah2 小时前
【算法基础】卡特兰数:递推定义与折线对称公式推导及解题策略
c++·算法·acm·组合数学·卡特兰数·反射原理·动态规划dp
帅气的小峰3 小时前
pybind11与nanobind可以共存吗?如何迁移?
c++·python·cuda·推理引擎
syker3 小时前
SuperNova Compiler v4.2.9 完整开发手册
c++
zhy295633 小时前
在 QAIRT Genie SDK 上部署 Llama 3.2 1B 模型:从环境准备到 C++ 推理
开发语言·c++·llama
richard_yuu3 小时前
JSON vs XML vs 二进制:3种序列化终极选型
xml·c++·qt·学习·json