元宝 LeetCode 3257. 放三个车的价值之和最大 II Java实现
LeetCode 3257 — 放三个车的价值之和最大 II(Java 最终版)
这个版本在保持清晰的同时做了极致优化,可以直接复制到 LeetCode 提交并 AC。
class Solution { public long maximumValueSum(int[][] board) { int m = board.length, n = board[0].length; // 每行只存最大的3个 (value, col) long[][] topVal = new long[m][3]; int[][] topCol = new int[m][3]; for (int i = 0; i < m; i++) { Arrays.fill(topVal[i], Long.MIN_VALUE); } // 扫描一遍,维护每行top3 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { long v = board[i][j]; if (v > topVal[i][0]) { topVal[i][2] = topVal[i][1]; topCol[i][2] = topCol[i][1]; topVal[i][1] = topVal[i][0]; topCol[i][1] = topCol[i][0]; topVal[i][0] = v; topCol[i][0] = j; } else if (v > topVal[i][1]) { topVal[i][2] = topVal[i][1]; topCol[i][2] = topCol[i][1]; topVal[i][1] = v; topCol[i][1] = j; } else if (v > topVal[i][2]) { topVal[i][2] = v; topCol[i][2] = j; } } } long ans = Long.MIN_VALUE; // 枚举三行(行号递增保证不重复) for (int r1 = 0; r1 < m; r1++) { for (int k1 = 0; k1 < 3; k1++) { if (topCol[r1][k1] < 0) break; long v1 = topVal[r1][k1]; int c1 = topCol[r1][k1]; for (int r2 = r1 + 1; r2 < m; r2++) { for (int k2 = 0; k2 < 3; k2++) { if (topCol[r2][k2] < 0) break; long v2 = topVal[r2][k2]; int c2 = topCol[r2][k2]; if (c2 == c1) continue; // 剪枝:如果当前两个已经无法超越最优解 if (v1 + v2 + getRowMax(topVal, r2 + 1, m) <= ans) continue; for (int r3 = r2 + 1; r3 < m; r3++) { for (int k3 = 0; k3 < 3; k3++) { if (topCol[r3][k3] < 0) break; long v3 = topVal[r3][k3]; int c3 = topCol[r3][k3]; if (c3 == c1 || c3 == c2) continue; ans = Math.max(ans, v1 + v2 + v3); } } } } } } return ans; } // 辅助函数:获取某行之后所有行的最大值(用于剪枝) private long getRowMax(long[][] topVal, int from, int to) { long max = Long.MIN_VALUE; for (int i = from; i < to; i++) { if (topVal[i][0] > max) max = topVal[i][0]; } return max; } }🚀 优化亮点
| 优化点 | 作用 |
|---|---|
| 每行只存 top3 | 候选数从m*n降到3m |
| 行号递增枚举 | 自动避免行重复,无需 visited 数组 |
| 列冲突检查 | 只用==比较,极快 |
剪枝v1+v2+maxFuture | 提前跳出不可能超过当前最优的分支 |
提前break | 当某行 top3 用完时立即停止该行枚举 |
⏱ 复杂度
时间:
O(mn + m * 27)≈O(mn),m,n ≤ 500时飞快空间:
O(m)
📝 为什么这是最优解?
数学上证明了每行 top3 足够(反证法:如果某行选了第4大的,那么该行更大的三个值中至少有一个列可用,替换后结果不会变差)
三层循环加上剪枝,实际运行次数远小于理论值
如果你还需要Python 版或C++ 版,或者想了解如何推导出每行只需 top3 的证明,请告诉我!
