0x01算法设计与分析复习(一)习题解答

参考书籍:算法设计与分析——C++语言描述(第二版)

练习一

  1. 逆序输出正整数的各位数(递归算法求解)
#include <stdio.h>
//逆序输出正整数的各位数(递归算法求解)
void print(unsigned int n)
{
    printf("%d", n%10);//基础情况
    if(n>=10){
        print(n/10);//递归部分
    }
}
int main()
{
    unsigned int n;
    scanf("%d", &n);
    print(n);

    return 0;
}

实验结果:

123456
654321
Press any key to continue.
  1. 汉诺塔问题
//hanoi,汉诺塔问题求解
//将x柱上的n个圆盘经z柱移动到y柱上,任何时刻大盘不能在小盘上

#include <stdio.h>

void move(int n, char x, char y)//将圆盘x从x移到y上
{
	printf("move %d from %c to %c\n", n, x, y);
	
}

void Hanoi(int n, char x, char z, char y)//将n个圆盘经z从x移到y
{
	if(n>0){
		Hanoi(n-1, x, y, z);//将n-1个盘从x移到z
		move(n, x, y);//将n盘从x移到y
		Hanoi(n-1, z, x, y);//将n-1个盘从z移到y
	}
	
}

int main()
{
	int n = 0;
	char x = 'X', y = 'Y', z = 'Z';
	scanf("%d", &n);
	
	Hanoi(n, x, z, y);
	
	return 0;
}

实验结果:

3
move 1 from X to Y
move 2 from X to Z
move 1 from Y to Z
move 3 from X to Y
move 1 from Z to X
move 2 from Z to Y
move 1 from X to Y

Press any key to continue.
  1. 排列产生算法
//排列产生算法
//给定n个自然数{0, 1, 2, ..., n-1},输出该集合所有可能的排列(permutation)

#include <stdio.h>
#include <stdlib.h>

int i = 0;
//arr[0]~arr[k-1]排好,求arr[k]到arr[n-1]的排列
void Perm(int arr[], int k, int n)
{
	if(k == n-1){
		for(int i = 0; i<n; i++)
			printf("%d ", arr[i]);
		printf("\n");
		i++;
	} else if(k>=0){
		//从arr[k]~arr[n-1]中拿出一个加入到已经排好的队中
		for(int i = k; i<n; i++){
			int tmp = arr[k];
			arr[k] = arr[i];
			arr[i] = tmp;
			Perm(arr, k+1, n);
			arr[i] = arr[k];
			arr[k] = tmp;
		}
	}
}

int main()
{
	int *arr = NULL, n = 0;
	scanf("%d", &n);
	arr = (int *)malloc(sizeof(int)*n);
	for(int i = 0; i<n; i++)
		arr[i] = i;
	
	Perm(arr, 0, n);
	printf("%d\n", i);
	return 0;
}

实验结果:

3
0 1 2
0 2 1
1 0 2
1 2 0
2 1 0
2 0 1
6

Press any key to continue.
  1. 给出\(n!\)的递归定义式,并设计一个递归函数计算\(n!\)
/*n!的递归定义
  n! = n*(n-1)!,n>0;
  n! = 1,n = 0;
  */

#include <stdio.h>

int fact(int n)
{
	if(n == 0)
		return 0;
	else if(n>1){
		return n*fact(n-1);
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	
	printf("%d\n", fact(n));
	
	return 0;
}

实验结果:

4
24

Press any key to continue.
  1. 写一个递归算法和一个迭代算法计算二项式系数:

\[C_n^m = C_{n-1}^m + C_{n-1}^{m-1} = \frac{n!}{m!(n-m)!} \]

#include <stdio.h>
#include <stdlib.h>
//递归算法
int func1(int n, int m)
{
	if (m > n)
		return 0;
	if (n == m || m == 0)
		return 1;
	else if (n>0 && m>0)
		return func1(n - 1, m) + func1(n - 1, m - 1);

}

//迭代算法
int func2(int n, int m)
{
	int i = 0, j = 0;
	int **record = (int **)malloc((n + 1) * sizeof(int *));
	for (i = 0; i<n+1; i++)
		record[i] = (int *)malloc((m + 1) * sizeof(int));
	//记录矩阵
	for (i = 0; i<n + 1; i++)
		for (j = 0; j<m + 1; j++) {
			if (i < j)
				record[i][j] = 0;
			if (i == j || j == 0)
				record[i][j] = 1;
			else if (i >0 && j> 0)
				record[i][j] = record[i - 1][j] + record[i - 1][j - 1];
		}
	return record[n][m];
}

int main()
{
	int n = 0, m = 0;
	scanf("%d %d", &n, &m);

	printf("%d\n", func1(n, m));

	printf("%d\n", func2(n, m));
	
	return 0;
}

实验结果:

4 2
function 1: 6
function 2: 6

Press any key to continue.

  1. 给定一个字符串s和一个字符x,编写递归算法实现下列功能:
    (1)检查x是否在s中
    (2)计算x在s中出现的次数
    (3)删除s中所有的x
/*
给定一个字符串s和一个字符x,编写递归算法实现下列功能:
(1)检查x是否在s中
(2)计算x在s中出现的次数
(3)删除s中所有的x
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//检查x是否在s中
void XinS(char *s, char x)
{
	if(s[0] != 0){
		if(x == s[0])
			printf("YES\n");
		else {
			XinS(s+1, x);
		}
	} else 
		printf("NO\n");

}

//计算x在s中出现的次数
int CountX(char *s, char x)
{
	int count = 0;
	if(s[0] != 0){
		if(s[0] == x)
			count++;
		count += CountX(s+1, x);
	}
	
	return count;
}

//删除s中所有的x
char *DelX(char *s, char x)
{
	static int j = 0;
	static char tmp[100] = {'\0'};
	if(s[0] != 0){
		if(s[0] != x){
			tmp[j++] = s[0];
		}
		DelX(s+1, x);
	} else
		return tmp;
} 

int main()
{
	char x, s[100] = {'\0'}, *tmp;
	scanf("%s", s);
	getchar();//接收空字符;
	scanf("%c", &x);
	//(1)
	XinS(s, x);
	//(2)
	printf("%d\n", CountX(s,x));
	//(3)
	tmp = DelX(s,x);
	memcpy(s, tmp, strlen(tmp)+1);
	printf("%s\n", s);
	return 0;
}

实验结果:

asdfgts
s
YES
2
adfgt

Press any key to continue.
  1. 写一个C++函数求解:给定正整数n,确定n是否是它所有因子之和
//写一个C++函数求解:给定正整数n,确定n是否是它所有因子之和
//因子就是所有可以整除这个数的数,不包括这个数自身
int ex7(unsigned int n)
{
	int k=2, flag = n-1;
	while(k*k<n){
		if(n%k == 0){
			flag -= k;
			flag -= n/k;
		}
		k++;
	}
	if(k*k == n){
		flag -=k;
	}
	return (flag==0);
}

实验结果:

15
NO

Press any key to continue.
  1. S是有n个元素的集合,S的幂集是S所有可能的子集组成的集合。例如,\(S = {a, b, c}, 则S的幂集={(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b,c)}\)。写一个C++递归函数,以S为输入,输出S的幂集。

练习二

  1. 矩阵转置
    (1)设计一个C/C++程序实现一个\(n\times m\)的矩阵转置。原矩阵保存在二维数组中。
    (2)使用全局变量count,改写矩阵转置程序,并运行修改后的程序,以确定改程序的程序步
    (3)计算此程序的渐进时间复杂度

  2. 证明:若\(f(n) = a_mn^m+a_{m-1}n^{m-1}+\cdots+a_1n+a_0\)\(m\)次多项式,且\(a_m>0\),则\(f(n)=\Omega(n^m)\).

    :不妨令\(c=\frac{1}{2\max\{a_0,a_1,\cdots,a_m\}},n_0=2\),当\(n\geq n_0\)时,有

    \[cg(n)\leq \frac{1}{2}(n^m+n^{m-1}+\cdots+n+1)\leq\frac{1}{2}(n^m+\frac{1-n^m}{1-n})\leq n^m \]

    根据定义有:\(f(n)=\Omega(n^m)\)

  3. 运用主定理求\(T(n) = 2T(n/4) + \sqrt{n}, T(1) = 3\)的渐进界

    :根据主定理,\(a=2,b=4,f(n)=\sqrt{n},log_4^2=\frac{1}{2}\),显然\(f(n) = \sqrt{n}=\Theta(n^{log_b^a})\),所以

\[T(n) = \Theta(n^{log_b^a}logn)=\Theta(\sqrt{n}logn) \]

posted @ 2018-01-09 10:57  main_c  阅读(649)  评论(0)    收藏  举报