算法设计与分析---递归与分治

算法设计与分析—递归与分治(持续更新中…虽然也没什么人看吧,hhh)

分治概念:将一个大规模问题分解为若干个小规模问题,以便逐个击破,即分而治之!
递归概念:直接或间接调用自身的算法成为递归。

二者的相关性十分强,这也是为什么教材把这两个算法归在一章里的原因。

问题一,输出全排列(不按照大小输出,要求使用递归不使用回溯)

input:
输入一个正整数(不要太大,递归层数稍微一多就超时!!!)
output:
输出1----n的全排列
input_case:

3

output_case:

123
132
213
231
321
312

思路:
递归一定要找好递归边界与递归关系!!!
设置函数P(int *a,int k,int n);

k从0开始计数,k到达问题边界就输出一下;
k没到边界开始,分别以每一个元素作为前缀进行递归输出!
code:

//输出全排列(递归实现)---非顺序输出 
#include<stdio.h>
using namespace std;

template<class T>
inline void swap(T &t1,T &t2){
    
    
	T temp=t1;
	t1=t2;
	t2=temp;
	return ;
}

void P(int *a,int k,int n)
{
    
    
	if(k==n){
    
    
		for(int i=0;i<n;i++){
    
    
			printf("%d",a[i]);
		}
		printf("\n");
		return ;
	}else{
    
    
		for(int i=k;i<n;i++){
    
    
			swap(a[k],a[i]);
			P(a,k+1,n);
			swap(a[k],a[i]);
		}
	}
	return ;
}

int main(){
    
    
	int n;
	scanf("%d",&n);
	int a[n];
	for(int i=1;i<=n;i++){
    
    
		a[i-1]=i; 
	}
	P(a,0,n);
	return 0;
}

问题二,汉诺塔问题

问题描述:
有a,b,c三个塔,a上有n个盘子,从小到大依次罗列,将这n个盘子从a移到c上,
注意:大盘不能压小盘;
一次只能移一盘;
input:
输入一个正整数,代表问题规模,不要太大!
output:
输出问题的移动过程:(以这种方式输出即可)
%c->%c\n
最后输出一共移动了多少次:(正整数)
Input_case:

3

output_case:

A->C
A->B
C->B
A->C
B->A
B->C
A->C
cnt=7

思路:
对于大规模问题无法直接求解,将其分为小规模问题(分治思想)!
code:

#include<stdio.h>

void hanoi(int n,char x,char y,char z);
int cnt=0;
int main(){
    
    
	int n;
	scanf("%d",&n);
	hanoi(n,'A','B','C');
	printf("cnt=%d",cnt);
	return 0;
} 
void hanoi(int n,char x,char y,char z){
    
    
	if(n==1){
    
    //递归边界 
		printf("%c->%c\n",x,z);cnt++;
	}else{
    
    //如果不是边界就一直递归调用 
	hanoi(n-1,x,z,y);//将x借助z移到y 
	printf("%c->%c\n",x,z);//输出路径 
	cnt++;
	hanoi(n-1,y,x,z);//将x借助y移到z 
    }
}

问题三,二分查找

问题描述:
对于已经从小到大排好序的数组a[0…n-1];
找出其中值为x的下标;
如果没有找到输出NULL;
input:
输入正整数n;
接下来输入n个正整数(从小到大);
在输入所要查找的值x;
output:
输出x对应在数组的下标;
如果没有x输出NULL;
input_case:

5
1 3 4 6 8
6

output_case:

3

code:

扫描二维码关注公众号,回复: 12929065 查看本文章
#include<stdio.h>

int search(int *a,int low,int high,int x){
    
    
	int mid=(low+high)/2;
	if(low==high&&a[mid]!=x)return -1;//没有找到 
	if(a[mid]==x){
    
    //找到了输出mid 
		return mid;
	}else if(a[mid]>x){
    
    //从左侧找 
		return search(a,low,mid,x);
	}else{
    
    //从右侧找 
		return search(a,mid+1,high,x);
	}
}

int main(){
    
    
	int n;
	scanf("%d",&n);
	
	int a[n];
	for(int i=0;i<n;i++){
    
    
		scanf("%d",&a[i]);
	}
	
	int x;
	scanf("%d",&x);
	int ans=search(a,0,n-1,x);
	if(ans>=0){
    
    
		printf("%d",ans);
	}else{
    
    
		printf("NULL");
	}
	return 0;
} 

时间复杂度:O(logn);

问题四,大整数相乘问题(分析)

问题描述:
两个非常大的正整数(以二进制形式给出)如何降低时间复杂度?
分析:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
时间复杂度:从O(n^2)------>O(n ^1.59)

问题五,Strassen矩阵乘法(分析)

问题描述:
对于nXn的方阵A乘以nXn的方针B形成nXn的方针C;
需要O(n^3)的时间复杂度
如何降阶呢?
分析:
将nXn的矩阵分成4个(n/2)X(n/2)的矩阵,这样时间复杂度为:
在这里插入图片描述
在这里插入图片描述
时间复杂度:O(n^3)-------->O(n ^2.81)

猜你喜欢

转载自blog.csdn.net/timelessx_x/article/details/115252906