我在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();
}
}
}
答案 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)
,因此每行的整数从零开始。
这给出了:
现在你可以这样做:
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!