问题

在一个 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.
 
另一个想法
- 直接将所有坐标的差值计算出来,计算是否满足对角线或直线的规则。
 - 这么做的话,需要考虑是否有遮挡,也就是一个方向只能用一次(平方和小的)。
 - 最后将坐标差值加上国王坐标,还原王后坐标。