• 重拾程序设计题


    重拾程序设计题

      今天是情人节,我竟然乖乖地去想明白一个题目。。。终于被我想明白了,也是比较高兴的,因为我昨晚对优化的第二种解法想不明白

      昨晚跟某强闲聊,说在练习python题,计算:1+2+..+(n-1)+n的和,一开始以为他是不记得python语法,所以很久都弄不出来,老实说,裸打我也不记得,不仅python,C的语法我也挺模糊。。。

      后来才发现他说是没想到怎么解决,也就是解题的逻辑,我就说人是怎么思考解决的,转化为计算机能懂的语言(编程),就行了。

      之后就推荐他看看程序设计的题目,一开始不需要写,但是要想,而且尽力想明白(这个过程我知道是很辛苦的啦,过来人,苦闷、无聊、郁闷...不过坚持下去,逻辑思维能力、读题理解能力等肯定会有一个质的提升)。最后扔了两个题目网址给他:

    (1)https://leetcode-cn.com/problemset/all/   ---- 职场人刷题多

    (2)http://poj.org/problemlist ---- 学生党多

      (今天才发现以前在里面刷了300+题目的杭电oj竟然不再对外开放了,有点伤感)

      为了督促自己,我也希望这篇文章之后,坚持每天或者每周思考一些程序设计的题目。脑袋瓜不用真是容易用进废退的,然后买来的书不看也是劳民伤财的

    #######################  上面都是废话

    一、问题

      临睡之前,我看了一条题,来自《算法竞赛入门经典》的第1章 例题18 开放式学分制(对应 UVa 11078),为什么选了这条题,因为题目够短

      这里不给出源代码,只有伪代码,哈哈哈,因为我不记得怎么写了

      我先简化下题目:

      给出n个整数的序列:A0,A1,。。。。,An-1,现在需要从中找出两个整数 Ai 和 Aj(i < j),使得Ai - Aj 尽量大

    【输入格式】

      每组数据的第一行为整数的个数n(2 <= n <= 100000),以下n行,每行末一个绝对值不超过150 000 的整数

    【输出格式】

      输出 Ai - Aj 的最大值

     

    二、问题分析

      1、最容易想到的解决方法:两个for循环去解决

      伪代码如下:

    1 ans=A[0] - A[1]
    2 
    3 for (i=0; i < n; i++)
    4     for (j = i+1; j < n; j++)
    5         ans = max(ans, A[i] - A[j])
    6 
    7 print ans

      从A0开始,比较A1,。。。An-1 与A0 的差值;然后下一个循环,A1开始,比较A2。。。An-1 与 A1 的差值,不断重复这个过程。

      要算的次数:(n-1) + (n-2) + ...+2+1= n*(n-1)/2

      也就是时间复杂度为: O(n^2)

      要是提交这个代码,TLE跑不掉(Time Limit Exceeded)

      俺不纠结这个,大部分人都能想到的。然后看了第二种方法,书中写的特别拗口:对于每个固定的 j,我们应该选择的是 小于 j 且 Ai 最大的 i,而和 Aj 的具体数值无关。 这样,我们从小到大枚举 j, 顺便维护 Ai 的最大值即可。

      一脸懵逼。。。不知所云,不明觉厉

     

      2、优化算法 O(n)

      我先举一个整数序列,就容易明白了:

    -5 3 8 -2 8 9 -16 -1 -1 

       是不是人眼一看就知道 9 - (-16)是最大的,因为我们选了一个Ai 最大的值,也就是整数9,Aj 的值我们不管它大小,想想Aj固定的情况下,Ai 是不是应该越大越好?所以上面红字就说跟 Aj 无关。

       对于每一个Aj来讲,假设扫描到 -16。我们是不是要比较 -16 之前 哪个Ai 是最大的,然后跟 Aj 做差,来获取一轮的 Ai - Aj。

       然而这还不够,我们要维护一个在Aj 之前,也就是Aj-1,前面序列的: Ai - Aj-1 的最大值。例如,当遍历到-16这个数时,要知道 -5 到 9 这个序列(-5 3 8 -2 8 9)的最大 Ai - Aj 

       所以,每扫描一个A[j],应更新 A[i] 的最大值,且得到 A[i] - A[j-1] 的最大差值。每遍历一个数都能获得当前两个值的最大值,扫描到最后就是最终结果

          伪代码贴下:

    ans = A[0] - A[1]
    MaxAi = A[0]
    for ( j = 1; j < n; j++) ans = max(ans, MaxAi - A[j]) MaxAi = max(A[j], MaxAi) print ans

      如果还有啥不懂,欢迎交流~~~

      希望自己也能捡回这个想题的习惯吧,这玩意还是挺有意思的,能锻炼:

    (1)读题、理解能力  ——》理解需求(工作、或者别人交待的问题),理解清楚,这个是基础

    (2)英文(有些题库是国外,纯英语)  ——》 英文还是不能落下

    (3)算法解题  ——》 工作问题或者生活问题怎么想的,怎么解决的思路

    (4)优化能力  ——》 有基本解题思路,还要想想如何更优处理,不要TLE之类的,实际工作中就是节省时间和空间成本

    时间类比成,跑一个代码结果一天都跑不下来的,想想就很郁闷>_<||

    空间可以理解为,魂斗罗游戏设计只有100多k(https://www.zhihu.com/question/50076174/answer/1101330430),节省很多硬盘空间,短小精悍

     

  • 相关阅读:
    SQL SERVER 修改表名、列名
    AgilePLM维护中,重启能解决的问题
    联通银铃小龙卡3G流量领取方法
    更改github默认分支main为master
    SQL基础:显示不存在的分组数量为0
    关于添加EF CODE First的问题
    安装Windows Service总是发生异常!
    通过Anaconda3pip安装opencvpython包失败的处理方法(亲测有效)
    jenkins安装及配置(一)
    Windows添加多个github ssh秘钥域名映射
  • 原文地址:https://www.cnblogs.com/windysai/p/15894509.html
Copyright © 2020-2023  润新知