C#矩阵环形区域元素搜索算法实现求助
解决方案:C#矩阵环形区域元素提取
核心思路
要提取目标坐标周围的环形元素,本质是获取以目标为中心、半径为指定值的正方形环边缘。我们可以通过两种高效方式实现,同时全程做越界检查保证鲁棒性:
方法1:定向遍历四条边(高效)
环形由四条边组成:上边、下边、左边、右边。直接遍历这四条边的坐标,跳过矩阵外的无效点,收集有效元素:
- 计算环形的上下左右边界(基于目标坐标和半径)
- 分别遍历四条边,对每个坐标做矩阵范围校验,有效则加入结果列表
- 左右边需排除与上下边重复的端点,避免元素重复
方法2:范围遍历+条件判断(简洁)
先限定遍历范围在矩阵有效区域内,再判断每个点是否属于环形(通过切比雪夫距离:max(|行差|, |列差|) == radius),满足条件则收集元素。逻辑更直观,适合中小矩阵场景。
代码实现
方法1:定向遍历四条边
using System.Collections.Generic; public static class MatrixHelper { public static List<T> GetRingElements<T>(T[,] matrix, (int Row, int Col) target, int radius) { var ringElements = new List<T>(); int totalRows = matrix.GetLength(0); int totalCols = matrix.GetLength(1); // 计算环形的四个边界 int topEdge = target.Row - radius; int bottomEdge = target.Row + radius; int leftEdge = target.Col - radius; int rightEdge = target.Col + radius; // 遍历上边 for (int col = leftEdge; col <= rightEdge; col++) { if (topEdge >= 0 && topEdge < totalRows && col >= 0 && col < totalCols) { ringElements.Add(matrix[topEdge, col]); } } // 遍历下边 for (int col = leftEdge; col <= rightEdge; col++) { if (bottomEdge >= 0 && bottomEdge < totalRows && col >= 0 && col < totalCols) { ringElements.Add(matrix[bottomEdge, col]); } } // 遍历左边(跳过上下边已包含的端点) for (int row = topEdge + 1; row <= bottomEdge - 1; row++) { if (row >= 0 && row < totalRows && leftEdge >= 0 && leftEdge < totalCols) { ringElements.Add(matrix[row, leftEdge]); } } // 遍历右边(跳过上下边已包含的端点) for (int row = topEdge + 1; row <= bottomEdge - 1; row++) { if (row >= 0 && row < totalRows && rightEdge >= 0 && rightEdge < totalCols) { ringElements.Add(matrix[row, rightEdge]); } } return ringElements; } }
方法2:范围遍历+条件判断
using System.Collections.Generic; using System; public static class MatrixHelper { public static List<T> GetRingElementsAlt<T>(T[,] matrix, (int Row, int Col) target, int radius) { var ringElements = new List<T>(); int totalRows = matrix.GetLength(0); int totalCols = matrix.GetLength(1); // 限定遍历范围在矩阵有效边界内,避免无效遍历 int startRow = Math.Max(0, target.Row - radius); int endRow = Math.Min(totalRows - 1, target.Row + radius); int startCol = Math.Max(0, target.Col - radius); int endCol = Math.Min(totalCols - 1, target.Col + radius); for (int row = startRow; row <= endRow; row++) { for (int col = startCol; col <= endCol; col++) { // 判断当前点是否在环形上(切比雪夫距离等于半径) if (Math.Max(Math.Abs(row - target.Row), Math.Abs(col - target.Col)) == radius) { ringElements.Add(matrix[row, col]); } } } return ringElements; } }
测试示例
以9x9矩阵、目标坐标(4,5)、半径3为例:
// 初始化矩阵,赋值为行号*10+列号 int[,] testMatrix = new int[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { testMatrix[i, j] = i * 10 + j; } } // 提取环形元素 var target = (Row: 4, Col: 5); var result = MatrixHelper.GetRingElements(testMatrix, target, 3); // 输出结果将包含:12,13,14,15,16,17,18,72,73,74,75,76,77,78,22,32,42,52,62,28,38,48,58,68
鲁棒性说明
两种方法都做了严格的越界校验:
- 方法1直接对每个坐标判断是否在矩阵的
[0, 总行数-1]和[0, 总列数-1]范围内 - 方法2先通过
Math.Max/Min限定遍历范围,避免访问矩阵外的区域
即使目标坐标靠近矩阵边缘、半径过大导致环形超出矩阵范围,也能安全返回有效元素,不会抛出越界异常。
内容的提问来源于stack exchange,提问作者Coltzy
相关产品推荐
相关产品推荐

