需要帮助递归

时间:2020-10-03 23:42:09

标签: python recursion

我试图递归计算数组中5个数字的总和。但是,我从递归函数得到的输出为0。如果我取消注释print语句,则得到的总和为15,但函数返回的总和为0。在这里我在做什么错??

我的代码-

def calcsum(arr):
  i = 0
  sum = 0
  solution(arr,sum,i)
  return sum

def solution(arr,sum,i):
  if i == len(arr):
    return

  sum = sum + arr[i]
  #print(sum,i)
  solution(arr,sum,i+1)

print(calcsum([1,2,3,4,5]))

4 个答案:

答案 0 :(得分:1)

请记住,递归至少有两种情况:

  • 基本情况:返回合计值
  • 递归大小写:返回递归结果

无论哪种情况您都不会返回值!尝试以下方法:

def solution(arr, sum_, i):
    if i == len(arr):
        return sum_

    sum_ += arr[i]
    return solution(arr, sum_, i+1)

此外,仅调用solution不会更改sumcalcsum的值,因此return sum将始终给出0。请尝试:

def calcsum(arr):
    return solution(arr, 0, 0)

(顺便说一句,在这种构造中,您创建了一个函数,该函数使用一些添加的参数将调用委托给助手,这使我想起了很多Haskell,您可能会在其中写:

calcsum :: Num a => [a] -> a
calcsum = go 0 0
  where go :: Num a => Int -> Int -> [a] -> a
        go acc idx xs
            | length xs >= idx = acc
            | otherwise        = go (acc + (xs !! idx)) idx+1 xs

您的逻辑也有些混乱。考虑使用类似的东西:

def solution(arr):
    if arr:
        # Recursive case
        x, rest = arr[0], arr[1:]
        return x + solution(rest)
    else:
        # Base case
        return 0

现在的基本情况是arr为空(而不是传递数组外部的索引时)。您计算空列表的总和,该列表只能在逻辑上由0来计算。递归情况将第一个元素从列表中拉出,并将其添加到列表其余部分的解决方案中。

答案 1 :(得分:1)

如前所述,您应该返回总和。这是迭代器版本:

def calcsum(arr):
    return solution(iter(arr), 0)

def solution(it, sum):
    for x in it:
        return solution(it, sum + x)
    return sum

print(calcsum([1,2,3,4,5]))

仅使用一个函数和一个参数的更短的方式,在递归后添加x

def calcsum(it):
    it = iter(it)
    for x in it:
        return x + calcsum(it)
    return 0

print(calcsum([1,2,3,4,5]))

两个解决方案都需要线性时间,而类似的解决方案只需要arr并将其拆分为arr[0]arr[1:],这需要整个二次时间。通过汇总1000个值的列表来比较该迭代器版本与该列表版本的基准:

0.28 ms  calcsum_1
2.70 ms  calcsum_2

基准代码:

from timeit import repeat

def calcsum_1(it):
    it = iter(it)
    for x in it:
        return x + calcsum_1(it)
    return 0

def calcsum_2(arr):
    if arr:
        x, rest = arr[0], arr[1:]
        return x + calcsum_2(rest)
    return 0

arr = [1] * 1000

for _ in range(3):
    for f in calcsum_1, calcsum_2:
        t = min(repeat(lambda: f(arr), number=1000))
        print('%.2f ms ' % t, f.__name__)
    print()

答案 2 :(得分:1)

您的代码至少有五个问题:

  • solution(arr, sum, i)中对calcsum的调用不会修改calcsum的局部变量sum,因此calcsum始终返回0;
  • 您最终为return中的递归写了return sum而不是solution,所以solution将返回None而不是返回总和这种情况
  • 您将递归调用写为solution(arr,sum,i+1)而不是return solution(arr,sum,i+1)some_variable = solution(arr,sum,i+1),所以递归调用的返回值还是会被忽略。除了return块内的语句之外,没有if语句,因此函数solution将没有返回值(或更准确地说,它将返回None);
  • 您似乎相信修改sum中的solution会修改整个程序中称为sum的任何变量。错了sum是函数的局部变量,对其进行修改不会影响程序的其余部分。
  • 在python中,调用变量sum是一个坏主意;这是内置函数的名称,因此您应该尝试为变量找到另一个名称。

为说明第四点,请尝试以下代码:

def mostly_harmless(n):
  n = 7

n = 8
mostly_harmless(n)
print('Does this set n to 7? Am I about to print 8 or 7?')
print(n)

print()

mostly_harmless(12)
print('did we set 12 = 7? did we just break all of mathematics?')
print('making sure 12 is still 12:')
print(12)
print('making sure n is still n:')
print(n)

考虑到这一点,我们可以修复您的代码:

def calcsum(arr):
  return solution(arr, 0, 0)

def solution(arr, sum, i):
  if i == len(arr):
    return sum
  else:
    return solution(arr, sum + arr[i], i+1)

print(calcsum([1,2,3,4,5]))

实际上,我们可以使用默认参数进一步简化代码:

def calcsum(arr, sum=0, i=0):
  if i == len(arr):
    return sum
  else:
    return calcsum(arr, sum + arr[i], i+1)

print(calcsum([1,2,3,4,5]))

但是请注意,python是不是的一种喜欢递归的语言。在其他一些编程语言中,递归非常好,并且与循环和while循环一样高效。但这不是python中的情况。在python中,递归比循环慢得多,并且使用更多的内存。我们可以使用for循环来重写您的程序:

def calcsum(arr):
  sum = 0
  for i in range(len(arr)):
    sum += arr[i]
  return sum

print(calcsum([1,2,3,4,5]))

甚至更好:

def calcsum(arr):
  sum = 0
  for v in arr:
    sum += v
  return sum

print(calcsum([1,2,3,4,5]))

还要注意,在python中调用变量sum是一个坏主意,因为sum是python中内置函数的名称。您可以在the python documentation中找到内置的列表;尝试为您的变量命名。

毫不奇怪,函数sum本身就可以计算总和:

print(sum([1,2,3,4,5]))

那么为什么调用变量sum如此糟糕呢?好吧,那么我们将无法使用相同名称的内置函数:

sum = 7
print(sum([1,2,3,4,5]))
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: 'int' object is not callable

通常sum指的是内置函数;但现在它引用的变量等于7;当我尝试调用sum([1,2,3,4,5])时,就好像我尝试调用7([1,2,3,4,5])一样,这没有意义,因为7不是函数。

答案 3 :(得分:1)

您可以使其“按自己的方式”工作,即,如果将sum放在变量calcsum中并增加其外部solution,则可以增加sum中的arr变量而不是拥有自己的。然后也不需要通过def calcsum(arr): def solution(i): nonlocal sum if i == len(arr): return sum = sum + arr[i] solution(i+1) sum = 0 solution(0) return sum print(calcsum([1,2,3,4,5]))

public partial class frmMain : Form
{
        SqlConnection connectionsql;
        string  connectionString;

        public frmMain()
        {
            InitializeComponent();
            connectionString = ConfigurationManager.ConnectionStrings["Equipment_Inventory.Properties.Settings.InventoryConnectionString"].ConnectionString;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            populategrid();
        }

        private void populategrid()
        {
            using (connectionsql = new SqlConnection(connectionString))
            using(SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Inventory", connectionsql))
            {
                DataTable InventoryTable = new DataTable();
                adapter.Fill(InventoryTable);
                dataGridView1.DataSource = InventoryTable;
            }
        }

        private void insert_button(object sender, EventArgs e)
        {
            string query = "insert into Inventory (InternalNumber, Grupa, Type, Manufacturer, Equipment) values (@InternalNumber, @Grupa, @Type, @Manufacturer, @Equipment)";

            using (connectionsql = new SqlConnection(connectionString))
            using (SqlCommand command = new SqlCommand(query, connectionsql))
            {
                connectionsql.Open();
                command.CommandType = CommandType.Text;
                command.Parameters.Add("@InternalNumber", textBox1.Text);
                command.Parameters.Add("@Grupa", textBox2.Text);
                command.Parameters.Add("@Type", textBox3.Text);
                command.Parameters.Add("@Manufacturer", textBox4.Text);
                command.Parameters.Add("@Equipment", textBox5.Text);

                command.ExecuteNonQuery();

                populategrid();
            }
        }
    }
}
相关问题