【问题标题】:Interview question - Finding numbers面试题——找数字
【发布时间】:2010-08-31 19:22:47
【问题描述】:

我刚刚在 SE 职位面试中得到这个问题,除了蛮力之外,我不太清楚如何回答:

给定一个自然数 N,找出两个数 A 和 P,这样:

N = A + (A+1) + (A+2) + ... + (A+P-1)

P 应该是可能的最大值。

例如:对于 N=14,A = 2 和 P = 4

N = 2 + (2+1) + (2+2) + (4+2-1) N = 2 + 3 + 4 + 5

有什么想法吗?

【问题讨论】:

  • A 和 P 是否允许为实数?还是必须是整数?
  • 定义蛮力。您可以从 1 开始迭代 A 的所有值并尝试在 O(1) 中为每个值找到 P 吗?
  • @EvilTeach,问题指定自然数(正整数)
  • 我什至不记得什么是自然数。也许这就是为什么我只是一个程序员而不是软件工程师的原因。 :)
  • @EvilTeach 如果 A 和 P 不是整数,那么求和就没有意义了。

标签: algorithm


【解决方案1】:

如果 N 是偶数/奇数,我们需要总和中的奇数个偶数/奇数个。这已经使可能解决方案的数量减半。例如。对于 N=14,检查任何 P 为奇数的组合是没有意义的。

重写给出的公式,我们得到:

N = A + (A+1) + (A+2) + ... + (A+P-1)
    = P*A + 1 + 2 + ... + (P-1)
    = P*A + (P-1)P/2 *
    = P*(A + (P-1)/2)
    = P/2*(2*A + P-1)

最后一行表示N必须能被P/2整除,这也排除了许多可能性。例如。 14 只有这些除数:1、2、7、14。所以 P 的可能值是 2、4、14 和 28。出于显而易见的原因,14 和 28 是我们的规则(事实上,任何高于 N/2 的 P 都可以是忽略)。

这应该比蛮力方法快很多。

(*前n个自然数之和为n(n+1)/2)

【讨论】:

  • 我不确定我是否明白你的想法:你能为15解释一下吗?据我了解,15 的除数为 1、3、5、15(清除)。因此,我们有可能的 P 值:2、6、10、30。但是 P 的值应该是 5,因为 15=1+2+3+4+5,不是吗?
  • 1+2+3+4+5 = 0+(0+1)+(0+2)+(0+3)+(0+4)+(0+5) 是A=0 和 P=6,不是吗?
  • 我认为你的意思是 N*2 必须能被 P 整除。对于 N=15,P 在 +-{1,2,3,5,6,10,15,30} 中,虽然我们可以忽略负面因素,因为 P=1 总是有效的。
  • @Strilanc:对不起,你当然是对的。我猜 P 的负值可以忽略。 @phimuemue:如果 A 必须为正,则 A=0,P=6 不是有效解决方案。
  • (事实上,任何高于 N/2 的 P 都可以忽略)——我猜 P
【解决方案2】:

对于面试问题,思考问题的目的通常是明智的。如果我要问你这个问题,并不是因为我认为你知道解决方案,而是我希望看到你找到解决方案。重新提出问题,提出影响,设计已知的东西,......这就是我希望看到的。

  • 如果你只是坐着告诉我“我不知道如何解决它”,你会立即通过面试。

  • 如果您说:我知道如何通过蛮力解决它,并且我知道它可能会很慢,我会给您一些提示或帮助您开始。如果这没有帮助,你很可能会失败(除非你展示了一些非凡的技能来弥补你在一般问题分析领域可能缺乏某些东西的事实,例如,你将展示如何实现一个针对多个内核并行化或已实现的解决方案在 GPU 上)。

  • 如果你给我一个现成的解决方案,但你无法推导出来,我会给你另一个类似的问题,因为我对解决方案不感兴趣,我对你的想法感兴趣。

【讨论】:

  • 我同意,但是,这是笔试,没有与面试官互动,论文只有上面的描述!我确实尝试写下我的想法,如果后来我想为什么那行不通,我会用一条线划过它并写下原因。我想这是等价的
【解决方案3】:

A + (A+1) + (A+2) + ... + (A+P-1) 简化为 P*A + (P*(P-1)/2)P*(A+(P-1)/2)

因此,您可以只枚举N 的所有除数,然后将每个除数P 测试为以下内容:

A = (N-(P*(P-1)/2))/P(解决了A 的第一个简化)是整数吗? (我假设它应该是一个整数,否则将是微不足道的。)如果是这样,请将其作为解决方案返回。

【讨论】:

  • “只枚举 N 的所有除数”并不容易......它相当于做一个素数分解
  • @user275455 寻找 N 的因子仍然比从 1 迭代到 N 更快。
  • (假设恒时除法)
【解决方案4】:

可以使用0-1背包解决方案。

观察:N/2 + N/2 + 1 > N

所以我们的系列是 1,2,...,N/2

考虑到所有元素的 W=N 和 vi =1 的约束,我认为这很容易映射到 0-1 背包,O(n^2)

【讨论】:

    【解决方案5】:

    这是一个 O(n) 的解决方案。

    它使用算术级数之和的性质。 S = 差值*(first_term + last_term)/2

    这里我们的和是N,差是P,第一项是A。

    操作上面的方程我们得到一些方程,我们可以从 1 到 n - 1 迭代 P 来得到一个有效的 A。

    def solve(n,p):
    return (2*n - (p**2) + p)/(2*p)
    
    def condition(n,p,a):
    if (2*n == (2*a*p) + (p**2) - p) and (a*-1 < 0):
        return True
    else:
        return False
    
    def find(n):
    for x in xrange(n,-1,-1):
        a = solve(n,x)
        if condition(n,x,a):
            return n,x,a
    

    【讨论】:

      猜你喜欢
      • 2011-05-23
      • 2011-05-23
      • 2021-12-05
      • 2020-01-07
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2011-03-04
      • 2020-09-29
      相关资源
      最近更新 更多