一天一算法题,将复杂问题进行分解!

算法其实并不是那么遥不可及,很多程序员都觉得自己不懂算法,其实他们每天都在使用着。例如,把提供给用户的数据按照某一个维度排一个序;对用户的请求做一个去重。这些都是算法。

在面试中,我们常常会被面试到算法题,甚至被要求写代码。一方面是考察你的算法基础,更重要地是看你分析问题的能力。

今天我们来看一个这么一个问题:

大家都玩过手机游戏,会根据你最后的分数,给你3颗星,或者2颗星,或者1颗星。今天我们有这样的一个游戏,首先,我们有若干个器皿,每个器皿里面都没有细胞,我们有下面两种操作:

1.往某一个器皿中加入一个新的细胞。

2.用一个特殊射线让所有器皿中的所有细胞一分为二。(假设细胞都可以分裂,且不会死掉)。

现在,我们一开始有n个器皿,通过一个系列的操作,我们让器皿中的细胞个数分别为a[1],a[2],a[3]..a[n]。如果用户用最少的操作完成目标,我们给他3颗星,现在我们想知道最少需要多少次操作。

例子1: n = 2, a = {1, 2} 结果为3

例子2: n = 2, a = {4, 8} 结果为5步,使用3次操作1,变成{1, 2}, 然后进行2次操作2。

思考:

很多人,一看到这个题目,一般都立马萌了。脑海中划过千万只草泥马,不对,千万种算法,都对应不上,然后GG。

干货1:问题分解,把简单的问题简单化!

我们先不做这个题目,我们来想一想另外一个问题。有两个操作, 加1 或者 乘以2, 如何把0变成x。例如 8 = (0 + 1) * 2 * 2 * 2。

然后我们再想一个问题,1个x,可以进行两个操作, 减1 或者 除以2(如果是2的倍数),如何更快地把x 变成 0. 例如15 : (((15 - 1 ) / 2 - 1) / 2 - 1) / 2 - 1 = 0.

不难发现,我们要尽量地使用乘除,少用加减。于是乎,我们有了这么一个算法。

一天一算法题,将复杂问题进行分解!至此,我们解决了这么一个子问题。我们知道了每个目标数需要多少次加法,多少次乘法。

让我们来看另外一个问题,假如我们知道每个数需要多少次加法跟乘法,我们总共需要多少次呢?我们来回头看一看规则。

1.往某一个器皿中加入一个新的细胞。

2.照射一个特殊射线让所有器皿中的所有细胞一分为二。(假设可以无穷分裂)。

我们发现,加法是不能共享的,但是乘法可以。我们举个例子来说明一下, a = {2, 4, 10},分别需要1,2,3次乘法和都需要{1,1,2}加法。

{0,0,1} a[3] 加 1

{0,0,2} 使用乘法

{0,1,2} a[2]加1

{0,2,4} 使用乘法

{1,2,5} a[1],a[3]加1

{2,4,10}使用乘法

总结:

经过上面的分析,这个题目的结果就是先求出每一个数的加法跟乘法的数量,然后最后结果为total{add} + max{mul},即总的加法次数与最大的乘法次数。

给大家留两个思考题,可以在评论中留言:

  1. 为什么要尽量用乘法。 有没有多用加法,少乘法的情况

  2. 如果题目换成加法共享,乘法独占,这个题目又应该怎么做?

欢迎大家关注我的头条号,也可以关注我的微信公众号(ddpcyh),会提供算法学习资料,一起来学习算法吧。

个人资料
hadoop迷
等级:6
文章:30篇
访问:2.2w
排名: 13
推荐圈子
上一篇: 算法入门----深度优先搜索
下一篇:一天一算法题,二分法的妙用
猜你感兴趣的圈子:
每日一算法
标签: 乘法、器皿、细胞、加法、颗星、面试题
隐藏