这是多年以前做的一道题目,原题来自软件报或者电脑报 ,我记不清了。解决这个题目有一个关键的步骤,就是要求一个整数在一个整数三角阵中的坐标。这篇blog就是讨论这个求坐标的问题,不是讨论那个报纸上的题目。现在将题目描述如下:

三角阵如下所示:

1

2         3

4         5         6

7        8         9        10

11       12       13       14        15

... ... ...

n     n+1    n+2             ... ...               n+k

三角阵中的每一个数字都有一个坐标对应,其中行是X轴,从右上往左下倾斜的边是Y轴。比如:2的坐标是(2,1),9的坐标是(4,3),应该很容易理解吧。下面还是从最简单的解法开始讨论。先看X轴坐标的求法。我们需要逐步的减去整数的个数,第一次减去第一行的整数个数,第二次减去第2行的整数的个数,如此重复知道给定的整数不够减而成为负数为止。这时将循环中当前使用的行数就是X轴的坐标,而不够减的数值就是Y轴的坐标。现在的问题就是怎么个减法效率才能尽可能的高,因为给定的整数可能非常的大,这里考虑理想情况,不要考虑具体一个语言的对整数溢出的限制,否则讨论算法的效率就没有意义了。

第一个方法是写一个第一项为1,公差为1的等差数列的求和函数,参数为n,返回值是前n项的和。然后开始从1循环,将返回值和给定整数比较,从而求得坐标。这个当然是最差的做法,效率几乎是最低的。如果谁在我的项目中这样写代码,那么这个月的工资会打折扣的。至少我们给出的解法应该是这样的:不能用一个求和函数来做,而是应该利用循环,从前n项的和递推出前n+1项的和,循环中应该有类似如下的递推求和代码:

nCount = nCount + 1; nSum = nSum + nCount;

由于整个计算过程使用加减完成,并且不存在回溯的情况,虽然整数有可能会很大,但是这个解法的效率应该是不会太差的,这个非常显然。因为大O时间复杂度中最高的指数为1,效率是很高的了。所以这算是一个解法,如此写代码的话至少满足使用要求,不扣工资了。

但是这个解法有一个问题,就是太过简单。当然在很多时候简单是一个非常好的特点,但是在这里不行,简单的让人觉得简陋了。思考片刻后,我得到了又一个更好的解法。那就是在循环递推前n项的和的时候,循环递增的步长不设置为固定的1,而是可变长的,比如2的整数倍,也就是每次循环递增一倍。这样通过若干次循环后,我们可以发现给定的整数会落在前一次循环(假设此时nCount等于n)所求和,和本次循环(假设此时nCount等于2n)所求和的范围之内。即便是对于一个很大的整数,由于循环的步长是2的几何数量级的增长,所以可以很快的找到这个范围。那么找到了这个范围之后又如何呢?我们可以在脑海中假设一个数组,这个数组是这个等差数列的前n项和的数组。第一个元素是前一项的和,第二个元素是前两项的和,如此,第n个元素就是前n项的和。那么我们知道了给定整数所落在的范围,于是我们就可以使用折半查找的办法来获得X轴坐标。但是需要注意的是,这个前n项和的数组不是写死的,需要在使用的时候动态计算出第n个元素的值。显然从算法的角度看这个解法的效率远比前面那个高。我一度为这个解法得意,但是在得意的同时又感到一点遗憾,就是感觉自己不是用算法解决的效率问题,而是用编程技巧解决的问题。我隐隐的感觉似乎还有一个完美的解隐藏着。

于是继续思考,没多久我终于找到了这个完美的解,找到了一个时间复杂度与给定整数大小几乎没有关系的算法。等差数列的求和公式是这样的:S = n(n+1)/2。以前的思路都是从n求得S,然后做减法再接着判断处理,在一个灵感的帮助下,我发现可以把给定的整数看做S,通过求和公式直接求得n。这时n的整数部分就是X坐标,然后减去X坐标值所表示的前若干项的和,就可以得到Y轴的坐标。

从结果看这是最好的算法,它的最优几乎可以被证明。那么如此利用了求和公式而得到的解法能不能算是一个算法呢?当时我认为是,但是由于所用知识过于简单,我不能肯定。直到2年后我自学了一本书,名字叫组合数学,其中有一章讲到了母函数。这时我才明白,我在不自觉地情况下使用了母函数的思路解决了问题。只是这个求和公式比较简单不需要求解特征方程等等相关的东西,所以我才作了出来。至此,我的疑问得到了解答,这是一个堂堂正正的算法。

一道解决的非常漂亮的算法题相关推荐

  1. 一道关于老鼠繁衍的算法题

    题目源头 这道题目是前些日子,面试阿里的时候,给的一道在线测评算法题 题目描述 大海中央的一座孤岛,上面本来没有老鼠.有一艘路过的船只在附近沉没了,船上 x 对 新出生的老鼠,顺着船只残骸漂流到小岛上 ...

  2. 一道让你拍案叫绝的算法题

    这是一道看完答案会觉得很简单,但做之前很难想到答案的题目!!! 不信? Let us go ! 题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次 ...

  3. 一道很简单的贪心算法题~【贪心:我不要脸的伐?】

    文章目录 题目描述 输入 输出 样例输入 样例输出 C语言代码实现 思路 排序 处理 完整代码 C++代码实现 排序 完整代码 彩蛋 题目描述 小健有一家自己的商店,主营牛奶饮品,最近资金紧张,他想以 ...

  4. 用队列解决击鼓传花算法题

    题目: 标号为0~6的6个小朋友围成一圈,开始数数,数到数字5的人自动淘汰,不断循环,剩下的最后一个人胜利. 问:最后胜利的人是谁? 解析: 将这6个学生放入队列中,每个人报一个数的同时出队,并重新进 ...

  5. 一道求因子之和面试算法题

    package com.project;/*一个数如果恰好等于它的因子之和,这个数就称为"完数".例如6=1+2+3.编程 找出1000以内的所有完数.(因子:除去这个数本身的其它 ...

  6. 力扣高频算法php_互联网公司最常见的面试算法题有哪些?

    很多时候,你即使提前复习了这些最常见的面试算法题,你依旧无法通过算法面试! 为什么?你在提前准备复习的时候,在网上找了半天相应题目的分析文章,但你看了就是不懂. 你在面试的时候,卡壳了,一时间忘了怎么 ...

  7. 如何出(改编)一道ACM算法题?

    本文背景 本人算法能力一般,但是为省赛和区域赛网络赛出过几道题,总结了一些自己的经验,希望与大家分享.本文不涉及具体的算法题,都是一些理论性的想法和一些建议. 题源 如果你能在没有题源的情况下自己想出 ...

  8. 【算法精讲】分享一道很不错的算法题

    戳蓝字"CSDN云计算"关注我们哦! 技术头条:干货.简洁.多维全面.更多云计算精华知识尽在眼前,get要点.solve难题,统统不在话下! 作者:帅地 转自:苦逼的码农 分享一道 ...

  9. Homebrew作者面试Google被拒,只因写不出一道算法题

    相信很多人听说过关于Max Howell(Homebrew的作者)的故事: Max Howell在Google面试,但Google拒绝了他,给出的答复是:"虽然我们90%的工程师都用你写的软 ...

最新文章

  1. 互联网巨头终极战场:得开发者得天下
  2. java Serializable 详解
  3. POI 导出excel带小数点的数字格式显示不对解决方法
  4. java闭包矩阵_深刻理解Java闭包概念
  5. 蚂蚁金服开源的机器学习工具 SQLFlow,有何特别之处?
  6. 计算机公式or,【转载】 odds、OR和RR的计算公式和实际意义
  7. if语句写阶跃函数C语言,C语言第四章分支语句.ppt
  8. idea 快捷键代码行标记并快捷跳到标记行
  9. 正月初二 | 2月13日 星期六 | 大年初一单日票房创新纪录;除夕当天外卖订单增七成;央视春晚直播受众达11.4亿人...
  10. 12.2日,第二次团队冲刺开始
  11. 英特尔:把基带卖给苹果 完全是高通逼的
  12. # 20162312 2017-2018 《程序设计与数据结构》第7周学习总结
  13. bzoj 3123 [Sdoi2013]森林
  14. 富士康跳楼事件续集,主管扬言现场把人处理掉,并表示拒不处理善后
  15. 日常如何维护OA系统?
  16. u 只读 盘 突然_u盘变成只读方式了,怎么办
  17. 马云,你不缺孩子,很多人叫你爸爸
  18. 小米手机不能发短信的一种解决方法--重新设置短信中心号码
  19. Win7 时间不准不能自动同步,执行w32tm /register发生下列错误: 拒绝访问(0x80070005)
  20. mpvue + vuex搭建小程序详细教程

热门文章

  1. 安装vuejs全过程、淘宝镜像
  2. file相对路径java_浅谈java 中文件的读取File、以及相对路径的问题
  3. TcpClient.Connect函数连接超时的问题(转载)
  4. 2019 wannafly winter camp day5-8代码库
  5. BZOJ2720: [Violet 5]列队春游
  6. 用border画三角形
  7. 文档排序--相似度模型--VSM
  8. leetcode之回溯backtracing专题1
  9. vue devtools面板没有显示_vue 基础入门(四)
  10. 脚本启动慢_Linux 常用运维脚本,建议收藏