由于这里的解决方案似乎是迭代的,我将提供另一个使用递归相对简单的解决方案。
算法
总之,该算法遍历二维数组中的所有 n 个元素,并在找到“C”后,开始将所有相邻的“W”元素转换为“C”的递归过程。如果没有相邻的“W”元素,它会终止递归并继续通过数组进行迭代。它本质上递归地填充数组中应该被污染的每个连接组件。
效率
该算法遍历每个元素,然后有效地实现深度优先搜索,当没有相邻元素可以被污染时终止。 DFS 的终止很重要,可以防止不必要的重复处理元素。该算法还具有内存效率,因为它会修改数组。
解决方案
public static void GenerateContaminant(string[,] arr)
{
// Iterate through every element of the array and when you find a "C",
// propagate the contamination recursively to its neighbors.
for (int row = 0; row < arr.GetLength(0); row++)
{
for (int col = 0; col < arr.GetLength(1); col++)
{
if (arr[row, col] == "C") {
ContaminateRecurse(row, col, arr);
}
}
}
return;
}
// Recurse from a "C" element and see if its neighbors should be contaminated.
public static void ContaminateRecurse(int row, int col, string[,] arr)
{
arr[row, col] = "C";
// Top Neighbor
if (isValid(row-1, col, arr)) {
ContaminateRecurse(row-1, col, arr);
}
// Bottom Neighbor
if (isValid(row+1, col, arr)) {
ContaminateRecurse(row+1, col, arr);
}
// Left Neighbor
if (isValid(row, col-1, arr)) {
ContaminateRecurse(row, col-1, arr);
}
// Right Neighbor
if (isValid(row, col+1, arr)) {
ContaminateRecurse(row, col+1, arr);
}
return;
}
// Makes sure that an element index is within the bounds of the array and is a 'W'.
public static bool isValid(int row, int col, string[,] arr) {
if ((0 <= row && row < arr.GetLength(0)) &&
(0 <= col && col < arr.GetLength(1)) &&
arr[row,col] == "W") {
return true;
}
else {
return false;
}
}
测试代码
这是我从您的 Rextester 链接添加到完整测试器代码的解决方案。我在开始时复制输入数组,因为我的算法修改了传递给它的数组。
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
// Set up input.
string[,] arr = new string[,]
{
{ "W", "W", "W", "R", "W" },
{ "C", "R", "R", "R", "R" },
{ "R", "W", "W", "R", "W" },
{ "W", "W", "W", "R", "R" },
{ "W", "R", "R", "W", "C" }
};
// Actual algorithm for solution.
// Make a copy for result since recursive solution will modify array in place.
string[,] result = arr.Clone() as string[,];
GenerateContaminant(result);
printGrid("Input:", arr);
printGrid("Output:", result);
}
public static void GenerateContaminant(string[,] arr)
{
// Iterate through every element of the array and when you find a "C",
// propagate the contamination recursively to its neighbors.
for (int row = 0; row < arr.GetLength(0); row++)
{
for (int col = 0; col < arr.GetLength(1); col++)
{
if (arr[row, col] == "C") {
ContaminateRecurse(row, col, arr);
}
}
}
return;
}
// Recurse from a "C" element and see if its neighbors should be contaminated.
public static void ContaminateRecurse(int row, int col, string[,] arr)
{
arr[row, col] = "C";
// Top Neighbor
if (isValid(row-1, col, arr)) {
ContaminateRecurse(row-1, col, arr);
}
// Bottom Neighbor
if (isValid(row+1, col, arr)) {
ContaminateRecurse(row+1, col, arr);
}
// Left Neighbor
if (isValid(row, col-1, arr)) {
ContaminateRecurse(row, col-1, arr);
}
// Right Neighbor
if (isValid(row, col+1, arr)) {
ContaminateRecurse(row, col+1, arr);
}
return;
}
// Makes sure that an element index is within the bounds of the array and is a 'W'.
public static bool isValid(int row, int col, string[,] arr) {
if ((0 <= row && row < arr.GetLength(0)) &&
(0 <= col && col < arr.GetLength(1)) &&
arr[row,col] == "W") {
return true;
}
else {
return false;
}
}
// Write grid to console.
public static void printGrid(string label, string[,] result) {
Console.Write(label);
Console.WriteLine();
for (int rowValue = 0; rowValue < result.GetLength(0); rowValue++) {
for (int colValue = 0; colValue < result.GetLength(1); colValue++) {
Console.Write(result[rowValue, colValue]);
}
Console.WriteLine();
}
Console.WriteLine();
}
}
}
结果:
Input:
WWWRW
CRRRR
RWWRW
WWWRR
WRRWC
Output:
CCCRW
CRRRR
RWWRW
WWWRR
WRRCC