算法设计与分析 3-14 分治法

3月14日 分治法相关练习记录

分治法是我们正式接触的第一个算法,它的求解可以简要概括为:
划分 求解子问题 合并
分治法要求子问题原问题之间形式相同,子问题之间相互独立,在实际运用中,如何划分让程序的时间空间复杂度尽可能降低是我们需要考虑的关键。

数组元素循环移动

题目内容:
设计分治算法实现将字符数组A[n]中所有元素循环左移k个位置,例如,对abcdefgh循环左移3位得到defghabc。

输入格式:
第一行为数组长度n
第二行为循环左移数k
第三行为数组中元素

输出格式:
循环左移k个位置后的结果

思路:
第一反应是考虑数组需要移动的数量k,如果k小于元素的数目n,那么创建第二个空数组,将前k个元素暂时存入新数组并删除,将剩余元素向前移动,完成后将新数组中元素接在原数组之后。
如果k大于n,那么使用模的思想,对元素的下标进行运算得出最终落点。
这种方法比较繁琐,可能需要占据一个新数组的空间,而且时间复杂度也高。
如果从使用分治法的思路来考虑,从网上检索得到了一种数学思路,同样将数组分成以k为划分的两个部分,通过两次逆序处理得到最终落点。

代码如下
*#include
#include
#include;
using namespace std;
void math(char a,int start,int end){
int i;
char t;
for(i=0;i<(end-start+1)/2;i++){
t=a[start+i];
a[start+i]=a[end-i];
a[end-i]=t;
}
}
int main(void){
int n,k;
int i;
char a[1000];
char j;
cin>>n;
cin>>k;
cin>>a;
math(a,0,k-1);
math(a,k,n-1);
math(a,0,n-1);
for(i=0;i cout< cout< system(“pause”);
return 0;
}

逆序数问题

题目内容:
设a1, a2,…, an是集合{1, 2, …, n}的一个排列,如果iaj,则序偶(ai, aj)称为该排列的一个逆序。例如,2, 3, 1有两个逆序:(3, 1)和(2, 1)。设计算法统计给定排列中含有逆序的个数。

输入格式:
第一行输入集合中元素个数n,第二行输入n个集合元素

输出格式:
含有逆序的个数

思路:
从第一个元素开始扫描,计算在它之后数值小于它的元素个数就是它的逆序数对数,依次向后直到最后一个数。这种方法属于蛮力法,当数组所含的元素较多时会导致运行时间的大幅上升,并不实用。
由于是对元素进行比对,考虑在排序中进行计数的可能,将数组视作n个小集合,每个集合中初始含有一个元素,将集合两两合并并且进行排序,在排序中计数逆序的个数(如果调整前满足逆序条件那么计数,如果为顺序则不做处理),依次向上排序直到最终合成一个有序数组。
由于在排序时可以是做是两个有序集合之间在对比,每次取集合的第一个元素与另一个集合的第一个元素进行对比,满足条件后其后的元素都不再需要对比,直接计数即可(即计数的核心代码 mid-i+1),满足需要的排序方法为归并排序,实际上只需要在归并排序的程序中插入一条代码就可以满足条件。

代码如下:
*#include
#include
using namespace std;
int number=0;
void Merge(int left,int right,int mid,int *a,int *b){
int i=left;
int j=mid+1;
int k=left;
if(i!=mid+1&&j!=right+1){
if(a[i]>a[j]){
b[k++]=a[j++];
number=number+mid-i+1;
}
else
b[k++]=a[i++];
}
while(i!=mid+1)
b[k++]=a[i++];
while(j!=right+1)
b[k++]=a[j++];
for(i=left;i<=right;i++)
a[i]=b[i];
}
void Mergesort(int left,int right,int *a,int b){
int mid;
if(left mid=(left+right)/2;
Mergesort(left,mid,a,b);
Mergesort(mid+1,right,a,b);
Merge(left,right,mid,a,b);
}
}
int main(void){
int n,i;
int a[100],b[100];
cin>>n;
for(i=0;i cin>>a[i];
Mergesort(0,n-1,a,b);
cout< system(“pause”);
return 0;
}

分治法的运用在于合理选择小问题划分的方式,运用合适的算法解决问题。

你可能感兴趣的:(算法设计与分析 3-14 分治法)