问题
在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。
给定一个由整数坐标组成的数组 queens ,表示黑皇后的位置;以及一对坐标 king ,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(任意顺序)。
后(英文:Queen,Unicode字符♕U+2655,♛U+2656)是国际象棋棋局中实力最强的一种棋子。 后可横直斜走,且格数不限。 吃子与走法相同。 因为后的实力最强,故而在兵升变时,虽然可以选择变为其他棋子,但绝大多数会选择升变为后。
思路
- 逆向思维,考虑国王周围的八个方向是否有后。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.util.ArrayList; import java.util.Arrays; import java.util.List;
class Solution { public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) { int[][] directions = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 1 }, { -1, -1 }, { -1, 1 }, { 1, -1 } }; List<List<Integer>> res = new ArrayList<List<Integer>>(); dirs: for (int i = 0; i < directions.length; i++) { int[] tmp = new int[2]; tmp[0] = king[0]; tmp[1] = king[1]; int[] dir = directions[i]; while (!isCross(tmp)) { tmp[0] += dir[0]; tmp[1] += dir[1]; for (int j = 0; j < queens.length; j++) { if (Arrays.equals(tmp, queens[j])) { List<Integer> posList = new ArrayList<Integer>(); posList.add(queens[j][0]); posList.add(queens[j][1]); res.add(posList); continue dirs; } } } } return res; }
boolean isCross(int[] pos) { return !(pos[0] > -1 && pos[0] < 8 && pos[1] > -1 && pos[1] < 8); } }
|
其他注意
- 低级错误:int[]类型是引用传递,没注意到导致bug.
另一个想法
- 直接将所有坐标的差值计算出来,计算是否满足对角线或直线的规则。
- 这么做的话,需要考虑是否有遮挡,也就是一个方向只能用一次(平方和小的)。
- 最后将坐标差值加上国王坐标,还原王后坐标。