【原创连载】算法素颜(第2篇):扫雷还可以这样玩

创作时间:2019-03-18

作者:周林

版权所有,转载请联系作者获取授权、并注明作者与出处

周林的简书主页

周林的CSDN博客主页

周林的知乎主页




       上篇文章介绍了算法的本质和基本概念,这次我们用实际的问题来做算法实战。

       假设如下场景: 公司新年晚会进行夺宝游戏,奖品是最新款的智能手机、VR游戏机、便携电脑三件套。游戏规则如下: 当主持人宣布游戏开始的时候,每位员工的手机上会同时收到两组数字(数组中的每个数字都是正整数且两两不等)和一个目标正整数。员工需要在两组数字中分别取两个数字相加,使得相加的结果与目标正整数最接近。哪位员工先做出结果,那么奖品就归谁。为了使赢率最高,请问应该采用什么样的策略或者方法?

       显然,这是在对一个特定问题找方法。那么根据上篇文章所讲到的,这就是在求算法。 那么如何算法求解呢?答案就在上篇文章提到的“朴素而广泛的方法论”中。这个方法论其实就是算法求解的套路。

套路第一步:重新定义问题,结构化描述

       原问题是生活场景,要转换成结构化问题描述。结构化描述分为如下两步:数据与规则抽取、数据结构选择与转化。


数据与规则抽取

       数据的来源:数据一般在原问题描述中以名词、量词形式出现

       数据的摘取:并不是所有的名词和量词都是有效数据。

       很明显,只有和问题求解相关的名词和量词才有意义。“问题求解”是动作,与动词相关。 那么是不是所有的动词都有效呢?也不是。只有和规则相关的动词才是有效的。

       规则的发掘:规则就是抵达结果的条件。

       根据上面的定义, 不难看出:

       数据是:两组数字(数组中的每个数字都是正整数且两两不等)、一个目标整数

      规则是:从两组数字中分别取两个数字相加,相加的结果必须与目标正整数最接近

数据结构选择与转化

       上篇文章已经讲到了:算法的依托是数据结构。如果把算法看做设计域的话,那么数据结构就是连接问题域到设计域的桥梁。那么如何选取合适的数据结构呢?答案是:对上一步摘取的数据进行类型联想、关联。


       上一步中,我们已经摘取了数据——两组数和一个正整数。很明显,这里涉及到两个类型:数组和整数。而这两个属于基础数据结构类型,至此数据结构选择问题解决了。接下来就是要对摘取的数据,基于选择的数据结构进行转化——“重整化”:

        两组数字(数组中的每个数字都是正整数且两两不等)=> int A[]; int B[];

        目标正整数 => int c;

        聪明的你,一定会问一个问题:数据结构的选择仅仅就在这一步决定吗? 答案是否定的。数据结构的选择会贯穿整个算法设计,是一个不断迭代的过程。后面部分会详细阐述。

套路第二步:问题归类

       算法问题的基本类型:搜索、排序、规划、计算。

       回到当前问题,根据问题描述,显然属于搜索类型。

套路第三步:经验匹配

       现在我们来翻看已有的搜索算法,看看有没有能与当前问题匹配的。

       理论上有3种情况:

       第1种情况,100%匹配,此时直接“拿来主义”;

       第2种情况,部分匹配,此时可在已有算法基础上进行调整、组合或者改良;

       第3种情况,完全不匹配,此时需要我们根据已有知识(甚至是跨学科知识,比方说数学、生物等),创新性地开发新算法。

       针对搜索问题,我们有一个万能算法——“暴力搜索”,即遍历每一种可能性,直到找到答案。但是这个算法要穷尽所有可能性,所以带来的时间和空间开销通常都是巨大的,用上篇文章的术语来讲,就是计算复杂度贼高。 为了给大家一个量化感觉,先用“暴力搜索”算法来解答这个题:

暴力搜索算法

       对于数组A中的每一个元素进行遍历:

              设当前元素为A[i],则:

              遍历数组b中的每一个元素B[j]:

            (i)计算A[i]+B[j]的值,将所求的值记为t;

              (ii) 计算t-c的绝对值|t-c|,记为k;

              (iii) 如果当前的k比历史的k小(k的初值可以设成一个极大值),那么:

                          将 {A[i], B[j]}取代之前的候选结果,作为新的候选结果

        待所有的遍历结束,最终的候选结果就是所要求的解。

       上面的算法有两重循环,所以暴力搜索时间复杂度为O(La x Lb)。 其中La表示数组a中元素的个数,Lb表示数组b中元素的个数。 随着La和Lb的增大,复杂度以两者乘积速度上升。

       那么如何对暴力算法进行优化呢?

       关于复杂度的计算,我会在下篇文章中详细介绍。

套路第四步:算法优化三步走

步骤1:找到算法性能瓶颈源头

             稍微分析一下,就明白:上述暴力搜索算法的开销在于穷尽了所有元素。

步骤2:对源头进行改造

             那么是否可以避免穷尽所有元素而得到结果呢?

             换言之,是否可以只比较部分元素、其他元素就自然被排除了呢?

             要得到这样的效果,显然我们需要一种性质——这种性质必须是容易获得的:

             要么可以直接从当前数据中获取,要么可以通过已有方法(算法)获取。

            最容易想到的就是有序性,这种性质可以通过排序算法获取。

            我们可以用快速排序算法对A数组和B组数进行排序,将排序后的元素按照下图放置: (为了方便表示,我们假设A数组是10个元素,B数组是11个元素)


           上图中的每个方格就是用来存放相加结果的。很显然,暴力搜索就是对上图中的每个方格都做了计算。

           现在我们要做的,就是利用有序性,避开尽可能多的方格。

           我们从右上角方格[A10, B1]开始遍历:

           记s[A10, B1] = A10 + B1,则:

            (i) 如果s[A10, B1] == 目标正整数c,那么元素对{A10, B1}即为所求解

            (ii) 如果s[A10, B1] < 目标正整数c, 那么所有与[A10,B1]在同一排的方格都不用计算了

                 原因如下:因为A1<=A2<=...<=A9<=A10,所以s[A1, B1] <= s[A2, B1] <= ... <= s[A10, B1],

                 从而这些s距离c都比s[10, B1]远,都不是所求解。

            (iii) 类似地,如果s[A10, B1] > 目标正整数c,那么所有与A[10, B1]在同一列的方格都不用计算了

           显然,按照对角线方向来遍历,每遍历一个方格,就可以避开一排或者一列的方格,感觉就像在玩扫雷游戏:)







步骤3:验证

        现在我们来验证一下优化后的算法的复杂度:

        整个算法分成两部分:

        第1部分是快速排序。快速排序算法的时间复杂度是O(nlogn),所以这部分的时间复杂度是O(MAX(LalogLa, LblogLb))

         第2部分是扫雷遍历。这部分最坏的情况就是走完整个对角线。此时共遍历La+Lb-1个方格,时间复杂度是O(La+Lb)

         两者相加得到最坏情况下的整体时间复杂度为:O(MAX(LalogLa, LblogLb)+La+Lb)


本原创系列同步在以下自媒体上更新,敬请关注:

CSDN:https://blog.csdn.net/jintianyishiyeai/

知乎:https://www.zhihu.com/people/cubiezhou2017

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