经典算法题2

主要是算法题练习记录2……

汉诺塔问题

约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。

  • 分析

移动n个盘子到终点,总的来说分三步:
1、把n-1个盘子移动到暂放区
2、把最大的移到终点
3、把暂放区的n-1个盘子移到终点

很明显是一个递归问题

用f(n, a, b, c)表示要求解的问题,其含义是有a、b、c三根棒和n只盘,且这n个盘叠放在a棒上,依次叠放为大盘在下,小盘在上。借助b棒将n只盘从a棒移到c棒上。每次只移一个盘,在移动时保持大盘在下,小盘在上。

将f(n, a, b, c)转化分解为如下三个子问题:
①f(n - 1, a, c, b),即将a棒上面的n-1个盘移到b棒,借助c棒。
②move(a, c),即将在a棒上的一个盘移到c棒。
③f(n - 1, b, a, c),即将b棒上面的n-1个盘移到c棒,借助a棒。

编程实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

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

void move(char from, char to) {
printf("%c-->%c\n", from, to);
}

void hanoit(int n, char a, char b, char c) {
if(n == 1){
move(a, c);
} else {
hanoit(n - 1, a, c, b);
move(a, c);
hanoit(n - 1, b, a, c);
}

}

int main() {
int m;
scanf("%d", &m);
hanoit(m, 'A', 'B', 'C');
return 0;
}

求最小公倍数和最大公约数

1、求最小公倍数:

最小公倍数=两整数的乘积 / 最大公约数

2、最大公约数:

辗转相除法:

① a%b得余数c

② 若c=0,则b即为两数的最大公约数

③ 若c≠0,则a=b,b=c,再回去执行①

例如求27和15的最大公约数过程为:

27÷15 余1215÷12余312÷3余0因此,3即为最大公约数

编码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>

int main()
{
int a,b,a1,b1,c;
scanf("%d %d",&a,&b);

a1 = a;
b1 = b;
c = a%b;
while(c!=0)
{
a1 = b1;
b1 = c ;
c = a1%b1;

}
printf("最大公约数为:%d",b1);
}

合并数组

给定两个元素个数不超过20的整数数组a和b,要求将a和b合并成一个新数组。合并规则:如果一个元素在两个数组中同时出现,则需在合并后的数组中去掉该元素;对于只在一个数组中重复出现的元素,合并后只保留一个。合并后按照从小到大的顺序将新数组输出(测试数据保证不会出现合并后无数据的情况)

输入:

5 1 4 1 2 9
7 2 3 1 5 7 6 5

输出:

3 4 5 6 7 9

  • 分析:

    首先是合并数组,除去相同的数字,然后是对此数组进行排序。对于相同的数字,在输出时只输出一个(可能比事先对输入数组去重简单一些)

    编程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<stdio.h>
#include <stdlib.h>
int cmp(const void *a,const void *b)//比较函数
{
return *(int *)a-*(int *)b;
}
int main()
{
int a[20],b[20],c[40],m,n;
scanf("%d",&m);
int i,j;
for(i=0;i<m;i++) //输入读取
{
scanf("%d",a+i);
}
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",b+i);
}
int k;
int count=0;
for( i=0;i<m;i++) //合并
{
k = 0;
for(j=0;j<n;j++)
{
if(a[i] != b[j])
{
k++;
}
}
if(k==n)//两个数组都有的数字 不存入c数组
{
c[count++]=a[i];
}

}

for(i=0;i<n;i++)
{
k = 0;
for(j=0;j<m;j++)
{
if(b[i] != a[j])
{
k++;
}
}
if(k==m)
{
c[count++]=b[i];
}

}
qsort(c,count,sizeof(c[0]),cmp); //快速排序
printf("%d ",c[0]);
for( i=1;i<count;i++)
{
if(c[i]==c[i-1])
{
continue; //去重
}
printf("%d ",c[i]);
}
}