Friday, September 18, 2020

529. Minesweeper

 Let's play the minesweeper game (Wikipedia, online game)!

You are given a 2D char matrix representing the game board. 'M' represents an unrevealedmine, 'E' represents an unrevealed empty square, 'B' represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit ('1' to '8') represents how many mines are adjacent to this revealed square, and finally 'X' represents a revealed mine.

Now given the next click position (row and column indices) among all the unrevealedsquares ('M' or 'E'), return the board after revealing this position according to the following rules:

  1. If a mine ('M') is revealed, then the game is over - change it to 'X'.
  2. If an empty square ('E') with no adjacent mines is revealed, then change it to revealed blank ('B') and all of its adjacent unrevealed squares should be revealed recursively.
  3. If an empty square ('E') with at least one adjacent mine is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines.
  4. Return the board when no more squares will be revealed.

 

Example 1:

Input: 

[['E', 'E', 'E', 'E', 'E'],
 ['E', 'E', 'M', 'E', 'E'],
 ['E', 'E', 'E', 'E', 'E'],
 ['E', 'E', 'E', 'E', 'E']]

Click : [3,0]

Output: 

[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'M', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]

Explanation:

Example 2:

Input: 

[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'M', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]

Click : [1,2]

Output: 

[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'X', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]

Explanation:

 

Note:

  1. The range of the input matrix's height and width is [1,50].
  2. The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square.
  3. The input board won't be a stage when game is over (some mines have been revealed).
  4. For simplicity, not mentioned rules should be ignored in this problem. For example, you don't need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.


class Solution {
public:
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        if (board[click[0]][click[1]] == 'M') {
            board[click[0]][click[1]] = 'X';
            return board;
        }
        
        // Check for digits.
        int count = countMines(click, board);
        if (count != 0) {
            board[click[0]][click[1]] = '0' + count;
        } else {
            vector<pair<int, int>> neighbors = {{0,1}, {0,-1}, {1,0}, {-1,0},
                                               {1,1}, {-1,-1}, {-1,1}, {1,-1}};
            board[click[0]][click[1]] = 'B';
            for (auto neighbor : neighbors) {
                int new_x = click[0] + neighbor.first;
                int new_y = click[1] + neighbor.second;
                if (new_x >= 0 && new_x < board.size() && new_y >= 0 && new_y < board[0].size() && board[new_x][new_y] == 'E') {
                    vector<int> newClick = {new_x, new_y};
                    updateBoard(board, newClick);
                }
            }
        }
        return board;
    }
    
    int countMines(vector<int>& click, vector<vector<char>>& board) {
        int count = 0;
        vector<pair<int, int>> neighbors = {{0,1}, {0,-1}, {1,0}, {-1,0},
                                               {1,1}, {-1,-1}, {-1,1}, {1,-1}};
        for (auto neighbor : neighbors) {
            int new_x = click[0] + neighbor.first;
            int new_y = click[1] + neighbor.second;
            if (new_x >= 0 && new_x < board.size() && new_y >= 0 && new_y < board[0].size()) {
                if (board[new_x][new_y] == 'M') {
                    count++;
                }
            }
        }
        return count;
    }
};

Sunday, September 13, 2020

42. Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.


The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

class Solution {
public:
    int trap(vector<int>& height) {
        int size = height.size();
        if (size == 0) {
            return 0;
        }
        
        int ans = 0;
        int left = 0, right = size - 1;
        int left_iter = left + 1;
        int right_iter = right - 1;
        while (left <= right && left_iter <= right_iter) {
            if (height[left] <= height[right]) {
                left_iter = left + 1;
                while (left_iter <= right_iter) {
                    if (height[left_iter] >= height[left]) {
                        left = left_iter;
                        break;
                    } else {
                        ans += height[left] - height[left_iter];
                    }
                    left_iter++;
                }
            } else {
                right_iter = right - 1;
                while (right_iter >= left_iter) {
                    if (height[right_iter] >= height[right]) {
                        right = right_iter;
                        break;
                    } else {
                        ans += height[right] - height[right_iter];
                    }
                    right_iter--;
                }
            }
        }
        return ans;
        
    /*
    cleaner one:
    int trap(vector<int>& height) {
        if(height.size() == 0) return 0;
        int n = height.size();
        int left = 0, right = n-1;
        int left_max = height[left], right_max = height[right];
        int area = 0;
        while(left < right){
            if(height[right] > height[left]){
                if(left_max < height[left]){ // Difference mein paani bhar do
                    left_max = height[left];
                }else{
                    area += left_max - height[left];
                }
                left++;
            }else{
                if(right_max < height[right]){
                    right_max = height[right];
                }else{
                    area += right_max - height[right];
                }
                right--;
            }            
        }
        return area;
    }
        
        ////////////////////////////////////////////////
        
    Extra space:
    int trap(vector<int>& height) {
        
        if(height.size()<1)
            return 0;
        
        int n=height.size();
        int left_max[n],right_max[n];
        
        left_max[0]=height[0];
        right_max[n-1]=height[n-1];
        
        for(int i=1;i<n;i++){
            left_max[i]=max(left_max[i-1],height[i]);
            right_max[n-i-1]=max(right_max[n-i],height[n-i-1]);
        }
        
        int water=0;
        
        for(int i=1;i<n-1;i++)
        {
            water+=min(left_max[i],right_max[i])-height[i];
            
        }
        return water;
    }
        
    */
    }
};

1095. Find in Mountain Array

 You may recall that an array A is a mountain array if and only if:

  • A.length >= 3
  • There exists some i with 0 < i < A.length - 1 such that:
    • A[0] < A[1] < ... A[i-1] < A[i]
    • A[i] > A[i+1] > ... > A[A.length - 1]

Given a mountain array mountainArr, return the minimum index such that mountainArr.get(index) == target.  If such an index doesn't exist, return -1.

You can't access the mountain array directly.  You may only access the array using a MountainArray interface:

  • MountainArray.get(k) returns the element of the array at index k (0-indexed).
  • MountainArray.length() returns the length of the array.

Submissions making more than 100 calls to MountainArray.get will be judged Wrong Answer.  Also, any solutions that attempt to circumvent the judge will result in disqualification.

     

    Example 1:

    Input: array = [1,2,3,4,5,3,1], target = 3
    Output: 2
    Explanation: 3 exists in the array, at index=2 and index=5. Return the minimum index, which is 2.

    Example 2:

    Input: array = [0,1,2,4,2,1], target = 3
    Output: -1
    Explanation: 3 does not exist in the array, so we return -1.
    

     

    Constraints:

    • 3 <= mountain_arr.length() <= 10000
    • 0 <= target <= 10^9
    • 0 <= mountain_arr.get(index) <= 10^9

    /**
     * // This is the MountainArray's API interface.
     * // You should not implement it, or speculate about its implementation
     * class MountainArray {
     *   public:
     *     int get(int index);
     *     int length();
     * };
     */

    class Solution {
    public:
        int findInMountainArray(int target, MountainArray &mountainArr) {
            int peak_idx = findpeak(mountainArr);
            if (peak_idx == -1) {
                return -1;
            }
            
            int left_idx = binary_search(mountainArr, 0, peak_idx, target);
            if (left_idx != -1) {
                return left_idx;
            }
            return binary_search_opposite(mountainArr, peak_idx + 1, mountainArr.length() - 1, target);
            
            
        }
        
        int findpeak(MountainArray &mountainArr) {
            int st = 0;
            int end = mountainArr.length() - 1;
            
            while (st < end) {
                int mid = st + (end - st)/2;
                if (mid == 0) {
                    return -1;
                }
                int mid_elem = mountainArr.get(mid);
                if (mid_elem > mountainArr.get(mid + 1) &&
                    mid_elem > mountainArr.get(mid - 1)) {
                    return mid;
                } else if (mid_elem > mountainArr.get(mid - 1)) {
                    st = mid + 1;
                } else {
                    end = mid;
                }
            }
            return -1;
        }
        
        int binary_search(MountainArray &mountainArr, int start, int end_idx, int target) {
            int st = start;
            int end = end_idx;
            
            while (st <= end) {
                int mid = st + (end - st)/2;
                int mid_elem = mountainArr.get(mid);
                if (mid_elem == target) {
                    return mid;
                } else if (mid_elem < target) {
                    st = mid + 1;
                } else {
                    end = mid - 1;
                }
            }
            return -1;
        }
        
        int binary_search_opposite(MountainArray &mountainArr, int start, int end_idx, int target) {
            int st = start;
            int end = end_idx;
            
            while (st <= end) {
                int mid = st + (end - st)/2;
                int mid_elem = mountainArr.get(mid);
                if (mid_elem == target) {
                    return mid;
                } else if (mid_elem > target) {
                    st = mid + 1;
                } else {
                    end = mid - 1;
                }
            }
            return -1;
        }
        
    };

    Tuesday, September 8, 2020

    341. Flatten Nested List Iterator

     Given a nested list of integers, implement an iterator to flatten it.

    Each element is either an integer, or a list -- whose elements may also be integers or other lists.

    Example 1:

    Input: [[1,1],2,[1,1]]
    Output: [1,1,2,1,1]
    Explanation: By calling next repeatedly until hasNext returns false, 
                 the order of elements returned by next should be: [1,1,2,1,1].

    Example 2:

    Input: [1,[4,[6]]]
    Output: [1,4,6]
    Explanation: By calling next repeatedly until hasNext returns false, 
                 the order of elements returned by next should be: [1,4,6].
    /**
     * // This is the interface that allows for creating nested lists.
     * // You should not implement it, or speculate about its implementation
     * class NestedInteger {
     *   public:
     *     // Return true if this NestedInteger holds a single integer, rather than a nested list.
     *     bool isInteger() const;
     *
     *     // Return the single integer that this NestedInteger holds, if it holds a single integer
     *     // The result is undefined if this NestedInteger holds a nested list
     *     int getInteger() const;
     *
     *     // Return the nested list that this NestedInteger holds, if it holds a nested list
     *     // The result is undefined if this NestedInteger holds a single integer
     *     const vector<NestedInteger> &getList() const;
     * };
     */
    
    class NestedIterator {
    public:
        NestedIterator(vector<NestedInteger> &nestedList) {
            helper(nestedList, data);
            if (data.size() != 0) {
                cur = 0;
            }
        }
        
        int next() {
            int ans;
            if (hasNext()) {
                ans = data[cur];
                cur++;
            }
            return ans;
        }
        
        bool hasNext() {
            return cur < data.size();
        }
        
    private:
        void helper(vector<NestedInteger> &nestedList, vector<int>& data) {
            for (auto NI : nestedList) {
                if (NI.isInteger()) {
                    data.push_back(NI.getInteger());
                } else {
                    helper(NI.getList(), data);
                }
            }
        }
        vector<int> data;
        int cur;
    };
    
    /**
     * Your NestedIterator object will be instantiated and called as such:
     * NestedIterator i(nestedList);
     * while (i.hasNext()) cout << i.next();
     */

    Thursday, September 3, 2020

    207. Course Schedule

     There are a total of numCourses courses you have to take, labeled from 0 to numCourses-1.

    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

    Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

     

    Example 1:

    Input: numCourses = 2, prerequisites = [[1,0]]
    Output: true
    Explanation: There are a total of 2 courses to take. 
                 To take course 1 you should have finished course 0. So it is possible.
    

    Example 2:

    Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
    Output: false
    Explanation: There are a total of 2 courses to take. 
                 To take course 1 you should have finished course 0, and to take course 0 you should
                 also have finished course 1. So it is impossible.
    

     

    Constraints:

    • The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
    • You may assume that there are no duplicate edges in the input prerequisites.
    • 1 <= numCourses <= 10^5

    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            // Check cycle.
            vector<vector<int>> graph = vector<vector<int>>(numCourses, vector<int>());
            
            for (auto prereq : prerequisites) {
                graph[prereq[0]].push_back(prereq[1]);
            }
            
            vector<int> graph_state = vector<int>(numCourses, 0);
            
            for (int node = 0; node < numCourses; node++) {
                if (graph_state[node] == 0 && cycle(graph, graph_state, node)) {
                    return false;
                }
            }
            return true;
        }
        
        // DFS.
        bool cycle(vector<vector<int>>& graph, vector<int>& state, int node) {
            if (state[node] == 2) {
                return false;
            }
            if (state[node] == 1) {
                return true;
            }
            state[node] = 1;
            for (auto neighbor : graph[node]) {
                if (cycle(graph, state, neighbor)) {
                    return true;
                }
            }
            state[node] = 2;
            return false;
        }
    };