算法设计第一章 水仙花数和北斗七星数

水仙花数是一个三位数,它的个位、十位、百位上的数值的三次方的和等于它本身。求水仙花数的算法如下:

迭代算法:

求水仙花数的直接方式是直接遍历所有的三位数(100 - 999)对每一个三位数进行判断,代码如下:

int getNarcissisticNumber(void){
	start = clock();
	int num, i, j, k;
	num = 1000;
	while(--num >= 100){
		i = num / 100; j = num / 10 % 10; k = num % 10;
		if(num == i*i*i + j *j *j + k *k *k) printf("%d ", num);
	}
	end = clock();
	printf("time = %f\n", ((double)end - start)/CLK_TCK);
	return 0;
}

迭代优化一

上述算法在每次循环中都会进行三次0 - 9中三个数字的立方计算,这其中有大量的重复计算,我们可以提前计算并保存下来,在循环中直接使用,如下所示:

int * getNarcissisticNumber2(void){
	start = clock();
	int num, i, j, k;
	int arr[10];
	for(int i = 0; i <= 9; ++i){
		arr[i] = i * i * i;
	}
	num = 1000;
	while(--num >= 100){
		i = num / 100; j = num / 10 % 10; k = num % 10;
		if(num == (arr[i] + arr[j] + arr[k]))  printf("%d ", num);
	}
	end = clock();
	printf("time = %ld\n", end - start);
}

下面我们来看一看采用这种优化方式对北斗七星数进行优化后的算法效率:

优化前:

void initArr(){
	for(int i = 0; i <= 9; i++){
		arr[i] = i*i*i*i*i*i*i;
	}
}

void getBigDipperNum(void){
	start = clock();
	unsigned num, i, j, k, l, m, n, o;
	initArr();
	num = 10000000;
	while(--num >= 1000000){
		i = num / 1000000; j = num / 100000 % 10; k = num / 10000 % 10;
		l = num / 1000 % 10; m = num / 100 % 10; n = num / 10 % 10; o = num % 10;
		if(num == (arr[i] + arr[j] + arr[k] + arr[l] + arr[m] + arr[n] + arr[o])){
			printf("%u ", num);

		}
	}
	end = clock();
	printf("Time = %f\n", ((double) end - start) / CLK_TCK);
}


优化一:

void getBigDipperNum2(void){
	start = clock();
	unsigned i, j, k, l, m, n, o;
	unsigned a[10], b[10], c[10], d[10], e[10], f[10], g[10];
	for(int i = 0; i < 10; i++){
		a[i] = i * 1000000;
		b[i] = i * 100000; c[i] = i * 10000;
		d[i] = i * 1000; e[i] = i * 100; f[i] = i * 10; g[i] = i;
	}
	initArr();
	for(i = 1; i <= 9; ++i)
		for(j = 0; j <= 9; ++j)
			for(k = 0; k <= 9; ++k)
				for(l = 0; l <= 9; ++l)
					for(m = 0; m <= 9; ++m)
						for(n = 0; n <= 9; ++n)
							for(o = 0; o <= 9; ++o){
								if((arr[i] + arr[j] + arr[k] +
										arr[l] + arr[m] + arr[n] + arr[o]) ==
												(a[i] + b[j] + c[k] + d[l] + e[m] + f[n] + g[o]))
									printf("%u%u%u%u%u%u%u ", i, j, k, l, m, n, o);
							}
	end = clock();
	printf("Time = %f\n", ((double) end - start) / CLK_TCK);
}<pre class="cpp" name="code">

 
 

迭代优化二:

对上述算法再最内层循环进行了多次加法运算,我们可以化简该运算表达式,将加法提到循环外部,减少加法执行次数,如下:

void getBigDipperNum3(void){
	start = clock();
	unsigned i, j, k, l, m, n, o;
	unsigned t1, t2, t3, t4, t5, t6;
	unsigned a[10], b[10], c[10], d[10], e[10], f[10], g[10];
	for(int i = 0; i < 10; i++){
		a[i] = i * 1000000;
		b[i] = i * 100000; c[i] = i * 10000;
		d[i] = i * 1000; e[i] = i * 100; f[i] = i * 10; g[i] = i;
	}
	initArr();
	for(i = 1; i <= 9; ++i)
		for(j = 0; j <= 9; ++j){
			t6 = a[i] + b[j] - arr[i] - arr[j];
			for(k = 0; k <= 9; ++k){
				t5 = t6 + c[k] - arr[k];
				for(l = 0; l <= 9; ++l){
					t4 = t5 + d[l] - arr[l];
					for(m = 0; m <= 9; ++m){
						t3 = t4 + e[m] - arr[m];
						for(n = 0; n <= 9; ++n){
							t2 = t3 + f[n] - arr[n];
//							if(t2 < 0) continue;
							for(o = 0; o <= 9; ++o){
								t1 = t2 + g[o] - arr[o];
								if(t1 == 0)
								printf("%u%u%u%u%u%u%u ", i, j, k, l, m, n, o);
							}
						}

					}
				}
			}
		}

	end = clock();
	printf("Time = %f\n", ((double) end - start) / CLK_TCK);
}


上述三种求北斗七星数的方式在i3-380M 2.53GHz机器上执行情况如下:

9926315 9800817 4210818 1741725 Time = 0.390000
1741725 4210818 9800817 9926315 Time = 0.125000
1741725 4210818 9800817 9926315 Time = 0.047000

大家可以看到明显的优化效果。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值