算法,讲究一个巧字:
最近一直在研究算法的内容,但是我发现了一个问题,那就是在学习的时候会有一种迷茫的感觉,有时候会分不清编程和算法的关系,有时候会分不清算法和数学的关系,在这里贴出一些我的小感悟,希望能帮助到有和我一样问题的大兄弟(
其实我觉得大概率没人看,写来自己玩玩也好)
给下目录,方便大家查看
- 介绍两种求最大公约数的算法
- 详细解释辗转相除法的数学逻辑和算法逻辑的转化过程
- 浅谈编程和算法,数学和算法的关系问题
1)介绍两种求最大公约数的算法
大家还记得最大公约数的求法吗
我这里简单用C语言写出两种给兄弟们回忆和学习
第一种是机械的循环判断,用i来储存所有余数,(因为i是递减的),当两者第一次能同时除以i时,此i即为最大公约数
#include "stdio.h"
int main()
{
/*读取用户想要计算的两个数字*/
int number1,number2;
scanf("%d %d",&number1,&number2);
/* 比较后将number1设置为最大数 */
int t;
if( number1 > number2 )
{
;
}
else
{
t = number1;
number1 = number2;
number2 = t;
}
//printf("%d %d",number1,number2);//用于测试比较大小代码;
for( int i = number2; i <= number2; i--)
{
if( ( number1 % i ) == 0 )
{
if( ( number2 % i ) == 0 )
{
printf("%d is the greast divisor.",i);
break;
}
}
}
return 0;
}
第二种利用辗转相除法的算法比较高级,所需计算时间也更少,算是优化过的算法,但是其中蕴含的巧妙和启示却是一言难尽的。
先上代码:
#include "stdio.h"
int main()
{
/*读取用户想要计算的两个数字*/
int number1,number2;
scanf("%d %d",&number1,&number2);
int t;
while( number2 != 0 )
{
t = number1 % number2;
number1 = number2;
number2 = t;
}
printf("%d",number1);
return 0;
}
可以看到,这段代码不仅简洁了许多,而且在算较大数字的时候也明显加快了速度。
看似很简单的问题,但很多初学者还是不懂这个算法是怎么来的。那我就多BB两句。
2)详细解释辗转相除法的数学逻辑和算法逻辑的转化过程
a) 辗转相除法的数学逻辑
假如,我们现在要求12和18的最大公约数,从数学的角度来看,辗转相除法的流程是这样的:
到这里,当12 除 6的时候余数为0 ,因此6就是他们的最大公约数,这是 人在用辗转相除法时的思维
那么算法就是将这种人的处理思维转化为计算机处理思维的过程,而结果不变。
听不懂我们上图。
所以接下来的任务就是 实现辗转相除法的算法逻辑并用编程实现。(上面的路径)
b)辗转相除法的算法实现
原始数据只有两个,我们定义为number1,number2;
并假设用户输入的number1为12 number2为18;
按照数学方法看,首先让number1对number2取余
于是我们直接写以下代码:
? = number1 % number2
这是你突然发现,运算的结果无处存放,于是很自然的,定义出一个变量t,供我们存储取余后的结果;
//这里提一嘴,有的兄弟不知道什么时候定义新变量,
//其实有时候变量的定义就和上面叙述的一样自然,
//需要了,缺了,我就定义一个。
定义之后,我们的表格成了现在这样
//12 % 18 = 12//不用我多说吧。。。。
接下来我们继续按照数学方法进行运算
12%18 = 12
18%12 = 6
12%6 = 0
得到最大公约数是6;
这是数学办法,一通运算堪称行云流水,但是,怎么转化为可执行的算法?
我的方法是,看位置,不看数字。
什么意思?
说白了,在表格中,就是
number1 对 number2 取余然后将得到的数储存在 t 中
但是我们面临的问题就是,如何让下一步运算合理化
现在进行
t = number1 % number2;
进行完之后其实留下一堆烂摊子——number1 和number2 的值不能供下次运算;
所以我们接下来的代码解决这个烂摊子——将number1 和number2 的值能供下次运算;
number1 = number2;//18作为被除数
number2 = t;//12作为除数
此时表格变成了这样
可以这句代码正常运算了
t = number1 % number2
完整代码变成了这样:
t = number1 % number2;
number1 = number2;
number2 = t;
我们不妨多走几遍这个流程
表格变成了下图
成功模拟出了所有数学方法中出现的量,问题解决了;
但是还有一个问题没有解决,那就是怎么写循环的问题;
写循环的关键就是明白循环什么时候后结束,所以问题变成了填出下面问号中的条件
while( ? )
{
t = number1 % number2;
number1 = number2;
number2 = t;
}
要填这个条件,要重新回到表格中去
我们发现,在计算出“6”这个数之后,整个问题就得到了解决但是你在一步步运行这个代码的时候发现循环还没有结束,此时
t = number1 % number2;//算出6的代码
number1 = number2; /*剩下两句也在循环体中,
必须执行结束才能跳出循环所以表格仍然需要补齐*/
number2 = t;
所以我们需要结束循环时,表格编程了上面那样,我们要在这张表格中找出一个 普适 的循环结束条件
那就是number2 = 0;
道理很简单,从数学方法上看,求得余数为0时,得到最大公约数,而最后的余数赋值给了number2,很自然的,number2 = 0 时结束循环;
那最后,谁是最大公约数呢?我们发现上一步中的number2作为余数,在最后一步中赋值给了Number1,所以number1为最大公约数。
数学成功转换成了算法。
回顾我们整个代码编写成功的过程,大概是这样的:
这篇文章其实是写给那些正在入门算法,但是觉得很麻烦,很难受的初学者的。
如果你觉得算法很难,那说明现在的你很浮躁
算法说到底,不过是按照步骤去解决问题罢了
拿出草稿纸,一步步列表观察运算结果,初期的算法很简单
一步一步解决,算法真的很简单。