【问题标题】:How to solve this recursion question I saw during job interview?如何解决我在求职面试中看到的这个递归问题?
【发布时间】:2022-01-26 11:31:41
【问题描述】:

我在在线评估期间被问到这个问题(我是一名正在寻找 SDE 实习的学生),但无法及时解决(我只给了 5 分钟......)。顺便说一句,你们认为这个问题 5 分钟就够了吗?我只是有点好奇其他人有多好。

不管怎样,问题来了:

给你两个整数元组(A, B)(C, D)
您可以进行两种操作:
(A + B, B)
(A, A + B)
编写一个返回True 的函数,如果使用这两种操作可以将(A, B) 转换为(C, D)False 否则。

例子:

Input: A = 2, B = 3, C = 8, D = 11
Output: True

我会把我在评估期间写的“想法”写在这里(我只有 70% 的把握)。它似乎工作正常,我不确定为什么它不能通过测试。如果你们知道问题是什么,或者正确的解决方案,请告诉我!

def func(A, B, C, D):
    if A == C and B == D:
        return True
    if A > C or B > D:  
        return False

    return func(A + B , B, C, D) or func(A, A + B, C, D)

【问题讨论】:

  • 如果任何一个数字是负数怎么办?
  • @oleksii-tambovtsev hmmmm (2, 3, 13, 8) 应该是真的吗?那我错过了什么
  • @Latra 也许我误解了这个任务,但我认为在每一步中你都可以将第二个元素添加到第一个元素中,反之亦然。所以你可以有(2, 3) -> (2 + 3, 3) -> (5, 3 + 5) -> (5 + 8, 8) = (13, 8)
  • 有趣的是,这个问题如何获得如此多的赞成票,而 cmets 中的每个人都在抱怨一个不清楚的问题。支持者是否可以帮助所有人更好地解决这个问题?
  • ABCD 有哪些限制?如果A, B, C, D < N,我的答案是O(N^2)

标签: python algorithm recursion


【解决方案1】:

这是一个完整的解决方案,适用于正整数和负整数的混合。

我不希望未来的实习生能在 5 分钟内解决这个问题。他们期望你这样做的事实我会称之为危险信号。

def op_test(a, b, c, d):
    if a == c and b == d:
        return True

    if max(a, b) < 0 and min(a, b) < min(c, d):
        # No way to increase min(a, b)
        return False
    elif 0 < min(a, b) and max(c, d) < max(a, b):
        # No way to decrease max(a, b)
        return False

    # The 0 checks are to avoid endless recursion.
    if 0 != a and op_test(a, a+b, c, d):
        return True

    if 0 != b and op_test(a+b, b, c, d):
        return True

    return False

【讨论】:

  • @SaiPardhu 我知道是的。这就是为什么指出他们提出了人们合理地不应该知道的问题是一个有用的危险信号。如果面试官通过展示他们知道如何去做来证明他们有多聪明 - 换一种方式。
【解决方案2】:

您必须小心,如果 A==0 或 B==0,您可能会获得无限递归并破坏您的堆栈。您需要检测该条件并返回 False。

return (B != 0 and func(A + B , B, C, D)) or (A != 0 and func(A, A + B, C, D))

【讨论】:

  • 当整数可以是正数或负数时,现有的保护条件不起作用。
  • @btilly 我没有说这是代码的唯一问题。这只是我跳出来的第一件事。
【解决方案3】:

从目标向下有一条独特的路径(假设为正整数),因此请朝该方向移动以避免较大的搜索空间。

即总是将较大的坐标减少较小的坐标,或任何 不会超出目标的较小值的整数倍。

例如8,11 -> 8,3 -> 2,3 是从目标向下的唯一路径,通过将较大的坐标减少不超调的较小的最大倍数来获得。


只要起点和终点坐标在同一个象限,我们就可以使用类似的逻辑。


如果起点在 I 或 III 象限,而终点在 II 或 IV 象限,则没有解决方案。对于相反的情况,我认为(但尚未证明)如果 gcd(A,B) = gcd(C,D) 存在解决方案。孩子们上床睡觉后,我会回到这个并编辑我的答案。

【讨论】:

  • “有一条独特的路径”:如何?
  • 将大减小@yves
  • 哎呀,对!
  • 这是对的,假设您有效地重复减法(例如使用模运算符),这将在对数时间内运行。
  • 但他们没有告诉你假设为正整数。
【解决方案4】:

希望对你有帮助

def recursively(A,B,C,D):

    if A < C :
        A = A + B
        return recursively(A,B,C,D)
    if B < D:
        B = A + B
        return recursively(A,B,C,D)
    if A  == C and B == D:
        return True
    if A > C and B > D:
        return False
    return False


print(recursively(2,3,8,11))

【讨论】:

  • 此代码并不总是有效,例如 (1, 3) 到 (5, 4)。解决方案是 (1, 3) -> (1, 4) -> (5, 4),但此代码从步骤 (1, 3) -> (4, 3) 开始,从那里无法到达目标。
【解决方案5】:

您可以尝试使用 BFS 或 DFS 方法。我会选择 BFS,因为它会让你最快到达那里(解决方案状态)。此外,请确保在没有解决方案(无法达到 C、D)的情况下停止循环的阈值

【讨论】:

    猜你喜欢
    • 2020-03-26
    • 2021-01-11
    • 1970-01-01
    • 2021-09-15
    • 2022-12-04
    • 2010-10-15
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    相关资源
    最近更新 更多