算法设计与分析——第一篇,写在前面的话

写在前面的话——

做程序员也有几年了,一直以来都是在有需要的时候,上网查查资料,看看别人写的博客来充实自己,有时候也会想写写随笔,学习笔记什么的,可是空空如也的我,一直以来都没有什么可以写的,不过既然决定重新回到学校,开始一段新的历程,那就还是写写吧,正好学校也开了算法设计与分析这门课,每节课后,老师都会要求写一篇当堂课的相关论文报告交上去,我就把我的每篇作业贴上来吧,不过都是参考书上的东西!


第一篇——

第一次作业比较简陋,主要是对一些简单的题目,写出一个基本的代码,加上一些分析



1,  求1000以内的完数

设计思想:完数的定义为该数的所有真因子之和仍等于其本身,由此可以预先排除掉数字1,而后需要求出所有大于1的数的所有真因子并且求和,当和为其本身的时候,该数为完数。


#include <stdio.h>
 
int main()
{
         intn = 1000;
         inti;
         for(i= 2; i <= n; i++) {
                   intj;
                   intsum = 0;
                   for(j= 1; j < i; j++) {
                            if(0== i % j) {//求出所有的真因子
                                     sum+= j;//求出真因子后进行求和
                            }
                   }
                   if(sum== i) {//若所有真因子之和和该数相等,则该数为完数
                            printf("%d为完数\n",i);
                   }
         }
 
 
         return 0;
}



2,  求一个输入的正整数的分化数目

设计思想:根据整数划分的思想,设函数Q(n,m)表示整数n的划分中最大加数为m的数目,可以得知:

(1)Q(n,1) =Q(1,m) = 1,因为无论是1的分划还是对于被加数最大为1,其都只有一种分划,即为n个1相加

(2)当n<m时,Q(n,m)=Q(n,n),因为被加数m显然不会超过n

(3)Q(n,m) =Q(n,m-1) + Q(n-m,m),Q(n,m-1)表示Q(n,m)中不包含m的划分,而Q(n,m)中包含m的划分可以通过对n-m进行不超过m的划分数目来取得

(4)当n=m时可以作为(3)的特殊情况,即Q(n,n)= Q(n,n-1) + 1

根据以上结论可以通过递归法求出结果

 

#include <stdio.h>
 
int Division(int n, int m)
{
         if(n < 1 || m < 1) {
                   return 0;
         } else if (n == 1 || m == 1) {//Q(n,1) = Q(1,m) = 1
                   return 1;
         } else if ( n < m) {
                   return Division(n , n);
         } else if ( n == m) {
                   return Division(n , n - 1) + 1;//Q(n,n) = Q(n,n-1)+ 1
         } else {
                  returnDivision(n , m - 1) + Division(n - m , m);//Q(n,m) = Q(n,m-1) + Q(n-m,m)
         }
}
 
int main()
{
         int n;
         printf("输入需要分化的整数:");
         scanf("%d",&n);
 
         int num = Division(n, n);
         if(0 == num) {
                   printf("输入错误!\n");
         } else {
                   printf("%d的分划数目为%d\n",n ,num);
         }
        
         return 0;
}


关于上面特别标了颜色的那条,也就是这个Q(n,m) =Q(n,m-1) + Q(n-m,m),当时百思不得其解,后来想通了,就是这个意思,可以理解为,Q(n,m)这个数字是由两部分组成,Q(n,m-1)代表Q(n,m)中不包含m的部分,那么剩下的就是仅包含m的部分,根据各种百度的说法,所谓求Q(n,m) 中仅包含m的部分,就是求Q(n-m,m),这个以我的能力非常不好解释,只能说看你能不能想到,简单来说,我就是找一个实例,分析,比如Q(6,4),那么4开头的项,是4+2和4+1+1,你可以想到,其实这个数目就是数字2的分划的数目,在看所谓Q(n,m)的m开头的项,其实就是m+(n-m),观察这个项,其实就是左边是m,右边就是n-m的分划,左边都是一样的,而右边的数目就是n-m分划的数目,所以整个是数目就是n-m的分划的数目,这个应该可以理解了吧,但是这个应该只是一种情况,就是Q(n,m)的m项的数目=Q(n-m,n-m),但是我们可以看到,实际上应该是等于Q(n-m,m),那么这个里面还有什么差别呢,呃,我没有研究,所以上面只是启发了一下大概的思考方向,如果要具体弄清楚,要么就是用数学的方法,要么就是找一些实例来验证,找到规律,我就不多说了!

 

 

3,分别使用递归和循环来实现输入一个任意十进制正整数,从低位到高位输出各位上的数字,再实现从高位到低位输出各位上的数字

设计思想:讲一个十进制正整数分拆开得到每一位的数字,首先可以通过对10取余得到个位的数字,然后通过除以10,去掉最后一位,再重复上一步,最终可以得到每一位的数字,但是如果使用循环法,因为不知道确切位数,直接求出最高位再依次得到低位比较麻烦,可以通过从低往高求出各位的数字再通过循环逆向输出,所以使用循环法会用到两次循环,但是如果使用递归法,可以通过调整递归调用和输出函数的位置来实现正向或逆向输出。

 

 

使用循环(从低位到高位):


#include <stdio.h>
 
int main()
{
         intn,index = 1;
         printf("输入一个十进制正整数:");
         scanf("%d",&n);
         if(n< 0) {
                   printf("输入错误!\n");
                   return0;
         }
 
         while(n> 10) {
                   printf("第%d位数字是%d\n",index ,n%10);//通过对10取余取出该位的数字
                   n= n/10;//由于是整型,通过除以10达到降低位数的目的
                   index++;
         }
         printf("第%d位数字是%d\n",index ,n%10);
 
         return 0;
}



从高位到低位:

 

#include <stdio.h>
 
int main()
{
         intn,index = 1,a[100] = {0};
         printf("输入一个十进制正整数:");
         scanf("%d",&n);
         if(n< 0) {
                   printf("输入错误!\n");
                   return0;
         }
 
         while(n> 10) {
                   a[index]= n%10;
                   n= n/10;
                   index++;
         }
         a[index]= n%10;
 
         inti;
         for(i= index; i > 0; i--) {
                   printf("第%d位数字是%d\n",i,a[i]);
         }
 
         return 0;
}



使用递归从低位到高位:


#include <stdio.h>
 
void Division(int n)
{
         if(n< 10) {
                   printf("最高位为%d\n",n);
         }else {
                   printf("%d\n",n%10);
                   Division(n/10);
         }
}
 
int main()
{
         intn,index = 1,a[100] = {0};
         printf("输入一个十进制正整数:");
         scanf("%d",&n);
         if(n< 0) {
                   printf("输入错误!\n");
                   return0;
         }
 
         Division(n);
 
         return 0;
}


从高位到低位:


#include <stdio.h>
 
void Division(int n)
{
         if(n< 10) {
                   printf("最高位为%d\n",n);
         }else {s
                   Division(n/10);//先递归,待逐级返回之后再打印输出,从而实现从高位到低位
                   printf("%d\n",n%10);
         }
}
 
int main()
{
         intn,index = 1,a[100] = {0};
         printf("输入一个十进制正整数:");
         scanf("%d",&n);
         if(n< 0) {
                   printf("输入错误!\n");
                   return0;
         }
 
         Division(n);
 
         return 0;
}



上面这个题,其实很简单,其实想想,就是循环与递归的对比,从低位到高位输出的时候,没什么太大的区别,但是高位到低位顺序输出的时候,循环方法明显会麻烦一点,所以也体现了一个题选择合适的算法会提高效率避免无意义的循环!

 

 

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值