【问题标题】:Codility OddOccurrencesInArray Problem - Recursion and PythonCodility OddOccurrencesInArray 问题 - 递归和 Python
【发布时间】:2022-01-05 18:44:25
【问题描述】:

我正在尝试使用递归来解决 Codility 中的 OddOccurrencesInArray 问题,其中

  • 给定一个包含 N 个元素的数组,N 总是奇数
  • 数组中除一个以外的所有元素的出现次数均为偶数
  • 我们需要编写返回一个未配对值的代码

例如,如果给定的数组是 [9, 3, 9, 3, 7, 9, 9],则代码必须返回 7,因为这是数组中唯一未配对的元素。

我的解决方案伪代码/思考过程是:

  • 对数组进行排序
  • 如果前两个元素彼此相等,则删除它们并在减去前两个元素的数组上再次递归运行求解算法(排序后),即如果未找到未配对的元素,我们会继续减小数组
  • 如果前两个元素不相等,则数组的第一个元素必须是未配对项

我的实现是:

def solution(A):
    # write your code in Python 3.6
    if len(A) > 1: 
        A = sorted(A)
        if A[0] != A[1]:
            return A[0]
        else:
            solution(A[2:])
    else:
        return A[0]

我不断收到错误消息

结果类型无效,应为 int,找到 。 RUNTIME ERROR(测试程序以退出代码 1 终止)

谁能帮我弄清楚这意味着什么以及如何纠正它?从算法上讲,我认为我的解决方案是合理的,但我不明白为什么它没有返回我指定的整数值。

【问题讨论】:

  • 递归对于这个问题来说太过分了;循环排序数组就足够了。如果您跟踪未配对的值,您也可以避免排序。
  • 一看你忘了在代码中return solution(A[2:])
  • @ScottHunter 除了对所有数字进行异或运算之外,其他任何事情都是多余的。

标签: python arrays recursion nonetype


【解决方案1】:

另一个 Python 解决方案 100%

还有另一种解决方案,我们可以使用 XOR 逻辑。

首先让我们一起记住 XOR 是什么意思:

所以我们可以认识到,如果我们有 Input AInput B 相同的位,那么 XOR 输出将为零。

此外,如果我们将任何数字与零进行异或,肯定会得到相同的数字,因为数字的位将产生相同的位,这意味着相同的数字。

现在,为了解决 XOR 逻辑的问题,我们首先定义一个数字,该数字将保存每次 XOR 输出的结果,所以首先,我们从零开始,我之前说过,任何数字的 0 都会给出同一个号码。

但如果我们下次得到不同的数字,XOR 结果将是某个未知数。

最后,确定没有配对的号码会被退回。

由于这样的解决方案只需要一个循环就可以实现,我们需要遍历所有元素,如果我们在某个时候执行 break,XOR 的结果将是我们不执行的某个数字需要所以我们需要确保我们遍历整个数组一次然后因为相同数字的位 XOR 将返回零。这样我们就可以将未配对的数字留在最后。

检测到的时间复杂度: O(N) 或 O(N*log(N))

def solution(A): 
     
    num = 0; 

    for i in range(0, len(A)): 
        num = num ^ A[i]        
         
    return num

【讨论】:

    【解决方案2】:

    我会建议完全不同的方法。递归方法并没有错,但是对sorted 的重复调用效率非常低,尤其是在输入非常大的情况下。

    def solve(t):
      s = set()
      for v in t:
        s.add(v) if v not in s else s.remove(v)
      return list(s)
    
    input = [9, 3, 9, 3, 7, 9, 9]
    solve(input)
    

    我们可以在评估过程中可视化s -

    {}     # <- initial s
    {9}    # <- 9 is added
    {9,3}  # <- 3 is added
    {3}    # <- 9 is removed
    {}     # <- 3 is removed
    {7}    # <- 7 is added
    {7,9}  # <- 9 is added
    {7}    # <- 9 is removed
    

    最终返回的list(s){7} 转换为[7]。要输出答案,我们可以写一个简单的if/elif/else -

    unpaired = solve(input)
    
    if (len(unpaired) < 1):
      print("there are no unpaired elements")
    elif (len(unpaired) > 1):
      print("there is more than one unpaired element")
    else:
      print("answer:", unpaired[0])
    

    另一种选择是让solve 返回第一个未配对的元素或None -

    def solve(t):
      s = set()
      for v in t:
        s.add(v) if v not in s else s.remove(v)
      for v in s:
        return v          # <- immediately return first element
    
    answer = solve(input)
    
    if answer is None:
      print("no solution")
    else:
      print("the solution is", answer)
    

    【讨论】:

      【解决方案3】:

      您没有从递归调用中返回任何内容,这意味着您正在返回 None

      【讨论】:

        【解决方案4】:
        def solution(A):
            cloned = []
            A.sort()
            if len(A) > 1:
               for itr in A:
                  if itr in cloned:
                     itrindex = cloned.index(itr)
                     cloned.pop(itrindex)
                  else:
                     cloned.append(itr)
            else:
                return A[0]
        
            return cloned[0]
        

        【讨论】:

        • 欢迎来到堆栈溢出,斯蒂芬。我认为最好通过一些解释来增强您的答案,以便其他人可以理解您的解决方案背后的逻辑!
        猜你喜欢
        • 2021-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-08
        • 2010-12-08
        相关资源
        最近更新 更多