알고리즘 설계 및 분석-재귀 및 분할 및 정복 (지속적인 업데이트 ... 아무도보고 있지 않지만 hhh)
개념 분할 및 정복 : 대규모 문제를 여러 개의 소규모 문제로 분해하여 하나씩 분할, 즉 분할 정복!
재귀의 개념 : 직접 또는 간접적으로 자신을 호출하는 알고리즘이 재귀 적이됩니다.
둘 사이의 상관 관계가 매우 강하기 때문에 교과서에서는이 두 알고리즘을 한 장에 넣습니다.
질문 1, 출력이 모두 정렬되어 있습니다 (출력의 크기가 아니라 역 추적없이 재귀를 사용해야 함).
입력 :
양의 정수를 입력합니다 (너무 크지 않습니다. 재귀 레이어의 수가 너무 크면 재귀 레이어가 시간 초과됩니다 !!!)
출력 :
1 ---- n input_case 의 전체 배열을 출력합니다
.
3
출력 _ 케이스 :
123
132
213
231
321
312
아이디어 :
재귀는 좋은 재귀 경계와 재귀 관계를 찾아야합니다! ! !
함수 P 설정 (int * a, int k, int n);
k는 0부터 계산을 시작하고 k가 문제의 경계에 도달하면 출력합니다 .k가 경계에 도달
하지 않으면 각 요소를 접두사로 사용하여 재귀 적으로 출력 합니다!
암호:
//输出全排列(递归实现)---非顺序输出
#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;
}
문제 2, 하노이 타워 문제
문제 설명 :
3 개의 타워 a, b, c가 있습니다. a에는 n 개의 플레이트가 있으며 작은 것부터 큰 것까지 순서대로 나열됩니다
. n 개의 플레이트를 a에서 c로
이동 합니다. 참고 : 큰 플레이트는 작은 접시; 하나만 움직일 수 있음 접시 하나;
입력 :
너무 크지 않은 문제의 척도를 나타내는 양의 정수를 입력하십시오!
출력 :
출력 문제의 이동 과정 : (이 방식으로 출력)
% c-> % c \ n
최종 출력이 이동 한 횟수 : (양의 정수)
Input_case :
3
출력 _ 케이스 :
A->C
A->B
C->B
A->C
B->A
B->C
A->C
cnt=7
아이디어 :
직접 해결할 수없는 대규모 문제는 작은 문제로 나누세요 (아이디어를 나누고 정복하세요)!
암호:
#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
}
}
질문 3, 이진 검색
문제 설명 :
어레이 A의 [0 ... N-1], 소형 ~ 대형의 정렬 된 것으로,
값 X 여기서 첨자를 찾아,
출력 NULL을 찾을 수없는 경우,
입력 :
입력은 양의 정수, N을,
그때 입력 n 양의 정수 (작은 것에서 큰 것까지);
입력에서 찾을 값 x;
출력 :
출력 x는 배열의 첨자에 해당합니다
.x가 없으면 NULL을 출력합니다.
input_case :
5
1 3 4 6 8
6
출력 _ 케이스 :
3
암호:
#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);
질문 4, 큰 정수의 곱셈 (분석)
문제 설명 :
두 개의 매우 큰 양의 정수 (이진 형식으로 제공됨)가 어떻게 시간 복잡성을 줄일 수 있습니까?
분석:
시간 복잡도 : from O (n ^ 2) ------> O (n ^ 1.59)
질문 5, Strassen 행렬 곱셈 (분석)
문제 설명 :
nXn 정사각형 행렬 A에 nXn 정책 B를 곱하여 nXn 정책 C를 형성합니다 .O
(n ^ 3)의 시간 복잡성
을 줄이는 방법은 무엇입니까?
분석 :
nXn 행렬을 4 (n / 2) X (n / 2) 행렬로 나눕니다. 따라서 시간 복잡도는 다음과 같습니다.
시간 복잡도 : O (n ^ 3) --------> O (n ^ 2.81 )