【问题标题】:traversing through a list using recursion使用递归遍历列表
【发布时间】:2021-10-05 11:32:11
【问题描述】:

所以我是递归新手,我正在尝试制作一个程序,您可以在其中输入一个列表,python 测试每个整数(例如 9)并查看它后面的整数是否加倍。因此,如果我输入 2 4 8 16 32 的列表,将返回 4,而 -5 -10 0 6 12 9 36 将返回 2,因为 -5 后跟 -10 是一,而 6 后跟 12 是第二个。这是我到目前为止的代码。我觉得我很接近。但只有几件事挡住了我的路。任何帮助都会很棒!

L = []
def countDouble(L):
    x = input(f'Enter a list of numbers separated by a space: ')
    y = (x.split(' '))
    print(y[1])
    print(y[0])
    count = 0
    
    y[0] += y[0]
    
# unsure of how to multiple y[0] by 2
    if y[0]*2 == y[1]:
        count += 1
    else:
        count += 0
        
#how would I traverse through the rest of the entered list using recursion?
        
    print(count)
    
countDouble(L)
  

【问题讨论】:

  • 这看起来像一个一维列表。这里没有必要/方式使用递归
  • 递归在 Python 中的使用深度既低效又有限。虽然可以将它与列表一起用于教育目的,但您永远不应该在“真实”代码中使用它:改用迭代。 Python 不是 Scheme 或 Haskell,list 类型也不是链表:它是一个可动态调整大小的数组。
  • 为什么第一个例子返回4
  • 另外,你的函数 countDouble 不是你想要递归的函数,因为它创建你想要迭代/递归的列表。
  • 你的递归函数应该有一个列表和索引。它测试该索引和index+1 处的元素。当索引是列表的末尾时它会停止——这是基本情况。

标签: python list recursion


【解决方案1】:

最终编辑:OP 编辑​​了他的示例,因此我的其他代码不适用

人们提出了一些很好的问题,但本着帮助的精神,这里有一个递归函数,它返回所有双打的计数。

def get_doubles_count_with_recursion(a_list, count, previous=None):
    while a_list:
        try:
            first = previous if previous else a_list.pop(0)
            next_item = a_list.pop(0)
        except IndexError:
            return count
        if next_item / 2 == first:
            count += 1
        return get_doubles_count_with_recursion(a_list, count, next_item)
    return count

a_list = [1, 3, 5, 10, 11, 14, 28, 56, 88, 116, 232, 464, 500]
doubles = get_doubles_count_with_recursion(a_list, 0)
print(doubles == 5)

也许可以稍微清理一下,但它比其他人的更容易阅读;)

【讨论】:

  • 或者你可以假设 14 是一个错字,应该是 16。
【解决方案2】:

如果您想/需要使用递归来解决它,以下方法可以解决问题:

def count_sequential_doubles(li, count=0):
    return count_sequential_doubles(li[1:], count + int(li[0] * 2 == li[1])) if len(li) > 1 else count

【讨论】:

    【解决方案3】:

    如果我没看错你的问题,你想计算第二个项目是第一个项目两倍的所有对。 (第一个列表中的14 是一个错字)。在这种情况下,像这样的简单函数应该可以完成这项工作:

    #a = [2,4,8,16,32]
    a = [-5, -10, 0, 16, 32]
    
    count = 0
    for i, x in enumerate(a):
      # Stop before the list overflows
      if i < len(a) - 1:
        # If the next element is double the current one, increment the counter
        if a[i+1] == x * 2:
          count = count + 1
      else:
        break
    
    print(count)
    

    【讨论】:

    • 不是递归,OP是专门询问使用递归
    【解决方案4】:

    我会建议这种递归方式:

    def countDouble(L):
        count = 0
        if len(L) == 1:
            return count
        else:
            if int(L[0])*2 == int(L[1]):
                count += 1
            return count + countDouble(L[1:])
    
    x = input(f'Enter a list of numbers separated by a space: ')
    y = (x.split(' '))
    
    count = countDouble(y)
    print(count)
    

    【讨论】:

      【解决方案5】:

      我敦促您阅读完整的答案,但如果您对提示、注释和寻找解决方案的过程不感兴趣,这里有两个解决方案:

      使用递归的解决方案(不推荐):

      x = input()
      y = x.split(' ')
      count = 0
      def countDouble(i):
          if(i+1 == len(y)):
              return 'recursion ends here when'
          if(int(y[i])*2==int(y[i+1])):
              count += 1
          countDouble(i+1)
      countDouble(0)
      print(count)
      

      这个解决方案只是模仿了一个while循环:

      使用 while 循环的解决方案(推荐):

      x = input()
      y = x.split(' ')
      count = 0
      i = 0
      while(i < len(y) - 1):
          if(int(y[i]) * 2 == int(y[i+1])):
              count += 1
          i += 1
      print(count)
      

      在我继续之前,这里有一些提示和注意事项:(其中一些只有在之后才有意义)

      • 我认为您示例中的 14 是错字
      • 我没有将代码放在函数中,因为它不需要,但您可以轻松更改它。
      • 在您的代码中,您将 L 作为参数传递给 countDouble() 函数,但您没有使用它。如果您不需要参数,请不要传递它。
      • 拆分输入时,列表的值仍然是字符串。因此在比较它们的值之前,您必须将它们反转为整数(例如,您可以使用 int() '函数') - 否则乘以 2 只会重复字符串。例如:'13'*2 是字符串'1313'
      • 我不知道您为什么在第 9 行中将 y[0] 添加到自身,但根据后面的代码会产生不正确的结果,您无需更改元素即可获得它们的值乘以 2。
      • 请注意,在 else 块中,没有任何变化。将 0 添加到计数不会改变它。这样您就可以完全删除 else 块

      虽然可以通过递归来解决问题,但还为这类问题设计了其他东西:循环。 问题本质上是对列表的每个元素重复一个简单的检查。

      这就是我要找到解决方案的方式

      所以我们要运行以下“代码”:

      if(y[0]*2 == y[1]):
          count += 1
      if(y[1]*2 == y[2]):
          count += 1
      if(y[2]*2 == y[3]):
          count += 1
      ...
      

      当然,计算机不理解“...”是什么意思,但它让我们对代码中的模式有了一个概念。现在我们可以执行以下操作:

      1. 将扩展的“代码”分成相似的部分。
      2. 识别模式中的变量 - 部分之间变化的值
      3. 找出所有变量的起始值
      4. 在每个变量的变化中寻找规律
      5. 找到一个断点,即一个变量的条件,告诉我们已经到达最后一个重复部分。

      这里是这个特定问题的步骤:

      1. 这些部分是 if 语句
      2. 变量是我们比较的 y 中元素的索引
      3. 第一个索引从 0 开始,第二个索引从 1 开始
      4. 每个 if 语句后两个索引都增加一个
      5. 当第二个索引大于 y 的最后一个索引时,我们已经检查了所有元素,我们可以停止

      剩下的就是设置所需的变量,有一个带有我们找到的中断条件的while循环,并且在while循环中有重复部分的一般情况,然后是变量的变化。 所以:

      x = input(f'Enter a list of numbers separated by a space: ')
      y = (x.split(' '))
      count = 0
      # setting the starting values of the variables
      index1 = 0
      index2 = 1
      # creating a loop with the breaking condition
      while(index2 < len(y)):
          # the general case of the repeated code:
          if(int(y[index1]) * 2 == int(y[index2])):
              count += 1
          # changing the variables for the next loop
          index1 += 1
          index2 += 1
      print(count)
      

      我们看到 index2 始终只是 index1 + 1。所以我们可以这样替换它:

      x = input(f'Enter a list of numbers separated by a space: ')
      y = (x.split(' '))
      count = 0
      index1 = 0
      while(index1 + 1 < len(y)):
          if(int(y[index1]) * 2 == int(y[index1 + 1])):
              count += 1
          index1 += 1
      print(count)
      

      注意:你可以使用类似于 while 循环的 for 循环

      总而言之,您可以使用递归来解决问题,但递归只是模仿循环的过程: 在每次调用中,都会检查中断条件,运行重复的代码并且变量/参数会改变。 希望你觉得这个答案有用:)

      【讨论】:

        猜你喜欢
        • 2019-08-03
        • 2016-04-30
        • 2014-03-01
        • 2021-10-11
        • 2021-09-19
        • 1970-01-01
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多