递归如何打印列表的总和

时间:2015-06-25 00:15:00

标签: c# .net algorithm recursion

我试图在递归算法中找到列表的总和

我正在学习递归算法,我知道我可以用另一种方式做到但我正在学习

这是我的代码(非常简单)

class SumList
{

    public SumList(int[] list ) {
        List<int> listInteger = new List<int>();
        for (int i = 0; i < list.Length; i++)
            listInteger.Add(list[i]);
        sum(listInteger);
    }


    private double sum(List<int> list) {
        if (list.Count == 1)
        {
            return list[0];
        }
        if(list.Count ==2)
        {
            Console.Write(printList(list));
            Console.WriteLine((list[0] + list[1]));
            return list[0] + list[1];
        }
        double last = list[list.Count - 1];
        List<int> backupList = new List<int>(list);
        list.RemoveAt(list.Count -1);
        double s = last + sum(list);
        Console.Write(printList(backupList));
        Console.WriteLine(s);
        return s;
    }
    private string printList(List<int> list)
    {
        string result = "";
        for (int i = 0; i < list.Count; i++)
        {
            result += list[i];
            if (i != list.Count - 1)
            {
                result +="+ ";
            }
            else
            {
                result+= " = ";
            }
        }
        return result;
    }
}

这就是这样称呼的:

int []listInt = new int[] { 4, 5, 6, 7, 9 , 10 };
            new SumList(listInt);
            Console.ReadLine();

我的问题是结果是:

enter image description here

我想得到结果但是像这样:

4 + 5 + 6 + 7 = ...
4 + 5 + 6 = ...

所以结果应该向后打印

我再次知道有很多方法可以找到列表的总和,但我正在尝试学习递归算法

6 个答案:

答案 0 :(得分:2)

您可能知道,递归函数是一个调用自身的函数。这意味着为了递归地解决问题,我们必须将问题分成步骤,使得程序不会在步骤之间改变,但是函数的输入将改变。此外,如果我们的递归函数永远正确终止,问题必须得到更小的&#34;我们采取的每一步。此步骤表示一个递归单位。此外,与&#34; normal&#34;不同。迭代,我们提前知道什么时候才能到达问题的最后。因此,我们需要一种机制来确定何时到达问题的最后并且应该停止递归。这称为基本情况

让我们尝试找一个列表总和的例子。

我们必须做的第一件事是提出一个递归单位(一个抽象的步骤,我们可以一遍又一遍地重复,直到我们找到解决方案)。

我们知道输入类型为List<int>

在这种情况下,我们可以注意到(此处为伪代码)sum(list) == list[0] + sum(restOfList)。请注意,现在我们有一个确定的值(list[0])和一个List<int>类型的对象(即restOfList)。

所以,现在我们有一个整洁,可重复的程序。

//Idk what language you are using, or if it matters, but I am writing this in java
public int sum(List<Integer> list) {
  //still need a base case
  return  list.get(0) + sum(list.subList(1, list.size()));
} 

现在我们只需确定基本情况。所以我们需要确定何时我们将完成列表的所有元素。

为此,让我们通过几个步骤来看看会发生什么。让我们从以下列表开始:{1, 2, 3, 4}

sum({1, 2, 3, 4}) 
-> 1 + sum({2, 3, 4})
       -> 2 + sum({3, 4})
              -> 3 + sum({4})
                     -> 4 + oops!!!

显然,我们无法从大小为1的列表中获取从索引1开始的子列表。这为我们的基本情况提供了答案。

public int sum(List<Integer> list) {
  printList(list);
  //base case
  if (list.size() == 1)
    return list.get(0); //recall that this is the entire list
  //otherwise, continue to next step.
  return  list.get(0) + sum(list.subList(1, list.size()));
}

添加有效,因为第一步的return语句取决于第二步的return语句,依此类推。这也是步骤以相反顺序打印的原因。

为了清楚起见,让我们最后一次追踪它。

sum({1, 2, 3, 4}) //sum({1, 2, 3, 4}) is called from main()
-> 1 + sum({2, 3, 4}) //sum({2, 3, 4}) is called from sum({1, 2, 3, 4})
       -> 2 + sum({3, 4}) //sum({3, 4}) is called from sum({2, 3, 4})
              -> 3 + sum({4}) //sum({4}) is called from sum({3, 4})
                     <- 4 //sum({4}) returns 4 to sum({3, 4})
                 3 + 4
              <- 7 //sum({3, 4}) returns 7 to sum({2, 3, 4})
          2 + 7
       <- 9 //sum({2, 3, 4}) returns 9 to sum({1, 2, 3, 4}) 
   1 + 9
<- 10 //sum({1, 2, 3, 4}) returns 10

我希望这有助于使事情变得更加清晰。

答案 1 :(得分:2)

或试试这个

 public static int Sum(List<int> listOfInt)
    {
        if (listOfInt.Count == 1)
        {
            return Convert.ToInt32(listOfInt[0]);

        }
        else
        {
            return Convert.ToInt32(listOfInt[0]) + Sum(listOfInt.Skip(1).ToList());


        }
    }

答案 2 :(得分:1)

嗯,这不是我怎么做的,它肯定有很多奇怪之处。但是,如果我试图保留你的设计背后的精神,那么我认为实现这一目标的一个好方法是在StringBuilder中缓冲输出,并使用其Insert(0, str)方法将线放在右边的地方。

  public SumList(int[] list)
  {
     List<int> listInteger = new List<int>();
     for (int i = 0; i < list.Length; i++)
        listInteger.Add(list[i]);

     StringBuilder output = new StringBuilder();
     sum(listInteger, output);
     Console.WriteLine(output.ToString());
  }

  private double sum(List<int> list, StringBuilder output)
  {
     if (list.Count == 1)
     {
        return list[0];
     }
     if (list.Count == 2)
     {
        output.Append(printList(list));
        output.Append((list[0] + list[1])).Append(Environment.NewLine);
        return list[0] + list[1];
     }

     double last = list[list.Count - 1];
     List<int> backupList = new List<int>(list);
     list.RemoveAt(list.Count - 1);
     double s = last + sum(list, output);
     output.Insert(0, Environment.NewLine);
     output.Insert(0, s);
     output.Insert(0, printList(backupList));
     return s;
  }

  private string printList(List<int> list)
  {
     string result = "";
     for (int i = 0; i < list.Count; i++)
     {
        result += list[i];
        if (i != list.Count - 1)
        {
           result += " + ";
        }
        else
        {
           result += " = ";
        }
     }
     return result;
  }

答案 3 :(得分:0)

您的代码通过计算所有列表的总和(并逐渐减少列表)然后向后打印它们来工作,这解释了为什么您看到的列表的大小正在增加。修复此问题的方法是修复递归。为了让它们按递减顺序打印,您希望递归按顺序递增。那么,计算sum(List.subList(1)),然后求和(List.subList(2)),依此类推......

另一种快速解决方法是将输出保存为数组中的字符串,然后向后打印数组。

答案 4 :(得分:0)

一种可能的解决方案是

List<int> listInteger = new List<int> ();

public SumList (int[] list)
{
    for (int i = 0; i < list.Length; i++)
        listInteger.Add (list [i]);
    listInteger.Reverse();
}

private void sumR (List<int> list, int index)
{
    int sigma = 0;
    if (list.Count - 1 == index) {
        return;// sigma + list [index];
    } else {
        for (int i = list.Count-1; i>=index; i--) {
            sigma += list [i];
            if (i == list.Count - 1)
                Console.Write ("{0} ", list [i]);
            else
                Console.Write ("+ {0} ", list [i]);
        }
        Console.WriteLine ("= {0}", sigma);
        sumR (list, index + 1);
    }
}
public void doSum(){
    sumR(listInteger, 0);
}

不需要其他方法,但如果您愿意,可以从构造函数中调用sumR。测试是

int [] listInt = new int[] { 4, 5, 6, 7, 9 , 10 };
SumList sl = new SumList (listInt);
sl.doSum();
Console.ReadLine ();

输出是:

4 + 5 + 6 + 7 + 9 + 10 = 41
4 + 5 + 6 + 7 + 9 = 31
4 + 5 + 6 + 7 = 22
4 + 5 + 6 = 15
4 + 5 = 9

答案 5 :(得分:0)

递归函数:

public static void PrintSum(int[] list)
{
    // Define the end of the recursion 
    if (list.Count() > 2)
        // Copy the shorter list to PrintSum()
        PrintSum(list.Take(list.Count() - 1).ToArray());

    // Print the result of list AFTER shorter list is done
    System.Diagnostics.Debug.WriteLine(
        string.Format("{0} = {1}", string.Join("+ ", list), 
        list.Sum()));
}

public static void PrintSumReverse(int[] list)
{
    // Print the result of list
    System.Diagnostics.Debug.WriteLine(
        string.Format("{0} = {1}", string.Join("+ ", list),
        list.Sum()));

    // Define the end of the recursion
    if (list.Count() > 2)
        // Copy the shorter list to PrintSum()
        PrintSum(list.Take(list.Count() - 1).ToArray());
}

用法:

var listInt = new int[] { 4, 5, 6, 7, 9, 10 };

PrintSum(listInt);

/* Result:

    4+ 5 = 9
    4+ 5+ 6 = 15
    4+ 5+ 6+ 7 = 22
    4+ 5+ 6+ 7+ 9 = 31
    4+ 5+ 6+ 7+ 9+ 10 = 41
*/


PrintSumReverse(listInt);

/* Result
    4+ 5+ 6+ 7+ 9+ 10 = 41
    4+ 5+ 6+ 7+ 9 = 31
    4+ 5+ 6+ 7 = 22
    4+ 5+ 6 = 15
    4+ 5 = 9
*/