使用递归来查找2d数组的第一行和最后一行中所有值的总和

时间:2018-05-30 02:53:00

标签: c# recursion sum

我在c#中练习递归,我有一个有效的解决方案,但它使用了3个函数(其中2个非常相似)。我正在寻找有关如何改善这一点的提示,或者我是否正确地采用了正确的方法。我避免使用循环并且只想使用递归来解决这个问题。

using System;

namespace RecursionPractice
{
    class Program
    {
        static int sumFirstLastRows(int[,] twoDArr)
        {
            int rowLength = twoDArr.GetLength(1); 

            int sumRow1 = sumFirstRow(twoDArr, rowLength);
            int sumRow2 = sumLastRow(twoDArr, rowLength);

            int sumTotal = sumRow1 + sumRow2;
            return sumTotal;
        }

        static int sumFirstRow(int[,] twoDArr, int N)
        {
            if (N <= 0)
            {
                //base case
                return 0;
            }

            return sumFirstRow(twoDArr, N - 1) + twoDArr[0, N - 1];
        }

        static int sumLastRow(int[,] twoDArr, int N)
        {
            if (N <= 0)
            {
                //base case
                return 0;
            }

            return sumLastRow(twoDArr, N - 1) + twoDArr[1, N - 1];
        }


        static void Main(string[] args)
        {
            int[,] twoD = new int[,] {{ 1, 3, 5 },
                                     {  2, 4, 6  }};

            Console.WriteLine(sumFirstLastRows(twoD));

            Console.ReadLine();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

[注意:仅用于递归学习]

如评论中所述,您的代码将仅计算第一行和第二行,如果twoDArr.GetLength(0) > 2则省略最后一行。要将此force转换为1方法递归调用,我将其分为某个状态(enum Pointer)并相应地计算/跳过。

我相信我和你一样好奇,所以我这样做,请尝试一下:

//my enum
public enum Pointer
    {
        Begin,
        First,
        Last,
        Skipped,
        Final
    }
//method
public static int sumFirstLast(int[,] arr, Pointer p = Pointer.Begin, int d1Length = 0, int d2Length = 0, int N = 0)
    {
        var tot = 0;
        switch (p)
        {
            case Pointer.Final:
                return 0;
            case Pointer.Begin:
                return sumFirstLast(arr, Pointer.First, arr.GetLength(0), arr.GetLength(1));
            case Pointer.First:
                if (d2Length == N)
                {
                    if (arr.GetLength(0) == 2)
                        return sumFirstLast(arr, Pointer.Last, d1Length, d2Length, 0);
                    return sumFirstLast(arr, Pointer.Skipped, d1Length, d2Length, 0);
                }
                tot = arr[0, N++];
                return sumFirstLast(arr, Pointer.First, d1Length, d2Length, N) + tot;
            case Pointer.Skipped:
                return sumFirstLast(arr, Pointer.Last, d1Length, d2Length, 0);
            case Pointer.Last:
                if (d2Length == N)
                {
                    return sumFirstLast(arr, Pointer.Final, d1Length, d2Length, 0);
                }
                tot += arr[d1Length-1, N++];
                return sumFirstLast(arr, Pointer.Last, d1Length, d2Length, N) + tot;
            default:
                return 0;
        }
//and..call it
static void Main(string[] args)
    {
        int[,] twoD = new int[,] {{ 1, 3, 5 }, {0, 0, 0},
                             {  2, 4, 6  }}; //new array added

        Console.WriteLine(sumFirstLast(twoD));

        Console.ReadLine();
    }

答案 1 :(得分:1)

我知道您正在尝试使用递归,但使用LINQ这个练习要简单得多。

如果你从这开始:

int[,] twoDArr = new int[,]
{
    { 1, 2, 3 },
    { 2, 3, 4 },
    { 3, 4, 5 },
};

通过这样做很容易将其转换为int[][]

int[][] rows =
    twoDArr
        .Cast<int>() // flattens to one dimension
        .Select((value, index) => new { value, index })
        .GroupBy(x => x.index / twoDArr.GetLength(1), x => x.value)
        .Select(x => x.ToArray())
        .ToArray();

.GroupBy键为x.index / twoDArr.GetLongLength(1),因此每行的整数从零开始。

这给出了:

rows

现在你可以这样做:

int result = rows.First().Sum() + rows.Last().Sum();

我从样本数据中得到的结果是18(这是第一行和最后一行的正确总和)。

答案 2 :(得分:0)

抱歉,这与您的代码无关。这只是我为第一行和最后一行做递归求和的版本。我希望它有所帮助。

int SumFirstLastRows(int[,] twoD)
{
    // we need some pointer information on when to start and end,
    // let's use column and row number, starting from 0,0
    return SumRecursive(twoD, 0, 0);
}

// this is a recursive method, which goes for each row and column recursively,
// however it only takes the sum of first and last rows' numbers
int SumRecursive(int[,] twoD, int column, int row)
{
    // determine the max row and column, to know when to end
    int maxRows = twoD.GetLength(0);
    int maxColumns= twoD.GetLength(1);

    if (row == maxRows)
    {
        // we are at the end of the rows, end everything
        return 0;
    }
    else if (column == maxColumns)
    {
        // we are at the end of column, switch to the next row instead
        return SumRecursive(twoD, 0, row + 1);
    }
    if ((row== 0 || row == maxRows-1) && column < maxColumns)
    {
        // only for the first or last row: current number + next column sum
        return twoD[row, column] + SumRecursive(twoD, column + 1, row);
    }
    else if(column < maxColumns)
    {
        // not the first or last row, so just skip to the next column
        return SumRecursive(twoD, column + 1, row);
    }
    return 0;
}

进行测试:

int[,] twod = new int[3,4]
        { {1,2,3,4 },
          {5,6,7,8 },
          {9,10,11,12 }
        };
int recursiveTest = SumFirstLastRows(twod);
int forVerification = 1 + 2 + 3 + 4 + 9 + 10 + 11 + 12;
bool isThisCorrect = recursiveTest == forVerification; // return true!