微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

[Daily Coding Problem 68] Count Pairs of attacking bishop pairs

This problem was asked by Google.

On our special chessboard,two bishops attack each other if they share the same diagonal. This includes bishops that have another bishop located between them,i.e. bishops can attack through pieces.

You are given N bishops,represented as (row,column) tuples on a M by M chessboard. Write a function to count the number of pairs of bishops that attack each other. The ordering of the pair doesn‘t matter: (1,2) is considered the same as (2,1).

For example,given M = 5 and the list of bishops:

  • (0,0)
  • (1,2)
  • (2,2)
  • (4,0)

The board would look like this:

[b 0 0 0 0]
[0 0 b 0 0]
[0 0 b 0 0]
[0 0 0 0 0]
[b 0 0 0 0]

You should return 2,since bishops 1 and 3 attack each other,as well as bishops 3 and 4.

 

The naive solution is to check each pair of all possible pairs. Its runtime is O(N^2). Can we make this any faster?

The bottle neck of the naive solution is that on a particular diagonal,if there are m bishops,then it takes m * (m - 1) / 2,which is O(m^2) time. It does not use the information that all of these bishops are in fact on the same diagonal already. A better solution is to go through each bishop and bucket them into each separate diagonal. For each diagonal with m bishops on it,there are m * (m - 1) / 2 attacking pairs. This reduces the runtime of getting all attacking pairs from one diagonal to O(m). 

Now we just need to find a good way of bucketing all bishops. We need a slope and a point to definitively specify a line in a 2D-coordinates. In this case,there can be only 2 slopes,+1 or -1.  And we can use the boundary coordinates of the chessboard to bucket each bishops.

For bishop (x,y),

1. when the slope is 1,if x > y,the boundary point is (x - y,y - y); else the boundary point is (x - x,y - x); so boundary point is (x - min(x,y - min(x,y)).

2. when the slope is -1,the boundary point is (x - x,y + x); else the boundary point is (x - (M - y),y + (M -y)); so the boundary point is (x - min(x,M - y),y + min(x,M - y)).

We can use two maps of map save the diagonals buckets. We must use 2 separate maps,1 for each slope because for each boundary point,there are 2 possilbe diagonals,one with slope 1,one with slope -1.

 

 1 public class AttackingBishop {
 2     class Point {
 3         int x,y;
 4     }
 5     public int countAttackingBishopPairs(Point[] points,int M) {
 6         Map<Integer,Map<Integer,Integer>> posMap = new HashMap<>();
 7         Map<Integer,Integer>> negMap = new HashMap<>();
 8         for(Point point : points) {
 9             int posBoundaryX = point.x - Math.min(point.x,point.y);
10             int posBoundaryY = point.y - Math.min(point.x,point.y);
11             int negBoundaryX = point.x - Math.min(point.x,M - point.y);
12             int negBoundaryY = point.y + Math.min(point.x,M - point.y);
13 
14             if(!posMap.containsKey(posBoundaryX)) {
15                 posMap.put(posBoundaryX,new HashMap<>());
16             }
17             if(!posMap.get(posBoundaryX).containsKey(posBoundaryY)) {
18                 posMap.get(posBoundaryX).put(posBoundaryY,0);
19             }
20             Map<Integer,Integer> map = posMap.get(posBoundaryX);
21             map.put(posBoundaryY,map.get(posBoundaryY) + 1);
22 
23             if(!negMap.containsKey(negBoundaryX)) {
24                 negMap.put(negBoundaryX,new HashMap<>());
25             }
26             if(!negMap.get(negBoundaryX).containsKey(negBoundaryY)) {
27                 negMap.get(negBoundaryX).put(negBoundaryY,0);
28             }
29             map = negMap.get(negBoundaryX);
30             map.put(negBoundaryY,map.get(negBoundaryY) + 1);
31         }
32         int count = 0;
33         for(Map<Integer,Integer> map : posMap.values()) {
34             for(int c : map.values()) {
35                 count += c * (c - 1) / 2;
36             }
37         }
38         for(Map<Integer,Integer> map : negMap.values()) {
39             for(int c : map.values()) {
40                 count += c * (c - 1) / 2;
41             }
42         }
43         return count;
44     }
45 }

 

A more concise implementation is to customize your own key and only use a hash map.

 1 public class AttackingBishop {
 2     class Point {
 3         int x,y;
 4 
 5         Point(int x,int y) {
 6             this.x = x;
 7             this.y = y;
 8         }
 9 
10         @Override
11         public int hashCode() {
12             return 31 * x + 37 * y;
13         }
14 
15         @Override
16         public boolean equals(Object obj) {
17             if (this == obj) {
18                 return true;
19             }
20             if (obj == null || getClass() != obj.getClass()) {
21                 return false;
22             }
23             Point p = (Point) obj;
24             if (x != p.x || y != p.y) {
25                 return false;
26             }
27             return true;
28         }
29     }
30 
31     public int countAttackingBishopPairs(Point[] points,int M) {
32         Map<Point,Integer> posMap = new HashMap<>();
33         Map<Point,Integer> negMap = new HashMap<>();
34         for (Point point : points) {
35             Point p1 = new Point(point.x - Math.min(point.x,point.y),point.y - Math.min(point.x,point.y));
36             Point p2 = new Point(point.x - Math.min(point.x,M - point.y),point.y + Math.min(point.x,M - point.y));
37             if (!posMap.containsKey(p1)) {
38                 posMap.put(p1,1);
39             } else {
40                 posMap.put(p1,posMap.get(p1) + 1);
41             }
42             if (!negMap.containsKey(p2)) {
43                 negMap.put(p2,1);
44             } else {
45                 negMap.put(p2,negMap.get(p2) + 1);
46             }
47         }
48         int count = 0;
49         for (int c : posMap.values()) {
50             count += c * (c - 1) / 2;
51         }
52         for (int c : negMap.values()) {
53             count += c * (c - 1) / 2;
54         }
55         return count;
56     }
57 }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐