Google L3 | Phone Interview - Round 1 | Question | India
Anonymous User
1657

Interviewer started with a brief Intro and directly put the question on online shared doc,
The question was : https://leetcode.com/problems/bricks-falling-when-hit/

  • After thinking for a while , i came up with Disjoint Set Union Solution,
  • As i was seeing this problem for the first time, i took around 10-15 minutes to implement the same,
  • This is the code , that i have written,
  • I tried to write it as readable as possible, can you guys have a look and provide some feedback.

PS: I am still waiting for the Phone Interview Result :)

class DisjointSet{
private:
    int numberOfSets;
    vector<int> parent,size;
    
    void initializeParentAndSizeDataStructures()
    {
        parent.clear();
        size.clear();
        parent.resize(numberOfSets);
        size.resize(numberOfSets);
        for(int setIdx = 0; setIdx < numberOfSets; setIdx += 1)
        {
            parent[setIdx] = setIdx;
            size[setIdx] = 1;
        }
    }
public:
    
    DisjointSet(int numberOfSets)
    {
        this->numberOfSets = numberOfSets;
        initializeParentAndSizeDataStructures();
    }
    
    int getParent(int element)
    {
        if(element == parent[element])
        {
            return element;
        }
        return parent[element] = getParent(parent[element]);
    }

    int getSize(int element)
    {
        return size[getParent(element)];
    }

    void connectElements(int element1,int element2)
    {
        element1 = getParent(element1);
        element2 = getParent(element2);
        if(element1 == element2)
            return;
        if(size[element1] < size[element2])
            swap(element1,element2);
        parent[element2] = element1;
        size[element1] += size[element2];
    }
};

class Solution {
private:

    enum brickStatus{
        NotPresent = 0, 
        Present = 1,
        Removed = -1  
    };

    int numberOfRows,numberOfCols;
    vector<vector<int>> grid,hits;
    
    int getId(int rowIdx,int colIdx)
    {
        return rowIdx * numberOfCols + colIdx + 1;
    }
    
    bool isBrickPresent(int rowIdx,int colIdx)
    {
        return grid[rowIdx][colIdx] == Present;
    }
    
    bool isARemovedBrick(int rowIdx,int colIdx)
    {
        return grid[rowIdx][colIdx] == Removed;
    }

    void removeBrick(int rowIdx,int colIdx)
    {
        grid[rowIdx][colIdx] = Removed;
    }
    
    void addBrick(int rowIdx,int colIdx)
    {
        grid[rowIdx][colIdx] = Present;
    }
    
    void removeAllBricksPresentInHitsArray()
    {
        for(vector<int> brick : hits)
        {
            int rowIdx = brick[0];
            int colIdx = brick[1];
            if(isBrickPresent(rowIdx,colIdx))
            {
                removeBrick(rowIdx,colIdx);
            }  
        }
    }
    
    bool isValid(int rowIdx,int colIdx)
    {
        return rowIdx >= 0 and rowIdx < numberOfRows and colIdx >= 0 and colIdx < numberOfCols and isBrickPresent(rowIdx,colIdx);
    }

    void connectBrickToNeighbours(int rowIdx,int colIdx,DisjointSet &disjointSet)
    {
        int currentCellId = getId(rowIdx,colIdx);
        int directions[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; 
        
        for(int dir = 0; dir < 4; dir++)
        {
            int nextRowIdx = rowIdx + directions[dir][0];
            int nextColIdx = colIdx + directions[dir][1];
            if(isValid(nextRowIdx,nextColIdx))
            {
                int nextCellId = getId(nextRowIdx,nextColIdx);
                disjointSet.connectElements(currentCellId,nextCellId);
            }
        }
        if(rowIdx == 0)
        {
            disjointSet.connectElements(0,currentCellId);
        }
    }

    void connectAllBricks(DisjointSet &disjointSet)
    {
        for(int rowIdx = 0; rowIdx < numberOfRows; rowIdx++)
        {
            for(int colIdx = 0; colIdx < numberOfCols; colIdx++)
            {
                if(isBrickPresent(rowIdx,colIdx))
                {
                    connectBrickToNeighbours(rowIdx,colIdx,disjointSet);
                }
            }
        }   
    }
    
    vector<int> getHitBricksByAddingAllRemovedBricks(DisjointSet &disjointSet)
    {
        int numberOfBricksConnectedToRoof = disjointSet.getSize(0);
        vector<int> hitBricks(hits.size());
        for(int hit = hits.size() - 1; hit >= 0; hit--)
        {
            int rowIdx = hits[hit][0];
            int colIdx = hits[hit][1];
            if(isARemovedBrick(rowIdx,colIdx))
            {
                addBrick(rowIdx,colIdx);
                connectBrickToNeighbours(rowIdx,colIdx,disjointSet);
                int numberOfBricksConnectedToRoofAfterAddingBackTheBrick = disjointSet.getSize(0);
                hitBricks[hit] = max(numberOfBricksConnectedToRoofAfterAddingBackTheBrick - numberOfBricksConnectedToRoof - 1,0);
                numberOfBricksConnectedToRoof = numberOfBricksConnectedToRoofAfterAddingBackTheBrick;
            }
        }
        return hitBricks;
    }
    
    vector<int> getHitBricks()
    {
        // initialize Disjoint Set with number of sets = numberOfCols * numberOfRows
        DisjointSet disjointSet(numberOfRows * numberOfCols + 1);
        
        // First Remove all the bricks that are present in hits array.
        removeAllBricksPresentInHitsArray();
        
        // Connect all the bricks that are present.
        connectAllBricks(disjointSet);
        
        // Add all the removed bricks back
        return getHitBricksByAddingAllRemovedBricks(disjointSet);
    }
    
public:
    vector<int> hitBricks(vector<vector<int>>& grid, vector<vector<int>>& hits) {
        this->numberOfRows = grid.size();
        this->numberOfCols = grid[0].size();
        this->grid = grid;
        this->hits = hits;
        return getHitBricks();
    }
};
Comments (4)