分治策略(Divide and Conquer)
一、基本思想
1、将原始问题划分或者归结为规模较小的子问题。
2、递归或迭代求解每个子问题。
3、将子问题的解综合得到原问题的解
注意:
1、子问题与原始问题性质完全一样
2、子问题之间可以彼此独立求解
3、递归停止时子问题可以直接求解
二、例题
1、幂乘算法:
题目说明:
计算正整数a的n次幂
解析:
如果顺序相乘,则需要n次操作,复杂度为n;
实际上,观察幂乘规则有:
1)当n为偶数时:an=an/2*an/2
2)当n为偶数时:an=an/2*an/2*a
因此我们可以逐渐平分幂数再相乘,此时时间复杂度为logn
代码;
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
using namespace std;
int mul_pow(int a,int n)
{
//分治的基层算子,递归结束
if(n==1)
{
return a;
}
//判断n的奇偶性
if(n%2==1)
{
return a * mul_pow(a, n / 2) * mul_pow(a, n / 2);
}
else
{
return mul_pow(a, n / 2) * mul_pow(a, n / 2);
}
}
int main()
{
int a, n;//底数与幂数
cin >> a >> n;
int ans = 0;
if(n==0)
{
ans = 1;
}
else
{
ans = mul_pow(a, n);
}
cout << ans<<endl;
}
2、求第k小
代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//使用单次快排将数组分为两部分
int quick_sort(vector<int>& arr, int left, int right)
{
//道标
int temp = arr[left];
int l = left;
int r = right;
while (l < r)
{
while (arr[r] >= temp && r > l)
{
r--;
}
while (arr[l] <= temp && r > l)
{
l++;
}
if (r > l)
{
swap(arr[l], arr[r]);
}
}
arr[left] = arr[l];
arr[l] = temp;
return l;
}
//通过递归完成
int temp_sort(vector<int>& arr, int left, int right, int k)
{
//
int mid = quick_sort(arr, left, right);
//寻找的就在中间
if (mid == k)
{
return arr[mid];
}
//依照情况将问题分为同模式的子问题
else if (mid < k)
{
return temp_sort(arr, mid + 1, right, k);
}
else
{
return temp_sort(arr, left, mid - 1, k);
}
}
int main()
{
int n, k;
vector<int> arr;
//数组和位置
cin >> n >> k;
for (int i = 0;i < n;i++)
{
int x;
cin >> x;
arr.push_back(x);
}
if (k >= 0 && k < n)
{
int ans = temp_sort(arr, 0, n - 1, k);
cout << ans << endl;
}
else
{
cout << "不在范围内。" << endl;
}
}