LeetCode 1001 - Grid Illumination


https://leetcode.com/problems/grid-illumination/
On a N x N grid of cells, each cell (x, y) with 0 <= x < N and 0 <= y < N has a lamp.
Initially, some number of lamps are on.  lamps[i] tells us the location of the i-th lamp that is on.  Each lamp that is on illuminates every square on its x-axis, y-axis, and both diagonals (similar to a Queen in chess).
For the i-th query queries[i] = (x, y), the answer to the query is 1 if the cell (x, y) is illuminated, else 0.
After each query (x, y) [in the order given by queries], we turn off any lamps that are at cell (x, y) or are adjacent 8-directionally (ie., share a corner or edge with cell (x, y).)
Return an array of answers.  Each value answer[i] should be equal to the answer of the i-th query queries[i].

Example 1:
Input: N = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,0]]
Output: [1,0]
Explanation: 
Before performing the first query we have both lamps [0,0] and [4,4] on.
The grid representing which cells are lit looks like this, where [0,0] is the top left corner, and [4,4] is the bottom right corner:
1 1 1 1 1
1 1 0 0 1
1 0 1 0 1
1 0 0 1 1
1 1 1 1 1
Then the query at [1, 1] returns 1 because the cell is lit.  After this query, the lamp at [0, 0] turns off, and the grid now looks like this:
1 0 0 0 1
0 1 0 0 1
0 0 1 0 1
0 0 0 1 1
1 1 1 1 1
Before performing the second query we have only the lamp [4,4] on.  Now the query at [1,0] returns 0, because the cell is no longer lit. 
Note:
  1. 1 <= N <= 10^9
  2. 0 <= lamps.length <= 20000
  3. 0 <= queries.length <= 20000
  4. lamps[i].length == queries[i].length == 2

https://blog.csdn.net/likewind1993/article/details/87998850
给定N的范围从1到10^9,如果直接拍脑门构建NxN大的方阵来对所有数据进行存储有点不太现实,再者,构建好NxN方阵之后,其存着的太多的0并没有太多的意义。因此我们需要构造合适的数据结构对题目中提到的关系进行存储。

关系分析
灯以及其照亮的点,这个关系是双向的,因为我们需要
根据照亮的点判断关哪个灯
关灯后熄灭其被照亮的点
查询的位置与被灯照亮的位置,需要被用来进行查找,因此这里的关系是单向
查询的位置周围8个格与灯的位置,因为在进行一次查询之后,如果周围有灯泡,需要将灯泡熄灭,这个关系也是一个单向的关系
最后,由于一个位置可能被多个灯照亮,因此被照亮的位置与灯存在一对多的关系
数据表示及算法流程
数据表示
在对涉及得到的位置信息进行分析之后,我们可以构造相应的数据结构来对以上的数据建立联系。

map<pair<int, int>, int > point_frep, 用map来建立从被照亮的点与灯的关系,**pair<int, int>**是被照亮的位置,后面的int 是该位置上的灯泡数。
map<int, int>x_frep, 表示x行被照亮,第二个int表示被几个灯光照亮
map<int, int>y_frep,表示y列被照亮,第二个int表示被几个灯光照亮
map<int, int>sum_frep, map<int, int> diff_frep分别表示斜着的x + y,x-y行被照亮,第二个int表示被几个灯光照亮。
关于第四个关系可以由以下的图简短说明:

当灯的位置处于(0,2)时可以发现

1. 被照亮的绿色位置的值均满足(x+y = 2)
2. 被照亮的红色位置的值均满足(x- y = -2)
3.
1
2
3
因此,可以很方便的根据给出点的坐标来判断是否被某灯照亮。(其实是分别处于x+y=a, x-y=b直线上)


流程
先对lamps进行遍历,构造提到的灯与被照亮位置的关系
记录每个位置灯的数量
更新其照亮的位置
遍历queries
根据其坐标判断是否被照亮
周围8个格子是否存在灯泡,根据point_frep来判断其值,如果存在灯泡
“熄灭”被照亮的行、列
该位置灯泡数减一
https://leetcode.com/problems/grid-illumination/discuss/243076/Java-Clean-Code-O(N)-Time-and-O(N)-Space-Beats-100

  • The row, column or diagonal will remain illuminated if there are > 0 lamps on that particular row, column or diagonal
  • all the diagonals with slope= 1, can be represented by x= y+c i.e. they have x-y = constant
  • all the diagonals with slope= -1, can be represented by x= -y+c i.e they have x+y = constant
  • store the counts in separate maps
  • When a lamp is turned off, the count of lamps in respective row, column or diagonal decreases by 1
class Solution {
    int[][] dirs = {{0,1}, {0,-1}, {1,0}, {-1,0}, {1,1}, {1,-1}, {-1,1}, {-1,-1}, {0,0}};
    
 public int[] gridIllumination(int N, int[][] lamps, int[][] queries) {
        Map<Integer, Integer> m1 = new HashMap();       // row number to count of lamps
        Map<Integer, Integer> m2 = new HashMap();       // col number to count of lamps
        Map<Integer, Integer> m3 = new HashMap();       // diagonal x-y to count of lamps
        Map<Integer, Integer> m4 = new HashMap();       // diagonal x+y to count of lamps
        Map<Integer, Boolean> m5 = new HashMap();       // whether lamp is  ON|OFF
        
        // increment counters while adding lamps
        for(int i=0; i<lamps.length; i++){
            int x = lamps[i][0];
            int y = lamps[i][1];
            m1.put(x, m1.getOrDefault(x, 0) + 1);
            m2.put(y, m2.getOrDefault(y, 0) + 1);
            m3.put(x-y, m3.getOrDefault(x-y, 0) + 1);
            m4.put(x+y, m4.getOrDefault(x+y, 0) + 1);
            m5.put(N*x + y, true);
        }

        int[] ans = new int[queries.length];
        // address queries
        for(int i=0; i<queries.length; i++){
            int x = queries[i][0];
            int y = queries[i][1];
            
            ans[i] = (m1.getOrDefault(x, 0) > 0 || m2.getOrDefault(y, 0) > 0 || m3.getOrDefault(x-y, 0) > 0 || m4.getOrDefault(x+y, 0) > 0) ? 1 : 0;            
            // switch off the lamps, if any
            for(int d=0; d<dirs.length; d++){
                int x1 = x + dirs[d][0];
                int y1 = y + dirs[d][1];
    if(m5.containsKey(N*x1 + y1) && m5.get(N*x1 + y1)){
                    // the lamp is on, turn it off, so decrement the count of the lamps
                    m1.put(x1, m1.getOrDefault(x1, 1) - 1);
                    m2.put(y1, m2.getOrDefault(y1, 1) - 1);
                    m3.put(x1 - y1, m3.getOrDefault(x1 - y1, 1) - 1);
                    m4.put(x1 + y1, m4.getOrDefault(x1 + y1, 1) - 1);
                    m5.put(N*x1+y1, false);
                }
            }
        }
        
        return ans;
    }
}
Update:
Following redundant code removed, Thanks to j46 for pointing it out!

 // following condition updated
 if(isValid(x1, y1) && m5.containsKey(N*x1 + y1) && m5.get(N*x1 + y1)){
 // removed the function for checking if the co-ordinates are valid, it is taken care by the .containsKey
    private boolean isValid(int x, int y){
        return (x >= 0 && x < MAX && y>=0 && y< MAX);    // MAX was class variable equal to N
    }
The exact complexity in terms of number of lamps, L and number of queries, Q is as follows:
Time Complexity: O(L+Q)
Space Complexity: O(L)

https://www.cnblogs.com/lz87/p/10434878.html

https://zxi.mytechroad.com/blog/hashtable/leetcode-1001-grid-illumination/
  vector<int> gridIllumination(int N, vector<vector<int>>& lamps, vector<vector<int>>& queries) {
    unordered_set<long> s;
    unordered_map<int, int> lx, ly, lp, lq;
    for (const auto& lamp : lamps) {
      const int x = lamp[0];
      const int y = lamp[1];
      s.insert(static_cast<long>(x) << 32 | y);
      ++lx[x];
      ++ly[y];
      ++lp[x + y];
      ++lq[x - y];
    }
    vector<int> ans;
    for (const auto& query : queries) {
      const int x = query[0];
      const int y = query[1];      
      if (lx.count(x) || ly.count(y) || lp.count(x + y) || lq.count(x - y)) {
        ans.push_back(1);      
        for (int tx = x - 1; tx <= x + 1; ++tx)
          for (int ty = y - 1; ty <= y + 1; ++ty) {
            if (tx < 0 || tx >= N || ty < 0 || ty >= N) continue;
            const long key = static_cast<long>(tx) << 32 | ty;
            if (!s.count(key)) continue;
            s.erase(key);
            if (--lx[tx] == 0) lx.erase(tx);
            if (--ly[ty] == 0) ly.erase(ty);
            if (--lp[tx + ty] == 0) lp.erase(tx + ty);
            if (--lq[tx - ty] == 0) lq.erase(tx - ty);
          }
      } else {
        ans.push_back(0);
      }
    }
    return ans;
  }

X. not efficient
http://www.noteanddata.com/leetcode-1001-Grid-Illumination-java-solution-note.html
    static class Position {
        int x;
        int y;
        public Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
        @Override
        public int hashCode() {
            return Objects.hash(x,y);
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Position position = (Position) o;
            return x == position.x &&
                    y == position.y;
        }       
        public String toString() {
            return "[" + x + "," + y + "]";
        }
    }
    public int[] gridIllumination(int N, int[][] lamps, int[][] queries) {
        Set<Position> lampset = new HashSet<>();
        Map<Integer, Set<Position>> rowMap = new HashMap<>();
        Map<Integer, Set<Position>> colMap = new HashMap<>();
        for(int[] lamp: lamps) {
            Position pos = new Position(lamp[0], lamp[1]);
            lampset.add(pos);
            rowMap.compute(lamp[0], (k,v)-> {
                if(v == null) {
                    Set<Position> set = new HashSet<>();
                    set.add(pos);
                    return set;
                }    
                else {
                    v.add(pos);
                    return v;
                }
            });
            colMap.compute(lamp[1], (k,v)->{
                if(v == null) {
                    Set<Position> set = new HashSet<>();
                    set.add(pos);
                    return set;
                }    
                else {
                    v.add(pos);
                    return v;
                }                
            });
        }
        int[] ret = new int[queries.length];
        
        for(int i = 0; i < queries.length; ++i) {
            if(rowMap.containsKey(queries[i][0])) {
                ret[i] = 1;
            }
            else if(colMap.containsKey(queries[i][1])) {
                ret[i] = 1;
            }
            else {
                for(Position pos: lampset) {
                    if(Math.abs(queries[i][0] - pos.x) == Math.abs(queries[i][1]-pos.y)) {
                        ret[i] = 1;
                        break;
                    }
                }
            }
            for(int p = -1; p <= 1; ++p) {
                for(int q = -1; q <= 1; ++q) {
                    int x = queries[i][0] + p;
                    int y = queries[i][1] + q;
                    
                    Position pos = new Position(x, y);
                    if(lampset.contains(pos)) {
                        lampset.remove(pos);
                        
                        Set<Position> setOnRow = rowMap.get(x);
                        setOnRow.remove(pos);
                        if(setOnRow.size() == 0) {
                            rowMap.remove(x);
                        }
                        
                        Set<Position> setOnCol = colMap.get(y);
                        setOnCol.remove(pos);
                        if(setOnCol.size() == 0) {
                            colMap.remove(y);
                        }
                    }
                }
            }            
        }
        return ret;
    }


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts