算法思想

算法思想有很多,业界公认的常用算法思想有8种,分别是枚举、递推、递归、分治、贪心、试探法、动态迭代和模拟。至于还有其他的,你们非要抬扛,show me your code. 本文主要介绍以上8种

1. 枚举

枚举算法的思想是:将问题的所有可能的答案一一列举,然后根据条件判断此答案是否合适,保留合适的,丢弃不合适的。

在C语言中,枚举算法一般使用while循环实现

1.1使用枚举算法解题的基本思路如下。

  • 确定枚举对象、枚举范围和判定条件
  • 逐一列举可能的解,验证每个解是否是问题的解
    枚举算法一般按照如下3个步骤进行。
  • 题解的可能范围,不能遗漏任何一个真正解,也要避免有重复
  • 判断是否是真正解的方法
  • 使可能解的范围降至最小,以便提高解决问题的效率

1.2 示例demo

问题描述:我国古代数学家在《算经》中有一道题:“鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?”意为:公鸡每只5元,母鸡每只3元,小鸡3只1元。用100元钱买100只鸡,问公鸡、母鸡、小鸡各多少?


    int x,y,z;
               for(x=0;x<=20;x++)
               {
                   for(y=0;y<=33;y++)
                   {
                       z=100-x-y;
                       if (z%3==0 &&x*5+y*3+z/3==100)
                           printf("鸡翁%d¸鸡母%d,鸡雏%d\n",x,y,z);
                   }
               }

结果如下

鸡翁0¸鸡母25,鸡雏75
鸡翁4¸鸡母18,鸡雏78
鸡翁8¸鸡母11,鸡雏81
鸡翁12¸鸡母4,鸡雏84

2. 递推

1相比,递推算法能够通过已知的某个条件,利用特定的关系得出中间推论,然后逐步递推,直到得到结果为止。由此可见,递推算法要比枚举算法聪明,它不会尝试每种可能的方案。

2.1 递推算法可以不断利用已有的信息推导出新的东西,在日常应用中有如下两种递推 算法。

  • ① 顺推法:从已知条件出发,逐步推算出要解决问题的方法。例如斐波那契数列就可以通过顺推法不断递推算出新的数据。
  • ② 逆推法:从已知的结果出发,用迭代表达式逐步推算出问题开始的条件,即顺推法的逆过程。

2.2 示例demo

问题描述:斐波那契数列因数学家列昂纳多•斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”。一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?

  int i;
           long fib[NUM] = {1,1};
           
           for(i=2;i<NUM;i++)
           {
               fib[i] = fib[i-1]+fib[i-2];
           }
           for(i=0;i<NUM;i++)
           {
               printf("%d月+++ 兔子数:%ld\n", i, fib[i]);
           }

结果:

0月+++ 兔子数:1
1月+++ 兔子数:1
2月+++ 兔子数:2
3月+++ 兔子数:3
4月+++ 兔子数:5
5月+++ 兔子数:8
6月+++ 兔子数:13
7月+++ 兔子数:21
8月+++ 兔子数:34
9月+++ 兔子数:55
10月+++ 兔子数:89
11月+++ 兔子数:144
12月+++ 兔子数:233

3. 递归

递归算法思想往往用函数的形式来体现,所以递归算法需要预先编写功能函数。这些函数是独立的功能,能够实现解决某个问题的具体功能,当需要时直接调用这个函数即可。

3.1 递归算法有如下3个特点。

  • 递归过程一般通过函数或子过程来实现。
  • 递归算法在函数或子过程的内部,直接或者间接地调用自己的算法。
  • 递归算法实际上是把问题转化为规模缩小了的同类问题的子问题,然后再递归调用函数或过程来表示问题的解。

3.2 在使用递归算法时,应该注意如下4点。

  • ① 递归是在过程或函数中调用自身的过程。
  • ② 在使用递归策略时,必须有一个明确的递归结束条件,这称为递归出口。
  • 递归算法通常显得很简洁,但是运行效率较低,所以一般不提倡用递归算法设计程序。
  • ④ 在递归调用过程中,系统用栈来存储每一层的返回点和局部量。如果递归次数过多,则容易造成栈溢出,所以一般不提倡用递归算法设计程序

3.3 示例demo:???

问题描述:寺院里有3根柱子,第一根有64个盘子,从上往下盘子越来越大。方丈要求小和尚A1把这64个盘子全部移动到第3根柱子上。在移动的时候,始终只能小盘子压着大盘子,而且每次只能移动一个。


int count = 0;  //统计移动次数
void hanNuoTa(int n,char x,char y,char z){ //x,y,z分别是三个柱子,
//第二个参数和第四个参数代表上面的盘子从这个柱子到那个柱子的移动过程
                                     //n是盘子数
    if(n == 1){
        printf("%c-->%c\n",x,z);
        count++;
        return;
    }
    hanNuoTa(n-1,x,z,y);  //第一步,把x最上面的n-1个盘子从x移动到y
    printf("%c-->%c\n",x,z);  //第二步,再把x上剩下的最上面的盘子放在z上
    count++;
    hanNuoTa(n-1,y,x,z);  //第三步,把y上面的n-1个盘子从y移动到z
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        int h;
        printf("请您输入要移动的盘子个数: ");
        scanf("%d",&h);
        printf("移动%2d盘子的步骤:\n",h);
        hanNuoTa(h,'a','b','c');
       
    }
    return 0;
}

结果

请您输入要移动的盘子个数: 3
移动 3盘子的步骤:
a-->c
a-->b
c-->b
a-->c
b-->a
b-->c
a-->c
Program ended with exit code: 0

4. 分治

分治算法是采取了各个击破的方法,将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。只要求出子问题的解,就可得到原问题的解。

4.1 使用分治算法解题的一般步骤如下。

  • 分解,将要解决的问题划分成若干个规模较小的同类问题。
  • 求解,当子问题划分得足够小时,用较简单的方法解决。
  • 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

5. 贪心

哈哈,你的温柔我永远不懂

贪心算法也被称为贪婪算法,它在求解问题时总想用在当前看来是最好方法来实现。这种算法思想不从整体最优上考虑问题,仅仅是在某种意义上的局部最优求解。虽然贪心算法并不能得到所有问题的整体最优解,但是面对范围相当广泛的许多问题时,能产生整体最优解或者是整体最优解的近似解。由此可见,贪心算法只是追求某个范围内的最优,可以称之为“温柔的贪婪”

贪心算法从问题的某一个初始解出发,逐步逼近给定的目标,以便尽快求出更好的解。当达到算法中的某一步不能再继续前进时,就停止算法,给出一个近似解。由贪心算法的特点和思路可看出,

5.1 贪心算法存在以下3个问题。

  • 不能保证最后的解是最优的。

  • 不能用来求最大或最小解问题。

  • 只能求满足某些约束条件的可行解的范围。

5.2 贪心算法的基本思路如下。

  • 建立数学模型来描述问题。

  • 把求解的问题分成若干个子问题。

  • 对每一子问题求解,得到子问题的局部最优解。

  • 把子问题的局部最优解合并成原来解问题的一个解。

5.3 实现该算法的基本过程如下。

  • (1)从问题的某一初始解出发。
  • (2)while能向给定总目标前进一步。
  • (3)求出可行解的一个解元素。
  • (4)由所有解元素组合成问题的一个可行解。

6.试探法(回溯法)

试探法也叫回溯法,试探法的处事方式比较委婉,它先暂时放弃关于问题规模大小的限制,并将问题的候选解按某种顺序逐一进行枚举和检验。当发现当前候选解不可能是正确的解时,就选择下一个候选解。如果当前候选解除了不满足问题规模要求外能够满足所有其他要求时,则继续扩大当前候选解的规模,并继续试探。如果当前候选解满足包括问题规模在内的所有要求时,该候选解就是问题的一个解。在试探算法中,放弃当前候选解,并继续寻找下一个候选解的过程称为回溯。扩大当前候选解的规模,并继续试探的过程称为向前试探。

6.1试探算法解题的基本步骤如下所示

  • 针对所给问题,定义问题的解空间。
  • 确定易于搜索的解空间结构。
  • 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

试探法为了求得问题的正确解,会先委婉地试探某一种可能的情况。在进行试探的过程中,一旦发现原来选择的假设情况是不正确的,立即会自觉地退回一步重新选择,然后继续向前试探,如此这般反复进行,直至得到解或证明无解时才死心

7. 动态迭代-辗转法

迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,在解决问题时总是重复利用一种方法。与迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代法又分为精确迭代和近似迭代。“二分法”和“牛顿迭代法”属于近似迭代法,功能都比较类似。

利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。

7.1 在使用迭代算法解决问题时,需要做好如下3个方面的工作。

  • (1)确定迭代变量 在可以使用迭代算法解决的问题中,至少存在一个迭代变量,即直接或间接地不断由旧值递推出新值的变量
  • (2)建立迭代关系式 迭代关系式是指如何从变量的前一个值推出其下一个值的公式或关系。通常可以使用递推或倒推的方法来建立迭代关系式,迭代关系式的建立是解决迭代问题的关键
  • (3)对迭代过程进行控制 在编写迭代程序时,必须确定在什么时候结束迭代过程,不能让迭代过程无休止地重复执行下去。

7.2 通常可分为如下两种情况来控制迭代过程:

  • 所需的迭代次数是个确定的值,可以计算出来,可以构建一个固定次数的循环来实现对迭代过程的控制
    + 所需的迭代次数无法确定,需要进一步分析出用来结束迭代过程的条件

8. 模拟

模拟是对真实事物或者过程的虚拟。在编程时为了实现某个功能,可以用语言来模拟那个功能,模拟成功也就相应地表示编程成功。

随机模拟,那就看个人造化和题目规则了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容

  • 任何一个可以用计算机求解的问题所需要的计算时间都与其规模有关。 以上五种可以理解为一种思想,而不是算法。 分治法 ...
    simplehych阅读 658评论 0 1
  • 八大算法:枚举、递推、递归、分治、贪心、试探法、动态迭代和模拟算法思想。 一、枚举算法思想(暴力算法) 将问题的所...
    super_hongtao阅读 696评论 0 0
  • 分治法 分治算法采取了各个击破的方法,将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题...
    GoFuncChan阅读 676评论 0 1
  • 几种算法思想: 一、递归(保留往期第五天任务) 通过LeetCode上【70. 爬楼梯】学习中文路径:https:...
    小爆爆就是我阅读 431评论 0 1
  • 迭代法 迭代法也被称为辗转法,是一种不断用变量的旧值递推新值的过程,在解决问题时总是重复利用一种方法。与迭代法相对...
    GoFuncChan阅读 8,410评论 0 2