【问题标题】:Fix the solution of "Binary period"修复“二进制周期”的解决方案
【发布时间】:2019-11-30 06:24:55
【问题描述】:

我找到了这个任务并完全坚持它的解决方案。

给出了一个由 Q 个字符组成的非空零索引字符串 S。这个字符串的周期是最小的正整数 P 使得:

P ≤ Q / 2 和 S[K] = S[K+P] 对于 0 ≤ K

例如,7 是“abracadabracadabra”的句号。如果 M 是 N 的二进制表示的周期,则正整数 M 是正整数 N 的二进制周期。

例如,1651 的二进制表示为“110011100111”。因此,它的二进制周期是5。另一方面,102没有二进制周期,因为它的二进制表示是“1100110”,它没有周期。

考虑上述场景并在 Python 中编写一个函数,该函数将接受整数 N 作为参数。给定一个正整数 N,函数返回 N 的二进制周期,如果 N 没有二进制周期,则返回 -1。

附加代码在某些输入(9、11、13、17 等)上仍然不正确。目标是找到并修复实现中的错误。最多可以修改2行。

def binary_period(n):
    d = [0] * 30
    l = 0
    while n > 0:
        d[l] = n % 2
        n //= 2
        l += 1
    for p in range(1, 1 + l):
        ok = True
        for i in range(l - p):
            if d[i] != d[i + p]:
                ok = False
                break
        if ok:
            return p
    return -1

【问题讨论】:

  • 你能提供失败的示例测试用例吗?
  • @venkatakrishnan 例如 9 是“1001”。但函数返回 3

标签: python python-3.x binary


【解决方案1】:

我在一次采访中得到了这段代码。

练习的目的是查看错误在哪里。

作为函数的输入,您将键入整数以查看它的二进制周期。例如solution(4) 会给你一个二进制数0011

但是,问题如下:错误是什么?

这种情况下的错误不是一些崩溃和烧毁代码,而是应该发生的行为并且在代码中不发生。

在代码中称为logical error。逻辑错误是代码未中断但未满足要求时的错误。

对代码使用蛮力无济于事,因为有十亿种可能性。

但是,如果您运行代码,假设从 solutions(1)solutions(100),您会看到代码运行时没有任何故障。但是,如果您正在查看代码,如果有错误,它应该返回 -1

即使您对更大的数字(如 10000)运行解决方案,代码也不会给出任何 -1

这里的错误在于没有被触发的-1。

那么让我们一步一步来编写代码吧。

可能是while 部分吗?

while n > 0:
    d[l] = n % 2
    n //= 2
    l += 1

如果您查看代码,它正在做它应该做的事情,将给定的数字更改为二进制数,即使它是从后面的位置做的。你有1101,而不是1011,但它可以完成这项工作。

问题在于那部分

for p in range(1, 1 + l):
        ok = True
        for i in range(l - p):
            if d[i] != d[i + p]:
                ok = False
                break
        if ok:
            return p
return -1

它没有返回-1

如果你像这样在代码的某些部分上打印,这会给你这个

for p in range(1, 1 + l):
    ok = True
    for i in range(l - p):
        print('l, which works as an incrementor is substracted to p of the first loop',p,l-p)
        if d[i] != d[i + p]:
            ok = False
            break
    if ok:
        return p
return -1

如果您运行整个脚本,实际上,您可以看到即使d[i] 不再等于d[i+p],它也不会结束。

但是为什么呢?

原因是因为 l,增量器是建立在整数除法之上的。因此,您需要发送1+l//2

这为您提供以下内容

def solution(n):
    d = [0] * 30
    l = 0
    while n > 0:
        d[l] = n % 2
        n //= 2
        l += 1
    for p in range(1, 1 + l//2): #here you put l//2
        ok = True
        print('p est ',p)
        for i in range(l - p):
            if d[i] != d[i + p]:
                ok = False
                break
        if ok:
            return

现在,如果您使用solutions(5) 运行代码,则应该修复错误并且您应该拥有-1


附录:

这个测试是一个困难的测试,算法不容易在很短的时间内处理,变量没有任何意义。

第一步是问以下问题:

  • 算法的输入是什么?在这种情况下,它是一个整数。
  • 预期输出是多少?在这种情况下,-1
  • 是逻辑错误还是崩溃和烧毁错误?在这种情况下,这是一个逻辑错误。

这些循序渐进的步骤 (heuristic) 将为您指明调试问题的正确方向。

【讨论】:

  • 嘿!感谢您对此编码挑战的回答,并对我迟来的问题感到抱歉,但我想知道为什么这条线 d = [0] * 30 可以?如果我尝试使用 2^32-1 代码会中断...对吗?
  • @hdlopez d = [0] * 30 正在制作一个包含 30 个零的列表。 2 power 32 minus 1 就像使用蛮力。不知道,但很可能,它会起作用。
【解决方案2】:

跟进安迪的解决方案并检查@hdlopez评论,在传递int.MaxVal=2147483647时出现边界情况 如果您不将数组大小增加到 31(而不是 30)。函数抛出一个超出范围的索引,所以需要修改两个地方:

1-int[] d = new int[31]; //changed 30 to 31 (unsigned integer)

2-for (p = 1; p < 1 + l / 2; ++p) //added division to l per statement, P ≤ Q / 2

【讨论】:

  • 是的!这正是我解决问题的方法。谢谢@jvmcollaborator
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 2013-02-02
  • 2021-02-04
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多