Hard Leetcode Problem: Grid Illumination

Here is the problem: 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

I honestly believe that the key phrase in this problem is the one highlighted above: this problem is pretty much a variation of the N-queens problem, which has been solved on this blog before.
Have a set of hash tables to keep track of: row lights, column lights, forward diag lights and backwards diag lights. Add the lights from the grids to these hash tables. Then process the queries turning off the lights in the hash tables appropriately. That should do it. Cheers, ACC.


public class Solution
{
 public int[] GridIllumination(int N, int[][] lamps, int[][] queries)
 {
  Hashtable rows = new Hashtable();
  Hashtable cols = new Hashtable();
  Hashtable forwardDiag = new Hashtable();
  Hashtable backwardsDiag = new Hashtable();

  Hashtable lampHash = new Hashtable();

  //Fill out the HTs
  for (int i = 0; i < lamps.GetLength(0); i++)
  {
   int r = lamps[i][0];
   int c = lamps[i][1];
   if (!lampHash.ContainsKey(r * N + c)) lampHash.Add(r * N + c, true);

   IncrementHashTable(ref rows, r);
   IncrementHashTable(ref cols, c);
   IncrementHashTable(ref forwardDiag, r + c);
   IncrementHashTable(ref  backwardsDiag, r - c);
  }

  //Queries
  int[] results = new int[queries.GetLength(0)];
  for (int i = 0; i < queries.GetLength(0); i++)
  {
   int r = queries[i][0];
   int c = queries[i][1];
   results[i] = (CheckHashTable(ref rows, r) ||
       CheckHashTable(ref cols, c) ||
       CheckHashTable(ref forwardDiag, r + c) ||
       CheckHashTable(ref backwardsDiag, r - c)) ? 1 : 0;

   //Turn off the lights...
   for (int dr = -1; dr <= 1; dr++)
   {
    for (int dc = -1; dc <= 1; dc++)
    {
     if (r + dr >= 0 &&
      r + dr < N &&
      c + dc >= 0 &&
      c + dc < N &&
      lampHash.ContainsKey((r + dr) * N + c + dr))
     {
      DecrementHashTable(ref rows, r + dr);
      DecrementHashTable(ref cols, c + dc);
      DecrementHashTable(ref forwardDiag, r + dr + c + dc);
      DecrementHashTable(ref backwardsDiag, r + dr - c - dc);
      lampHash.Remove((r + dr) * N + c + dr);
     }
    }
   }
  }

  return results;
 }

 private void PrintGrid(int N,
       Hashtable rows,
       Hashtable cols,
       Hashtable forwardDiag,
       Hashtable backwardsDiag)
 {
  for (int r = 0; r < N; r++)
  {
   for (int c = 0; c < N; c++)
   {
    if (CheckHashTable(ref rows, r) ||
     CheckHashTable(ref cols, c) ||
     CheckHashTable(ref forwardDiag, r + c) ||
     CheckHashTable(ref backwardsDiag, r - c))
    {
     Console.Write("{0} ", 1);
    }
    else
    {
     Console.Write("{0} ", 0);
    }
   }
   Console.WriteLine();
  }
 }

 private void IncrementHashTable(ref Hashtable ht, int key)
 {
  if (!ht.ContainsKey(key)) ht.Add(key, 0);
  ht[key] = (int)ht[key] + 1;
 }

 private bool CheckHashTable(ref Hashtable ht, int key)
 {
  if (!ht.ContainsKey(key)) return false;
  return (int)ht[key] > 0;
 }

 private void DecrementHashTable(ref Hashtable ht, int key)
 {
  if (ht.ContainsKey(key)) ht[key] = (int)ht[key] - 1;
 }
}

Comments

Popular posts from this blog

Golang vs. C#: performance characteristics (simple case study)

Claude vs ChatGPT: A Coder's Perspective on LLM Performance

ProjectEuler Problem 719 (some hints, but no spoilers)