
本文介绍如何修改固定长度的 position 数组返回逻辑,使其仅包含有效的骑士移动位置,避免 null 占位,通过两次遍历和 arrays.copyofrange 实现纯数组方案。
本文介绍如何修改固定长度的 position 数组返回逻辑,使其仅包含有效的骑士移动位置,避免 null 占位,通过两次遍历和 arrays.copyofrange 实现纯数组方案。
在实现国际象棋中骑士(Knight)的合法移动方法时,一个常见误区是预先分配固定大小(如 8)的 Position[] 数组,并对所有 8 种可能偏移统一赋值——这会导致无效坐标位置被设为 null,最终返回形如 {(2,3),(3,2),null,null,null,null,null,null} 的“稀疏数组”,既浪费空间又增加调用方处理负担。
若明确不能使用 ArrayList
- 首次遍历:统计当前棋盘位置下实际合法的移动数量;
- 二次遍历:仅向紧凑新数组中填充有效 Position 对象。
以下是优化后的完整实现:
public Position[] moves(Position p) {
int row = p.getRow();
int col = p.getCol();
// 骑士 8 个方向的 (行偏移, 列偏移)
int[][] offsets = {{-1,-2},{1,-2},{-1,2},{1,2},{-2,-1},{-2,1},{2,-1},{2,1}};
// 第一阶段:统计合法移动数
int validCount = 0;
for (int[] offset : offsets) {
int newRow = row + offset[0];
int newCol = col + offset[1];
if (newRow >= 1 && newRow = 1 && newCol = 1 && newRow = 1 && newCol <p>✅ <strong>优势说明</strong>: </p>
- 返回数组长度严格等于合法移动数(如 (1,1) 时返回长度为 2 的数组),无 null 元素;
- 时间复杂度仍为 O(1)(因骑士最多只有 8 种移动,为常量);
- 空间利用率高,避免冗余对象引用;
- 完全符合题目约束:不依赖 ArrayList、LinkedList 等集合类。
⚠️ 注意事项:
- 假设 Position 类的行列索引从 1 开始(符合题目中 1..8 的边界判断),请确保其 getRow()/getCol() 行为一致;
- 若需支持零基坐标(如 0..7),只需将边界条件改为 >= 0 &&
- 此方案虽略增一次循环,但逻辑清晰、可读性强,且比 Arrays.copyOfRange 手动截断更直观(后者需先填满原数组再复制,仍隐含临时 null 占位)。
总结:在禁止使用动态集合的前提下,“先计数、后填充” 是处理此类固定上限但实际数量可变的数组返回问题的标准范式,兼顾简洁性、健壮性与教学示范价值。










