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(避免整数溢出)

-如果arr[mid] == 目标值,返回mid

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

-如果arr[mid] > 目标值,说明目标值在左半部分,更新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;
}
相关推荐
端平入洛1 天前
delete又未完全delete
c++
端平入洛2 天前
auto有时不auto
c++
哇哈哈20213 天前
信号量和信号
linux·c++
多恩Stone3 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马3 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost
超级大福宝3 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode
weiabc3 天前
printf(“%lf“, ys) 和 cout << ys 输出的浮点数格式存在细微差异
数据结构·c++·算法
问好眼3 天前
《算法竞赛进阶指南》0x01 位运算-3.64位整数乘法
c++·算法·位运算·信息学奥赛
yyjtx3 天前
DHU上机打卡D31
开发语言·c++·算法
czxyvX3 天前
020-C++之unordered容器
数据结构·c++