zoukankan      html  css  js  c++  java
  • [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), y - min(x, y)).

    2. when the slope is -1, if x > y, 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, 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 }
  • 相关阅读:
    OpenStack功能简介
    Openstack(七)keystone
    Openstack(六)RabbitMQ集群
    Openstack(五)Memcache- repcached集群
    Openstack(四)Mysql主从
    Openstack(三)Haproxy+Keepalived双机
    Openstack(二)基本环境准备--网络、时间、yum源等
    Openstack架构简介(一)
    运维监控系统之Open-Falcon
    python高级之Flask框架
  • 原文地址:https://www.cnblogs.com/lz87/p/10351395.html
Copyright © 2011-2022 走看看