寻找矩阵中最大的全相同数字正方形子矩阵技术咨询
嘿,咱们一起把这个问题搞定!你现在的动态规划逻辑有个关键问题,没法正确识别由相同数字组成的最大正方形子矩阵。咱们一步步拆解修正:
问题分析
你的原代码的状态转移逻辑存在偏差——它错误地通过比较dp值的大小来决定当前dp[i,j],但实际上,要形成以(i,j)为右下角的相同数字正方形,需要依赖左上、上方、左方三个位置dp值的最小值再加1。只有这三个方向的正方形都能扩展到当前位置,才能确保形成更大的、全相同数字的正方形。
另外,原代码没有跟踪最大正方形的位置和边长,就算dp数组计算正确,也没法直接定位到你想要的3x3子矩阵。
修正后的C#代码
using System; class Program { static void Main() { int[,] a = { {7, 4, 7, 7, 7, 7}, {7, 4, 7, 7, 7, 7}, {7, 7, 1, 7, 7, 7}, {7, 7, 3, 7, 9, 7}, {1, 1, 7, 7, 1, 7}, {7, 7, 7, 5, 7, 7} }; int rows = a.GetLength(0); int cols = a.GetLength(1); int[,] dp = new int[rows, cols]; int maxSide = 1; int maxRow = 0, maxCol = 0; // 记录最大正方形的右下角位置 // 初始化第一行和第一列:单个元素本身就是1x1的正方形 for (int i = 0; i < rows; i++) { dp[i, 0] = 1; } for (int j = 0; j < cols; j++) { dp[0, j] = 1; } // 填充dp数组并跟踪最大正方形 for (int i = 1; i < rows; i++) { for (int j = 1; j < cols; j++) { // 只有当前元素与左上、上、左的元素完全相同时,才可能扩展正方形 if (a[i, j] == a[i-1, j] && a[i, j] == a[i, j-1] && a[i, j] == a[i-1, j-1]) { // 取三个方向dp值的最小值加1,确保扩展后的正方形全为相同数字 dp[i, j] = Math.Min(Math.Min(dp[i-1, j], dp[i, j-1]), dp[i-1, j-1]) + 1; // 更新最大正方形的信息 if (dp[i, j] > maxSide) { maxSide = dp[i, j]; maxRow = i; maxCol = j; } } else { dp[i, j] = 1; // 无法扩展时,单个元素是最小的正方形 } } } // 输出结果 Console.WriteLine($"最大相同数字正方形的边长为: {maxSide}"); Console.WriteLine($"它的左上角位置为: ({maxRow - maxSide + 1}, {maxCol - maxSide + 1})"); Console.WriteLine("对应的子矩阵是:"); for (int i = maxRow - maxSide + 1; i <= maxRow; i++) { for (int j = maxCol - maxSide + 1; j <= maxCol; j++) { Console.Write($"{a[i, j]} "); } Console.WriteLine(); } } }
代码关键说明
- DP数组定义:
dp[i,j]表示以矩阵第i行第j列元素为右下角的、由相同数字组成的最大正方形的边长。 - 初始化逻辑:第一行和第一列的元素本身就是1x1的正方形,所以dp值统一设为1。
- 状态转移核心:当当前元素与左上、上方、左方元素完全相同时,取三个位置dp值的最小值加1——这保证了扩展后的正方形所有元素都是相同数字,因为这三个dp值对应的正方形本身就由该数字组成。
- 最大正方形跟踪:在填充dp数组时实时更新最大边长和右下角位置,最后通过右下角位置和边长反推出左上角位置,直接输出目标子矩阵。
运行结果
运行这段代码后,会精准输出你期望的右上角3x3的7组成的子矩阵:
最大相同数字正方形的边长为: 3 它的左上角位置为: (0, 3) 对应的子矩阵是: 7 7 7 7 7 7 7 7 7
内容的提问来源于stack exchange,提问作者E.Snieckus
相关产品推荐
相关产品推荐

