# Split a String Into the Max Number of Unique Substrings

- slug: split-a-string-into-the-max-number-of-unique-substrings
- difficulty: Medium

Given a string `s`, return _the maximum number of unique substrings that the given string can be split into_.

You can split string `s` into any list of **non-empty substrings**, where the concatenation of the substrings forms the original string. However, you must split the substrings such that all of them are **unique**.

A **substring** is a contiguous sequence of characters within a string.

**Example 1:**

**Input:** s =  "ababccc "
**Output:** 5
**Explanation**: One way to split maximally is \['a', 'b', 'ab', 'c', 'cc'\]. Splitting like \['a', 'b', 'a', 'b', 'c', 'cc'\] is not valid as you have 'a' and 'b' multiple times.

**Example 2:**

**Input:** s =  "aba "
**Output:** 2
**Explanation**: One way to split maximally is \['a', 'ba'\].

**Example 3:**

**Input:** s =  "aa "
**Output:** 1
**Explanation**: It is impossible to split the string any further.

**Constraints:**

*   `1 <= s.length <= 16`

*   `s` contains only lower case English letters.

## A solution in Java

```java
import java.util.HashSet;

public int maxUniqueSplit(String s) {
    return maxUniqueSplit(s, 0, new HashSet<String>());
}

private int maxUniqueSplit(String s, int start, HashSet<String> seen) {
    if (start == s.length()) {
        return 0;
    }
    int maxUnique = -1;
    for (int i = start + 1; i <= s.length(); ++i) {
        String sub = s.substring(start, i);
        if (!seen.contains(sub)) {
            seen.add(sub);
            int unique = maxUniqueSplit(s, i, seen);
            if (unique != -1) {
                maxUnique = Math.max(maxUnique, unique + 1);
            }
            seen.remove(sub);
        }
    }
    return maxUnique;
}
```
The algorithm is a recursive backtracking algorithm. We start at the beginning of the string and iteratively build substrings from the current starting position. If the substring is not already in the set of seen substrings, we add it to the set and continue the split process for the remaining part of the string. Then we remove the substring from the set of seen substrings and continue with the next possible substring. The base case is reached when we processed the entire string, in which case we return 0 as the initial value for the split count. The final result will be the maximum number of unique substrings found during the recursive process.

## A solution in C++

```cpp
#include <string>
#include <unordered_set>

int maxUniqueSplit(const std::string& s, int start = 0, std::unordered_set<std::string>& seen = std::unordered_set<std::string>()) {
    if (start == s.size())
        return 0;
    int maxUnique = -1;
    for (int i = start + 1; i <= s.size(); ++i) {
        std::string sub = s.substr(start, i - start);
        if (seen.find(sub) == seen.end()) {
            seen.insert(sub);
            int unique = maxUniqueSplit(s, i, seen);
            if (unique != -1)
                maxUnique = std::max(maxUnique, unique + 1);
            seen.erase(sub);
        }
    }
    return maxUnique;
}
```
The algorithm is a recursive backtracking algorithm. We start at the beginning of the string and iteratively build substrings from the current starting position. If the substring is not already in the set of seen substrings, we add it to the set and continue the split process for the remaining part of the string. Then we remove the substring from the set of seen substrings and continue with the next possible substring. The base case is reached when we processed the entire string, in which case we return 0 as the initial value for the split count. The final result will be the maximum number of unique substrings found during the recursive process.

## A solution in Python

```python
def maxUniqueSplit(s, start=0, seen=None):
    if seen is None:
        seen = set()
    if start == len(s):
        return 0
    maxUnique = -1
    for i in range(start + 1, len(s) + 1):
        sub = s[start:i]
        if sub not in seen:
            seen.add(sub)
            unique = maxUniqueSplit(s, i, seen)
            if unique != -1:
                maxUnique = max(maxUnique, unique + 1)
            seen.remove(sub)
    return maxUnique
```
The algorithm is a recursive backtracking algorithm. We start at the beginning of the string and iteratively build substrings from the current starting position. If the substring is not already in the set of seen substrings, we add it to the set and continue the split process for the remaining part of the string. Then we remove the substring from the set of seen substrings and continue with the next possible substring. The base case is reached when we processed the entire string, in which case we return 0 as the initial value for the split count. The final result will be the maximum number of unique substrings found during the recursive process.

## A solution in Javascript

```javascript
function maxUniqueSplit(s, start = 0, seen = new Set()) {
    if (start === s.length) {
        return 0;
    }
    let maxUnique = -1;
    for (let i = start + 1; i <= s.length; ++i) {
        let sub = s.slice(start, i);
        if (!seen.has(sub)) {
            seen.add(sub);
            let unique = maxUniqueSplit(s, i, seen);
            if (unique !== -1) {
                maxUnique = Math.max(maxUnique, unique + 1);
            }
            seen.delete(sub);
        }
    }
    return maxUnique;
}
```
The algorithm is a recursive backtracking algorithm. We start at the beginning of the string and iteratively build substrings from the current starting position. If the substring is not already in the set of seen substrings, we add it to the set and continue the split process for the remaining part of the string. Then we remove the substring from the set of seen substrings and continue with the next possible substring. The base case is reached when we processed the entire string, in which case we return 0 as the initial value for the split count. The final result will be the maximum number of unique substrings found during the recursive process.


# Maximum Non Negative Product in a Matrix

- slug: maximum-non-negative-product-in-a-matrix
- difficulty: Medium

You are given a `m x n` matrix `grid`. Initially, you are located at the top-left corner `(0, 0)`, and in each step, you can only **move right or down** in the matrix.

Among all possible paths starting from the top-left corner `(0, 0)` and ending in the bottom-right corner `(m - 1, n - 1)`, find the path with the **maximum non-negative product**. The product of a path is the product of all integers in the grid cells visited along the path.

Return the _maximum non-negative product **modulo**_ `109 + 7`. _If the maximum product is **negative**, return_ `-1`.

Notice that the modulo is performed after getting the maximum product.

**Example 1:**

**Input:** grid = \[\[-1,-2,-3\],\[-2,-3,-3\],\[-3,-3,-2\]\]
**Output:** -1
**Explanation:** It is not possible to get non-negative product in the path from (0, 0) to (2, 2), so return -1.

**Example 2:**

**Input:** grid = \[\[1,-2,1\],\[1,-2,1\],\[3,-4,1\]\]
**Output:** 8
**Explanation:** Maximum non-negative product is shown (1 \* 1 \* -2 \* -4 \* 1 = 8).

**Example 3:**

**Input:** grid = \[\[1,3\],\[0,-4\]\]
**Output:** 0
**Explanation:** Maximum non-negative product is shown (1 \* 0 \* -4 = 0).

**Constraints:**

*   `m == grid.length`
*   `n == grid[i].length`
*   `1 <= m, n <= 15`
*   `-4 <= grid[i][j] <= 4`

## A solution in Java

```java
public int maxProductPath(int[][] grid) {
    int m = grid.length, n = grid[0].length, mod = 1_000_000_007;
    long[][][] dp = new long[m][n][2];
    dp[0][0][0] = dp[0][0][1] = grid[0][0];
    for (int i = 1; i < m; ++i) dp[i][0][0] = dp[i][0][1] = grid[i][0] * dp[i - 1][0][0];
    for (int j = 1; j < n; ++j) dp[0][j][0] = dp[0][j][1] = grid[0][j] * dp[0][j - 1][0];
    for (int i = 1; i < m; ++i) {
        for (int j = 1; j < n; ++j) {
            if (grid[i][j] < 0) {
                dp[i][j][0] = Math.min(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
                dp[i][j][1] = Math.max(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
            } else {
                dp[i][j][0] = Math.min(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
                dp[i][j][1] = Math.max(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
            }
        }
    }
    return dp[m - 1][n - 1][1] < 0 ? -1 : (int)(dp[m - 1][n - 1][1] % mod);
}
```
We use dynamic programming. We create a 3D DP array, `dp[m][n][2]`, where `dp[i][j][0]` and `dp[i][j][1]` store the smallest and largest product ending at `(i, j)`. We initialize `dp[0][0]` with the starting value and set each entry in the first row and column accordingly.

For each cell `(i, j)` in the grid, if the value is negative, we multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`. If the value is non-negative, we multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`.

Finally, we return -1 if the last element of the last row in the DP array is negative, otherwise, we return the result modulo `1e9 + 7`.

## A solution in C++

```cpp
int maxProductPath(vector<vector<int>>& grid) {
    int m = grid.size(), n = grid[0].size(), mod = 1e9 + 7;
    vector<vector<vector<long long>>> dp(m, vector<vector<long long>>(n, vector<long long>(2, 0)));
    dp[0][0][0] = dp[0][0][1] = grid[0][0];
    for (int i = 1; i < m; ++i) dp[i][0][0] = dp[i][0][1] = grid[i][0] * dp[i - 1][0][0];
    for (int j = 1; j < n; ++j) dp[0][j][0] = dp[0][j][1] = grid[0][j] * dp[0][j - 1][0];
    for (int i = 1; i < m; ++i) {
        for (int j = 1; j < n; ++j) {
            if (grid[i][j] < 0) {
                dp[i][j][0] = min(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
                dp[i][j][1] = max(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
            } else {
                dp[i][j][0] = min(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
                dp[i][j][1] = max(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
            }
        }
    }
    return dp.back().back()[1] < 0 ? -1 : dp.back().back()[1] % mod;
}
```
We use dynamic programming. We create a 3D DP array, `dp[m][n][2]`, where `dp[i][j][0]` and `dp[i][j][1]` store the smallest and largest product ending at `(i, j)`. We initialize `dp[0][0]` with the starting value and set each entry in the first row and column accordingly.

For each cell `(i, j)` in the grid, if the value is negative, we multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`. If the value is non-negative, we multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`.

Finally, we return -1 if the last element of the last row in the DP array is negative, otherwise, we return the result modulo `1e9 + 7`.

## A solution in Python

```python
def maxProductPath(self, grid: List[List[int]]) -> int:
    m, n, mod = len(grid), len(grid[0]), 10**9 + 7
    dp = [[[0, 0] for _ in range(n)] for _ in range(m)]
    dp[0][0] = [grid[0][0], grid[0][0]]
    for i in range(1, m):
        dp[i][0] = [grid[i][0] * dp[i - 1][0][0], grid[i][0] * dp[i - 1][0][0]]
    for j in range(1, n):
        dp[0][j] = [grid[0][j] * dp[0][j - 1][0], grid[0][j] * dp[0][j - 1][0]]
    for i in range(1, m):
        for j in range(1, n):
            if grid[i][j] < 0:
                dp[i][j][0] = min(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1])
                dp[i][j][1] = max(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0])
            else:
                dp[i][j][0] = min(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0])
                dp[i][j][1] = max(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1])
    return -1 if dp[-1][-1][1] < 0 else dp[-1][-1][1] % mod
```
We use dynamic programming. We create a 3D DP array, `dp[m][n][2]`, where `dp[i][j][0]` and `dp[i][j][1]` store the smallest and largest product ending at `(i, j)`. We initialize `dp[0][0]` with the starting value and set each entry in the first row and column accordingly.

For each cell `(i, j)` in the grid, if the value is negative, we multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`. If the value is non-negative, we multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`.

Finally, we return -1 if the last element of the last row in the DP array is negative, otherwise, we return the result modulo `1e9 + 7`.

## A solution in Javascript

```javascript
const maxProductPath = (grid) => {
    const m = grid.length, n = grid[0].length, mod = 1e9 + 7;
    let dp = Array.from(Array(m), () => Array.from(Array(n), () => [0, 0]));
    dp[0][0] = [grid[0][0], grid[0][0]];
    for (let i = 1; i < m; ++i) dp[i][0] = [grid[i][0] * dp[i - 1][0][0], grid[i][0] * dp[i - 1][0][0]];
    for (let j = 1; j < n; ++j) dp[0][j] = [grid[0][j] * dp[0][j - 1][0], grid[0][j] * dp[0][j - 1][0]];
    for (let i = 1; i < m; ++i) {
        for (let j = 1; j < n; ++j) {
            if (grid[i][j] < 0) {
                dp[i][j][0] = Math.min(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
                dp[i][j][1] = Math.max(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
            } else {
                dp[i][j][0] = Math.min(grid[i][j] * dp[i - 1][j][0], grid[i][j] * dp[i][j - 1][0]);
                dp[i][j][1] = Math.max(grid[i][j] * dp[i - 1][j][1], grid[i][j] * dp[i][j - 1][1]);
            }
        }
    }
    return dp[m - 1][n - 1][1] < 0 ? -1 : dp[m - 1][n - 1][1] % mod;
};
```
We use dynamic programming. We create a 3D DP array, `dp[m][n][2]`, where `dp[i][j][0]` and `dp[i][j][1]` store the smallest and largest product ending at `(i, j)`. We initialize `dp[0][0]` with the starting value and set each entry in the first row and column accordingly.

For each cell `(i, j)` in the grid, if the value is negative, we multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`. If the value is non-negative, we multiply the maximum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][0]`. We multiply the minimum of each adjacent cell in the DP array by the current value and store it in `dp[i][j][1]`.

Finally, we return -1 if the last element of the last row in the DP array is negative, otherwise, we return the result modulo `1e9 + 7`.


# Minimum Cost to Connect Two Groups of Points

- slug: minimum-cost-to-connect-two-groups-of-points
- difficulty: Hard

You are given two groups of points where the first group has `size1` points, the second group has `size2` points, and `size1 >= size2`.

The `cost` of the connection between any two points are given in an `size1 x size2` matrix where `cost[i][j]` is the cost of connecting point `i` of the first group and point `j` of the second group. The groups are connected if **each point in both groups is connected to one or more points in the opposite group**. In other words, each point in the first group must be connected to at least one point in the second group, and each point in the second group must be connected to at least one point in the first group.

Return _the minimum cost it takes to connect the two groups_.

**Example 1:**

**Input:** cost = \[\[15, 96\], \[36, 2\]\]
**Output:** 17
**Explanation**: The optimal way of connecting the groups is:
1--A
2--B
This results in a total cost of 17.

**Example 2:**

**Input:** cost = \[\[1, 3, 5\], \[4, 1, 1\], \[1, 5, 3\]\]
**Output:** 4
**Explanation**: The optimal way of connecting the groups is:
1--A
2--B
2--C
3--A
This results in a total cost of 4.
Note that there are multiple points connected to point 2 in the first group and point A in the second group. This does not matter as there is no limit to the number of points that can be connected. We only care about the minimum total cost.

**Example 3:**

**Input:** cost = \[\[2, 5, 1\], \[3, 4, 7\], \[8, 1, 2\], \[6, 2, 4\], \[3, 8, 8\]\]
**Output:** 10

**Constraints:**

*   `size1 == cost.length`
*   `size2 == cost[i].length`
*   `1 <= size1, size2 <= 12`
*   `size1 >= size2`
*   `0 <= cost[i][j] <= 100`

## A solution in Java

```java
import java.util.Arrays;

public int connectTwoGroups(List<List<Integer>> cost) {
    int size1 = cost.size(), size2 = cost.get(0).size();
    int[] min_cost = new int[size2];
    Arrays.fill(min_cost, Integer.MAX_VALUE);

    for (int i = 0; i < size1; i++) {
        for (int j = 0; j < size2; j++) {
            min_cost[j] = Math.min(min_cost[j], cost.get(i).get(j));
        }
    }

    int total_cost = 0;
    for (int i = 0; i < size1; i++) {
        total_cost += Collections.min(cost.get(i));
    }

    for (int j = 0; j < size2; j++) {
        total_cost += min_cost[j];
    }

    return total_cost;
}
```
To minimize the cost of connecting the two groups, we should first find the minimum cost of connecting each point i in the first group with all the points in the second group, and then find the minimum cost of connecting each point j in the second group with all the points in the first group.

1. Iterate through each point of the first group.
2. For each point i in the first group, find the minimum cost of connecting it with all the points in the second group.
3. Store the minimum cost in the min_cost array for the second group points.
4. Add up the total minimum cost for all points in the first group.
5. Add up the minimum cost for all points in the second group from the min_cost array.
6. Return the total cost as the minimum cost to connect the two groups.

## A solution in C++

```cpp
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int connectTwoGroups(vector<vector<int>>& cost) {
    int size1 = cost.size(), size2 = cost[0].size();
    vector<int> min_cost(size2, INT_MAX);

    for (int i = 0; i < size1; i++) {
        for (int j = 0; j < size2; j++) {
            min_cost[j] = min(min_cost[j], cost[i][j]);
        }
    }

    int total_cost = 0;
    for (int i = 0; i < size1; i++) {
        total_cost += *min_element(cost[i].begin(), cost[i].end());
    }

    for (int j = 0; j < size2; j++) {
        total_cost += min_cost[j];
    }

    return total_cost;
}
```
To minimize the cost of connecting the two groups, we should first find the minimum cost of connecting each point i in the first group with all the points in the second group, and then find the minimum cost of connecting each point j in the second group with all the points in the first group.

1. Iterate through each point of the first group.
2. For each point i in the first group, find the minimum cost of connecting it with all the points in the second group.
3. Store the minimum cost in the min_cost array for the second group points.
4. Add up the total minimum cost for all points in the first group.
5. Add up the minimum cost for all points in the second group from the min_cost array.
6. Return the total cost as the minimum cost to connect the two groups.

## A solution in Python

```python
def connectTwoGroups(cost):
    size1, size2 = len(cost), len(cost[0])
    min_cost = [float('inf')] * size2

    for i in range(size1):
        for j in range(size2):
            min_cost[j] = min(min_cost[j], cost[i][j])

    total_cost = 0
    for i in range(size1):
        total_cost += min(cost[i])

    for j in range(size2):
        total_cost += min_cost[j]

    return total_cost
```
To minimize the cost of connecting the two groups, we should first find the minimum cost of connecting each point i in the first group with all the points in the second group, and then find the minimum cost of connecting each point j in the second group with all the points in the first group.

1. Iterate through each point of the first group.
2. For each point i in the first group, find the minimum cost of connecting it with all the points in the second group.
3. Store the minimum cost in the min_cost array for the second group points.
4. Add up the total minimum cost for all points in the first group.
5. Add up the minimum cost for all points in the second group from the min_cost array.
6. Return the total cost as the minimum cost to connect the two groups.

## A solution in Javascript

```javascript
function connectTwoGroups(cost) {
    const size1 = cost.length, size2 = cost[0].length;
    const min_cost = Array(size2).fill(Infinity);

    for (let i = 0; i < size1; i++) {
        for (let j = 0; j < size2; j++) {
            min_cost[j] = Math.min(min_cost[j], cost[i][j]);
        }
    }

    let total_cost = 0;
    for (let i = 0; i < size1; i++) {
        total_cost += Math.min(...cost[i]);
    }

    for (let j = 0; j < size2; j++) {
        total_cost += min_cost[j];
    }

    return total_cost;
}
```
To minimize the cost of connecting the two groups, we should first find the minimum cost of connecting each point i in the first group with all the points in the second group, and then find the minimum cost of connecting each point j in the second group with all the points in the first group.

1. Iterate through each point of the first group.
2. For each point i in the first group, find the minimum cost of connecting it with all the points in the second group.
3. Store the minimum cost in the min_cost array for the second group points.
4. Add up the total minimum cost for all points in the first group.
5. Add up the minimum cost for all points in the second group from the min_cost array.
6. Return the total cost as the minimum cost to connect the two groups.


# Build Binary Expression Tree From Infix Expression

- slug: build-binary-expression-tree-from-infix-expression
- difficulty: Hard

A **[binary expression tree](https://en.wikipedia.org/wiki/Binary_expression_tree)** is a kind of binary tree used to represent arithmetic expressions. Each node of a binary expression tree has either zero or two children. Leaf nodes (nodes with 0 children) correspond to operands (numbers), and internal nodes (nodes with 2 children) correspond to the operators `'+'` (addition), `'-'` (subtraction), `'*'` (multiplication), and `'/'` (division).

For each internal node with operator `o`, the [**infix expression**](https://en.wikipedia.org/wiki/Infix_notation) it represents is `(A o B)`, where `A` is the expression the left subtree represents and `B` is the expression the right subtree represents.

You are given a string `s`, an **infix expression** containing operands, the operators described above, and parentheses `'('` and `')'`.

Return _any valid **binary expression tree**, whose **[in-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#In-order_(LNR))** reproduces_ `s` _after omitting the parenthesis from it._

**Please note that order of operations applies in** `s`**.** That is, expressions in parentheses are evaluated first, and multiplication and division happen before addition and subtraction.

Operands must also appear in the **same order** in both `s` and the in-order traversal of the tree.

**Example 1:**

**Input:** s =  "3\*4-2\*5 "
**Output:** \[-,\*,\*,3,4,2,5\]
**Explanation:** The tree above is the only valid tree whose inorder traversal produces s.

**Example 2:**

**Input:** s =  "2-3/(5\*2)+1 "
**Output:** \[+,-,1,2,/,null,null,null,null,3,\*,null,null,5,2\]
**Explanation:** The inorder traversal of the tree above is 2-3/5\*2+1 which is the same as s without the parenthesis. The tree also produces the correct result and its operands are in the same order as they appear in s.
The tree below is also a valid binary expression tree with the same inorder traversal as s, but it not a valid answer because it does not evaluate to the same value.

The third tree below is also not valid. Although it produces the same result and is equivalent to the above trees, its inorder traversal does not produce s and its operands are not in the same order as s.

**Example 3:**

**Input:** s =  "1+2+3+4+5 "
**Output:** \[+,+,5,+,4,null,null,+,3,null,null,1,2\]
**Explanation:** The tree \[+,+,5,+,+,null,null,1,2,3,4\] is also one of many other valid trees.

**Constraints:**

*   `1 <= s.length <= 100`
*   `s` consists of digits and the characters `'+'`, `'-'`, `'*'`, and `'/'`.
*   Operands in `s` are **exactly** 1 digit.
*   It is guaranteed that `s` is a valid expression.

## A solution in Java

```java
class Solution {
    public TreeNode expTree(String s) {
        Stack<TreeNode> nodes = new Stack<>();
        Stack<Character> ops = new Stack<>();
        for (int i = 0; i < s.length(); ++i) {
            if (Character.isDigit(s.charAt(i))) {
                nodes.push(new TreeNode(s.charAt(i)));
            } else if (s.charAt(i) == '(') {
                ops.push(s.charAt(i));
            } else if (s.charAt(i) == ')') {
                while (ops.peek() != '(') {
                    process(nodes, ops);
                }
                ops.pop();
            } else {
                while (!ops.empty() && precedence(ops.peek(), s.charAt(i))) {
                    process(nodes, ops);
                }
                ops.push(s.charAt(i));
            }
        }
        while (!ops.empty()) {
            process(nodes, ops);
        }
        return nodes.peek();
    }

    private boolean precedence(char a, char b) {
        if (a == '(') return false;
        if (b == '(' || b == ')') return true;
        if ((a == '*' || a == '/') && (b == '+' || b == '-')) return true;
        return false;
    }

    private void process(Stack<TreeNode> nodes, Stack<Character> ops) {
        TreeNode right = nodes.pop();
        TreeNode left = nodes.pop();
        TreeNode oper = new TreeNode(ops.pop());
        oper.left = left;
        oper.right = right;
        nodes.push(oper);
    }
}
```
This solution follows the algorithm of the well-known Shunting Yard algorithm. We process the input string `s` character by character.

1. If the character `s[i]` is a digit, create a `TreeNode` with the value and push it to the `nodes` stack.
2. If the character is an opening parenthesis, push it to the `ops` stack.
3. If the character is a closing parenthesis, pop the operators from the `ops` stack and process them with the corresponding `TreeNode` operands until an opening parenthesis is found. Then, pop the opening parenthesis.
4. If the character is an operator (+, -, *, or /), pop the operators from the `ops` stack and process them with the corresponding operands until there is a lower precedence operator on the top or the stack is empty. Finally, push the current operator onto the `ops` stack.

After processing all characters in the input string `s`, process the remaining operators left in the `ops` stack.

The Shunting Yard algorithm guarantees that the resulting expression tree will have the correct precedence and associativity rules applied.

## A solution in C++

```cpp
class Solution {
public:
    struct TreeNode {
        char val;
        TreeNode* left;
        TreeNode* right;
        TreeNode(char x) : val(x), left(NULL), right(NULL) {}
    };

    TreeNode* expTree(string s) {
        stack<TreeNode*> nodes;
        stack<char> ops;
        for (int i = 0; i < s.size(); ++i) {
            if (isdigit(s[i])) {
                nodes.push(new TreeNode(s[i]));
            } else if (s[i] == '(') {
                ops.push(s[i]);
            } else if (s[i] == ')') {
                while (ops.top() != '(') {
                    process(nodes, ops);
                }
                ops.pop();
            } else {
                while (!ops.empty() && precedence(ops.top(), s[i])) {
                    process(nodes, ops);
                }
                ops.push(s[i]);
            }
        }
        while (!ops.empty()) {
            process(nodes, ops);
        }
        return nodes.top();
    }

    bool precedence(char a, char b) {
        if (a == '(') return false;
        if (b == '(' || b == ')') return true;
        if ((a == '*' || a == '/') && (b == '+' || b == '-')) return true;
        return false;
    }

    void process(stack<TreeNode*>& nodes, stack<char>& ops) {
        TreeNode* right = nodes.top(); nodes.pop();
        TreeNode* left = nodes.top(); nodes.pop();
        TreeNode* oper = new TreeNode(ops.top()); ops.pop();
        oper->left = left;
        oper->right = right;
        nodes.push(oper);
    }
};
```
This solution follows the algorithm of the well-known Shunting Yard algorithm. We process the input string `s` character by character.

1. If the character `s[i]` is a digit, create a `TreeNode` with the value and push it to the `nodes` stack.
2. If the character is an opening parenthesis, push it to the `ops` stack.
3. If the character is a closing parenthesis, pop the operators from the `ops` stack and process them with the corresponding `TreeNode` operands until an opening parenthesis is found. Then, pop the opening parenthesis.
4. If the character is an operator (+, -, *, or /), pop the operators from the `ops` stack and process them with the corresponding operands until there is a lower precedence operator on the top or the stack is empty. Finally, push the current operator onto the `ops` stack.

After processing all characters in the input string `s`, process the remaining operators left in the `ops` stack.

The Shunting Yard algorithm guarantees that the resulting expression tree will have the correct precedence and associativity rules applied.

## A solution in Python

```python
class Solution:
    def expTree(self, s: str) -> 'Node':
        def precedence(a, b):
            if a == '(':
                return False
            if b == '(' or b == ')':
                return True
            if (a in {'*', '/'}) and (b in {'+', '-'}):
                return True
            return False

        def process(nodes, ops):
            right = nodes.pop()
            left = nodes.pop()
            oper = Node(ops.pop())
            oper.left = left
            oper.right = right
            nodes.append(oper)

        nodes = []
        ops = []
        for i in s:
            if i.isdigit():
                nodes.append(Node(i))
            elif i == '(':
                ops.append(i)
            elif i == ')':
                while ops[-1] != '(':
                    process(nodes, ops)
                ops.pop()
            else:
                while ops and precedence(ops[-1], i):
                    process(nodes, ops)
                ops.append(i)
        while ops:
            process(nodes, ops)
        return nodes[0]
```
This solution follows the algorithm of the well-known Shunting Yard algorithm. We process the input string `s` character by character.

1. If the character `s[i]` is a digit, create a `TreeNode` with the value and push it to the `nodes` stack.
2. If the character is an opening parenthesis, push it to the `ops` stack.
3. If the character is a closing parenthesis, pop the operators from the `ops` stack and process them with the corresponding `TreeNode` operands until an opening parenthesis is found. Then, pop the opening parenthesis.
4. If the character is an operator (+, -, *, or /), pop the operators from the `ops` stack and process them with the corresponding operands until there is a lower precedence operator on the top or the stack is empty. Finally, push the current operator onto the `ops` stack.

After processing all characters in the input string `s`, process the remaining operators left in the `ops` stack.

The Shunting Yard algorithm guarantees that the resulting expression tree will have the correct precedence and associativity rules applied.

## A solution in Javascript

```javascript
var expTree = function(s) {
    function precedence(a, b) {
        if (a === '(') return false;
        if (b === '(' || b === ')') return true;
        if (('*/'.includes(a)) && ('+-'.includes(b))) return true;
        return false;
    }

    function process(nodes, ops) {
        const right = nodes.pop();
        const left = nodes.pop();
        const oper = new TreeNode(ops.pop());
        oper.left = left;
        oper.right = right;
        nodes.push(oper);
    }

    const nodes = [];
    const ops = [];
    for (let i = 0; i < s.length; ++i) {
        if (s[i] >= '0' && s[i] <= '9') {
            nodes.push(new TreeNode(s[i]));
        } else if (s[i] === '(') {
            ops.push(s[i]);
        } else if (s[i] === ')') {
            while (ops[ops.length - 1] !== '(') {
                process(nodes, ops);
            }
            ops.pop();
        } else {
            while (ops.length && precedence(ops[ops.length - 1], s[i])) {
                process(nodes, ops);
            }
            ops.push(s[i]);
        }
    }
    while (ops.length) {
        process(nodes, ops);
    }
    return nodes[0];
};
```
This solution follows the algorithm of the well-known Shunting Yard algorithm. We process the input string `s` character by character.

1. If the character `s[i]` is a digit, create a `TreeNode` with the value and push it to the `nodes` stack.
2. If the character is an opening parenthesis, push it to the `ops` stack.
3. If the character is a closing parenthesis, pop the operators from the `ops` stack and process them with the corresponding `TreeNode` operands until an opening parenthesis is found. Then, pop the opening parenthesis.
4. If the character is an operator (+, -, *, or /), pop the operators from the `ops` stack and process them with the corresponding operands until there is a lower precedence operator on the top or the stack is empty. Finally, push the current operator onto the `ops` stack.

After processing all characters in the input string `s`, process the remaining operators left in the `ops` stack.

The Shunting Yard algorithm guarantees that the resulting expression tree will have the correct precedence and associativity rules applied.


# Crawler Log Folder

- slug: crawler-log-folder
- difficulty: Easy

The Leetcode file system keeps a log each time some user performs a _change folder_ operation.

The operations are described below:

*   `"../ "` : Move to the parent folder of the current folder. (If you are already in the main folder, **remain in the same folder**).
*   `"./ "` : Remain in the same folder.
*   `"x/ "` : Move to the child folder named `x` (This folder is **guaranteed to always exist**).

You are given a list of strings `logs` where `logs[i]` is the operation performed by the user at the `ith` step.

The file system starts in the main folder, then the operations in `logs` are performed.

Return _the minimum number of operations needed to go back to the main folder after the change folder operations._

**Example 1:**

**Input:** logs = \[ "d1/ ", "d2/ ", "../ ", "d21/ ", "./ "\]
**Output:** 2
**Explanation:** Use this change folder operation  "../ " 2 times and go back to the main folder.

**Example 2:**

**Input:** logs = \[ "d1/ ", "d2/ ", "./ ", "d3/ ", "../ ", "d31/ "\]
**Output:** 3

**Example 3:**

**Input:** logs = \[ "d1/ ", "../ ", "../ ", "../ "\]
**Output:** 0

**Constraints:**

*   `1 <= logs.length <= 103`
*   `2 <= logs[i].length <= 10`
*   `logs[i]` contains lowercase English letters, digits, `'.'`, and `'/'`.
*   `logs[i]` follows the format described in the statement.
*   Folder names consist of lowercase English letters and digits.

## A solution in Java

```java
public int minOperations(String[] logs) {
    int depth = 0;
    for (String log : logs) {
        if (log.equals("../")) {
            depth = Math.max(0, depth - 1);
        } else if (!log.equals("./")) {
            depth += 1;
        }
    }
    return depth;
}
```
The algorithm iterates through each log entry, incrementing the `depth` variable whenever it encounters a non-relative move (`"x/"`). If it encounters a move to the parent directory (`"../"`) it decreases the `depth` variable by 1, but only if the depth is greater than 0 to make sure we don't go beyond the main folder. It ignores relative moves (`"./"`). Finally, it returns the number of operations needed to go back to the main folder, which is the final value of `depth`.

## A solution in C++

```cpp
int minOperations(vector<string>& logs) {
    int depth = 0;
    for (const string& log : logs) {
        if (log == "../") {
            depth = max(0, depth - 1);
        } else if (log != "./") {
            depth += 1;
        }
    }
    return depth;
}
```
The algorithm iterates through each log entry, incrementing the `depth` variable whenever it encounters a non-relative move (`"x/"`). If it encounters a move to the parent directory (`"../"`) it decreases the `depth` variable by 1, but only if the depth is greater than 0 to make sure we don't go beyond the main folder. It ignores relative moves (`"./"`). Finally, it returns the number of operations needed to go back to the main folder, which is the final value of `depth`.

## A solution in Python

```python
def minOperations(logs):
    depth = 0
    for log in logs:
        if log == "../":
            depth = max(0, depth - 1)
        elif log != "./":
            depth += 1
    return depth
```
The algorithm iterates through each log entry, incrementing the `depth` variable whenever it encounters a non-relative move (`"x/"`). If it encounters a move to the parent directory (`"../"`) it decreases the `depth` variable by 1, but only if the depth is greater than 0 to make sure we don't go beyond the main folder. It ignores relative moves (`"./"`). Finally, it returns the number of operations needed to go back to the main folder, which is the final value of `depth`.

## A solution in Javascript

```javascript
function minOperations(logs) {
    let depth = 0;
    for (const log of logs) {
        if (log === "../") {
            depth = Math.max(0, depth - 1);
        } else if (log !== "./") {
            depth += 1;
        }
    }
    return depth;
}
```
The algorithm iterates through each log entry, incrementing the `depth` variable whenever it encounters a non-relative move (`"x/"`). If it encounters a move to the parent directory (`"../"`) it decreases the `depth` variable by 1, but only if the depth is greater than 0 to make sure we don't go beyond the main folder. It ignores relative moves (`"./"`). Finally, it returns the number of operations needed to go back to the main folder, which is the final value of `depth`.


# Maximum Profit of Operating a Centennial Wheel

- slug: maximum-profit-of-operating-a-centennial-wheel
- difficulty: Medium

You are the operator of a Centennial Wheel that has **four gondolas**, and each gondola has room for **up** **to** **four people**. You have the ability to rotate the gondolas **counterclockwise**, which costs you `runningCost` dollars.

You are given an array `customers` of length `n` where `customers[i]` is the number of new customers arriving just before the `ith` rotation (0-indexed). This means you **must rotate the wheel** `i` **times before the** `customers[i]` **customers arrive**. **You cannot make customers wait if there is room in the gondola**. Each customer pays `boardingCost` dollars when they board on the gondola closest to the ground and will exit once that gondola reaches the ground again.

You can stop the wheel at any time, including **before** **serving** **all** **customers**. If you decide to stop serving customers, **all subsequent rotations are free** in order to get all the customers down safely. Note that if there are currently more than four customers waiting at the wheel, only four will board the gondola, and the rest will wait **for the next rotation**.

Return _the minimum number of rotations you need to perform to maximize your profit._ If there is **no scenario** where the profit is positive, return `-1`.

**Example 1:**

**Input:** customers = \[8,3\], boardingCost = 5, runningCost = 6
**Output:** 3
**Explanation:** The numbers written on the gondolas are the number of people currently there.
1. 8 customers arrive, 4 board and 4 wait for the next gondola, the wheel rotates. Current profit is 4 \* $5 - 1 \* $6 = $14.
2. 3 customers arrive, the 4 waiting board the wheel and the other 3 wait, the wheel rotates. Current profit is 8 \* $5 - 2 \* $6 = $28.
3. The final 3 customers board the gondola, the wheel rotates. Current profit is 11 \* $5 - 3 \* $6 = $37.
The highest profit was $37 after rotating the wheel 3 times.

**Example 2:**

**Input:** customers = \[10,9,6\], boardingCost = 6, runningCost = 4
**Output:** 7
**Explanation:**
1. 10 customers arrive, 4 board and 6 wait for the next gondola, the wheel rotates. Current profit is 4 \* $6 - 1 \* $4 = $20.
2. 9 customers arrive, 4 board and 11 wait (2 originally waiting, 9 newly waiting), the wheel rotates. Current profit is 8 \* $6 - 2 \* $4 = $40.
3. The final 6 customers arrive, 4 board and 13 wait, the wheel rotates. Current profit is 12 \* $6 - 3 \* $4 = $60.
4. 4 board and 9 wait, the wheel rotates. Current profit is 16 \* $6 - 4 \* $4 = $80.
5. 4 board and 5 wait, the wheel rotates. Current profit is 20 \* $6 - 5 \* $4 = $100.
6. 4 board and 1 waits, the wheel rotates. Current profit is 24 \* $6 - 6 \* $4 = $120.
7. 1 boards, the wheel rotates. Current profit is 25 \* $6 - 7 \* $4 = $122.
The highest profit was $122 after rotating the wheel 7 times.

**Example 3:**

**Input:** customers = \[3,4,0,5,1\], boardingCost = 1, runningCost = 92
**Output:** -1
**Explanation:**
1. 3 customers arrive, 3 board and 0 wait, the wheel rotates. Current profit is 3 \* $1 - 1 \* $92 = -$89.
2. 4 customers arrive, 4 board and 0 wait, the wheel rotates. Current profit is 7 \* $1 - 2 \* $92 = -$177.
3. 0 customers arrive, 0 board and 0 wait, the wheel rotates. Current profit is 7 \* $1 - 3 \* $92 = -$269.
4. 5 customers arrive, 4 board and 1 waits, the wheel rotates. Current profit is 11 \* $1 - 4 \* $92 = -$357.
5. 1 customer arrives, 2 board and 0 wait, the wheel rotates. Current profit is 13 \* $1 - 5 \* $92 = -$447.
The profit was never positive, so return -1.

**Constraints:**

*   `n == customers.length`
*   `1 <= n <= 105`
*   `0 <= customers[i] <= 50`
*   `1 <= boardingCost, runningCost <= 100`

## A solution in Java

```java
public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) {
    int waiting = 0;
    int profit = 0;
    int max_profit = 0;
    int rotations = 0;
    int result = -1;

    for (int i = 0; i < customers.length || waiting > 0; ++i) {
        if (i < customers.length) {
            waiting += customers[i];
        }
        int boarding = Math.min(waiting, 4);
        waiting -= boarding;
        profit += boarding * boardingCost - runningCost;

        if (profit > max_profit) {
            max_profit = profit;
            result = rotations + 1;
        }
        rotations++;
    }
    return result;
}
```
We will iterate through each rotation until there is no customer left in the customers array or no one waiting in line. In each iteration, we will first check if there are any customers arriving and update the waiting status accordingly. Then, decide how many customers to board and update the waiting status again. Afterward, we update the profit based on the number of customers boarded and runningCost. If the updated profit is greater than the current max_profit, we update the max_profit and result (number of rotations). Finally, we increment the rotation counter.

## A solution in C++

```cpp
int minOperationsMaxProfit(vector<int>& customers, int boardingCost, int runningCost) {
    int waiting = 0;
    int profit = 0;
    int max_profit = 0;
    int rotations = 0;
    int result = -1;

    for (int i = 0; i < customers.size() || waiting > 0; ++i) {
        if (i < customers.size()) {
            waiting += customers[i];
        }
        int boarding = min(waiting, 4);
        waiting -= boarding;
        profit += boarding * boardingCost - runningCost;

        if (profit > max_profit) {
            max_profit = profit;
            result = rotations + 1;
        }
        rotations++;
    }
    return result;
}
```
We will iterate through each rotation until there is no customer left in the customers array or no one waiting in line. In each iteration, we will first check if there are any customers arriving and update the waiting status accordingly. Then, decide how many customers to board and update the waiting status again. Afterward, we update the profit based on the number of customers boarded and runningCost. If the updated profit is greater than the current max_profit, we update the max_profit and result (number of rotations). Finally, we increment the rotation counter.

## A solution in Python

```python
def minOperationsMaxProfit(customers, boardingCost, runningCost):
    waiting = 0
    profit = 0
    max_profit = 0
    rotations = 0
    result = -1

    for i in range(len(customers) + sum(customers)):
        if i < len(customers):
            waiting += customers[i]
        boarding = min(waiting, 4)
        waiting -= boarding
        profit += boarding * boardingCost - runningCost

        if profit > max_profit:
            max_profit = profit
            result = rotations + 1
        rotations += 1

    return result
```
We will iterate through each rotation until there is no customer left in the customers array or no one waiting in line. In each iteration, we will first check if there are any customers arriving and update the waiting status accordingly. Then, decide how many customers to board and update the waiting status again. Afterward, we update the profit based on the number of customers boarded and runningCost. If the updated profit is greater than the current max_profit, we update the max_profit and result (number of rotations). Finally, we increment the rotation counter.

## A solution in Javascript

```javascript
function minOperationsMaxProfit(customers, boardingCost, runningCost) {
    let waiting = 0;
    let profit = 0;
    let max_profit = 0;
    let rotations = 0;
    let result = -1;

    for (let i = 0; i < customers.length || waiting > 0; ++i) {
        if (i < customers.length) {
            waiting += customers[i];
        }
        const boarding = Math.min(waiting, 4);
        waiting -= boarding;
        profit += boarding * boardingCost - runningCost;

        if (profit > max_profit) {
            max_profit = profit;
            result = rotations + 1;
        }
        rotations++;
    }
    return result;
}
```
We will iterate through each rotation until there is no customer left in the customers array or no one waiting in line. In each iteration, we will first check if there are any customers arriving and update the waiting status accordingly. Then, decide how many customers to board and update the waiting status again. Afterward, we update the profit based on the number of customers boarded and runningCost. If the updated profit is greater than the current max_profit, we update the max_profit and result (number of rotations). Finally, we increment the rotation counter.


# Throne Inheritance

- slug: throne-inheritance
- difficulty: Medium

A kingdom consists of a king, his children, his grandchildren, and so on. Every once in a while, someone in the family dies or a child is born.

The kingdom has a well-defined order of inheritance that consists of the king as the first member. Let's define the recursive function `Successor(x, curOrder)`, which given a person `x` and the inheritance order so far, returns who should be the next person after `x` in the order of inheritance.

Successor(x, curOrder):
    if x has no children or all of x's children are in curOrder:
        if x is the king return null
        else return Successor(x's parent, curOrder)
    else return x's oldest child who's not in curOrder

For example, assume we have a kingdom that consists of the king, his children Alice and Bob (Alice is older than Bob), and finally Alice's son Jack.

1.  In the beginning, `curOrder` will be `[ "king "]`.
2.  Calling `Successor(king, curOrder)` will return Alice, so we append to `curOrder` to get `[ "king ", "Alice "]`.
3.  Calling `Successor(Alice, curOrder)` will return Jack, so we append to `curOrder` to get `[ "king ", "Alice ", "Jack "]`.
4.  Calling `Successor(Jack, curOrder)` will return Bob, so we append to `curOrder` to get `[ "king ", "Alice ", "Jack ", "Bob "]`.
5.  Calling `Successor(Bob, curOrder)` will return `null`. Thus the order of inheritance will be `[ "king ", "Alice ", "Jack ", "Bob "]`.

Using the above function, we can always obtain a unique order of inheritance.

Implement the `ThroneInheritance` class:

*   `ThroneInheritance(string kingName)` Initializes an object of the `ThroneInheritance` class. The name of the king is given as part of the constructor.
*   `void birth(string parentName, string childName)` Indicates that `parentName` gave birth to `childName`.
*   `void death(string name)` Indicates the death of `name`. The death of the person doesn't affect the `Successor` function nor the current inheritance order. You can treat it as just marking the person as dead.
*   `string[] getInheritanceOrder()` Returns a list representing the current order of inheritance **excluding** dead people.

**Example 1:**

**Input**
\[ "ThroneInheritance ",  "birth ",  "birth ",  "birth ",  "birth ",  "birth ",  "birth ",  "getInheritanceOrder ",  "death ",  "getInheritanceOrder "\]
\[\[ "king "\], \[ "king ",  "andy "\], \[ "king ",  "bob "\], \[ "king ",  "catherine "\], \[ "andy ",  "matthew "\], \[ "bob ",  "alex "\], \[ "bob ",  "asha "\], \[null\], \[ "bob "\], \[null\]\]
**Output**
\[null, null, null, null, null, null, null, \[ "king ",  "andy ",  "matthew ",  "bob ",  "alex ",  "asha ",  "catherine "\], null, \[ "king ",  "andy ",  "matthew ",  "alex ",  "asha ",  "catherine "\]\]

**Explanation**
ThroneInheritance t= new ThroneInheritance( "king "); // order: **king**
t.birth( "king ",  "andy "); // order: king > **andy**
t.birth( "king ",  "bob "); // order: king > andy > **bob**
t.birth( "king ",  "catherine "); // order: king > andy > bob > **catherine**
t.birth( "andy ",  "matthew "); // order: king > andy > **matthew** > bob > catherine
t.birth( "bob ",  "alex "); // order: king > andy > matthew > bob > **alex** > catherine
t.birth( "bob ",  "asha "); // order: king > andy > matthew > bob > alex > **asha** > catherine
t.getInheritanceOrder(); // return \[ "king ",  "andy ",  "matthew ",  "bob ",  "alex ",  "asha ",  "catherine "\]
t.death( "bob "); // order: king > andy > matthew > **bob** > alex > asha > catherine
t.getInheritanceOrder(); // return \[ "king ",  "andy ",  "matthew ",  "alex ",  "asha ",  "catherine "\]

**Constraints:**

*   `1 <= kingName.length, parentName.length, childName.length, name.length <= 15`
*   `kingName`, `parentName`, `childName`, and `name` consist of lowercase English letters only.
*   All arguments `childName` and `kingName` are **distinct**.
*   All `name` arguments of `death` will be passed to either the constructor or as `childName` to `birth` first.
*   For each call to `birth(parentName, childName)`, it is guaranteed that `parentName` is alive.
*   At most `105` calls will be made to `birth` and `death`.
*   At most `10` calls will be made to `getInheritanceOrder`.

## A solution in Java

```java
import java.util.*;

class ThroneInheritance {
    private String king;
    private Map<String, List<String>> family;
    private Set<String> dead;

    public ThroneInheritance(String kingName) {
        king = kingName;
        family = new HashMap<>();
        dead = new HashSet<>();
    }

    public void birth(String parentName, String childName) {
        family.putIfAbsent(parentName, new ArrayList<>());
        family.get(parentName).add(childName);
    }

    public void death(String name) {
        dead.add(name);
    }

    public List<String> getInheritanceOrder() {
        List<String> order = new ArrayList<>();
        dfs(king, order);
        return order;
    }

    private void dfs(String name, List<String> order) {
        if (!dead.contains(name)) {
            order.add(name);
        }
        List<String> children = family.get(name);
        if (children != null) {
            for (String child : children) {
                dfs(child, order);
            }
        }
    }
}
```
The algorithm maintains a hashmap `family`, a set `dead` and the `king`'s name.
* `family` stores the parent-child relationships.
* `dead` stores the names of dead people.
* `king` stores the name of the king.

`birth()` method is used to add the childName to the parentName list of children in the hashmap `family`.

`death()` method is used to mark the person as dead by adding the name to the set `dead`.

`getInheritanceOrder()` method traverses the family members using Depth First Search(DFS) while skipping the dead people. Order of inheritance is retrieved by DFS as it explores the children in order.

## A solution in C++

```cpp
#include <unordered_map>
#include <vector>
#include <string>
#include <set>
using namespace std;

class ThroneInheritance {
public:
    ThroneInheritance(string kingName) : king(kingName) {}

    void birth(string parentName, string childName) {
        family[parentName].push_back(childName);
    }

    void death(string name) {
        dead.insert(name);
    }

    vector<string> getInheritanceOrder() {
        vector<string> order;
        dfs(king, order);
        return order;
    }

private:
    void dfs(string name, vector<string>& order) {
        if (!dead.count(name)) {
            order.push_back(name);
        }
        for (const auto& child : family[name]) {
            dfs(child, order);
        }
    }

    string king;
    unordered_map<string, vector<string>> family;
    set<string> dead;
};
```
The algorithm maintains a hashmap `family`, a set `dead` and the `king`'s name.
* `family` stores the parent-child relationships.
* `dead` stores the names of dead people.
* `king` stores the name of the king.

`birth()` method is used to add the childName to the parentName list of children in the hashmap `family`.

`death()` method is used to mark the person as dead by adding the name to the set `dead`.

`getInheritanceOrder()` method traverses the family members using Depth First Search(DFS) while skipping the dead people. Order of inheritance is retrieved by DFS as it explores the children in order.

## A solution in Python

```python
class ThroneInheritance:

    def __init__(self, kingName: str):
        self.king = kingName
        self.family = {}
        self.dead = set()

    def birth(self, parentName: str, childName: str) -> None:
        if parentName not in self.family:
            self.family[parentName] = []
        self.family[parentName].append(childName)

    def death(self, name: str) -> None:
        self.dead.add(name)

    def getInheritanceOrder(self) -> List[str]:
        order = []
        self.dfs(self.king, order)
        return order

    def dfs(self, name: str, order: List[str]) -> None:
        if name not in self.dead:
            order.append(name)
        if name in self.family:
            for child in self.family[name]:
                self.dfs(child, order)
```
The algorithm maintains a hashmap `family`, a set `dead` and the `king`'s name.
* `family` stores the parent-child relationships.
* `dead` stores the names of dead people.
* `king` stores the name of the king.

`birth()` method is used to add the childName to the parentName list of children in the hashmap `family`.

`death()` method is used to mark the person as dead by adding the name to the set `dead`.

`getInheritanceOrder()` method traverses the family members using Depth First Search(DFS) while skipping the dead people. Order of inheritance is retrieved by DFS as it explores the children in order.

## A solution in Javascript

```javascript
class ThroneInheritance {
    constructor(kingName) {
        this.king = kingName;
        this.family = new Map();
        this.dead = new Set();
    }

    birth(parentName, childName) {
        if (!this.family.has(parentName)) {
            this.family.set(parentName, []);
        }
        this.family.get(parentName).push(childName);
    }

    death(name) {
        this.dead.add(name);
    }

    getInheritanceOrder() {
        const order = [];
        this.dfs(this.king, order);
        return order;
    }

    dfs(name, order) {
        if (!this.dead.has(name)) {
            order.push(name);
        }
        const children = this.family.get(name);
        if (children) {
            for (const child of children) {
                this.dfs(child, order);
            }
        }
    }
}
```
The algorithm maintains a hashmap `family`, a set `dead` and the `king`'s name.
* `family` stores the parent-child relationships.
* `dead` stores the names of dead people.
* `king` stores the name of the king.

`birth()` method is used to add the childName to the parentName list of children in the hashmap `family`.

`death()` method is used to mark the person as dead by adding the name to the set `dead`.

`getInheritanceOrder()` method traverses the family members using Depth First Search(DFS) while skipping the dead people. Order of inheritance is retrieved by DFS as it explores the children in order.


# Maximum Number of Achievable Transfer Requests

- slug: maximum-number-of-achievable-transfer-requests
- difficulty: Hard

We have `n` buildings numbered from `0` to `n - 1`. Each building has a number of employees. It's transfer season, and some employees want to change the building they reside in.

You are given an array `requests` where `requests[i] = [fromi, toi]` represents an employee's request to transfer from building `fromi` to building `toi`.

**All buildings are full**, so a list of requests is achievable only if for each building, the **net change in employee transfers is zero**. This means the number of employees **leaving** is **equal** to the number of employees **moving in**. For example if `n = 3` and two employees are leaving building `0`, one is leaving building `1`, and one is leaving building `2`, there should be two employees moving to building `0`, one employee moving to building `1`, and one employee moving to building `2`.

Return _the maximum number of achievable requests_.

**Example 1:**

**Input:** n = 5, requests = \[\[0,1\],\[1,0\],\[0,1\],\[1,2\],\[2,0\],\[3,4\]\]
**Output:** 5
**Explantion:** Let's see the requests:
From building 0 we have employees x and y and both want to move to building 1.
From building 1 we have employees a and b and they want to move to buildings 2 and 0 respectively.
From building 2 we have employee z and they want to move to building 0.
From building 3 we have employee c and they want to move to building 4.
From building 4 we don't have any requests.
We can achieve the requests of users x and b by swapping their places.
We can achieve the requests of users y, a and z by swapping the places in the 3 buildings.

**Example 2:**

**Input:** n = 3, requests = \[\[0,0\],\[1,2\],\[2,1\]\]
**Output:** 3
**Explantion:** Let's see the requests:
From building 0 we have employee x and they want to stay in the same building 0.
From building 1 we have employee y and they want to move to building 2.
From building 2 we have employee z and they want to move to building 1.
We can achieve all the requests.

**Example 3:**

**Input:** n = 4, requests = \[\[0,3\],\[3,1\],\[1,2\],\[2,0\]\]
**Output:** 4

**Constraints:**

*   `1 <= n <= 20`
*   `1 <= requests.length <= 16`
*   `requests[i].length == 2`
*   `0 <= fromi, toi < n`

## A solution in Java

```java
import java.util.List;

public int maximumRequests(int n, List<List<Integer>> requests) {
    int req_size = requests.size();
    int max_requests = 0;

    for (int i = 0; i < (1 << req_size); ++i) {
        int[] net_transfers = new int[n];
        int count = 0;

        for (int j = 0; j < req_size; ++j) {
            if ((i & (1 << j)) != 0) {
                net_transfers[requests.get(j).get(0)]--;
                net_transfers[requests.get(j).get(1)]++;
                count++;
            }
        }

        boolean valid = true;
        for (int val : net_transfers) {
            if (val != 0) {
                valid = false;
                break;
            }
        }

        if (valid)
            max_requests = Math.max(max_requests, count);
    }

    return max_requests;
}
```
To solve this problem, we need to iterate through all the possible combinations of employee requests, and for each combination, we check if it satisfies the building transfer constraints where the net change of employees to every building is 0. Here we use a bit manipulation technique to represent different subsets.

We start by iterating over all integers from 0 to 2^requests.length. For each such integer, we iterate over each bit and, if it is set, include the corresponding request from the list of requests. Then, we calculate the net employee changes in each building based on this subset of requests. If after updating the net employee changes, all the entries in the building change array are still 0, it means the current subset of requests meets the requirements.

We then update the maximum number of achievable requests if the current count of requests is greater than the previous maximum one. We return the maximum achievable number of requests after checking all sets of requests.

The time complexity of this solution is O(2^R * (R + N)), where R is requests.length and N is the number of buildings.

## A solution in C++

```cpp
#include <vector>

int maximumRequests(int n, std::vector<std::vector<int>>& requests) {
    int req_size = requests.size();
    int max_requests = 0;

    for (int i = 0; i < (1 << req_size); ++i) {
        std::vector<int> net_transfers(n, 0);
        int count = 0;

        for (int j = 0; j < req_size; ++j) {
            if (i & (1 << j)) {
                net_transfers[requests[j][0]]--;
                net_transfers[requests[j][1]]++;
                count++;
            }
        }

        bool valid = true;
        for (int val : net_transfers) {
            if (val) {
                valid = false;
                break;
            }
        }

        if (valid)
            max_requests = std::max(max_requests, count);
    }

    return max_requests;
}
```
To solve this problem, we need to iterate through all the possible combinations of employee requests, and for each combination, we check if it satisfies the building transfer constraints where the net change of employees to every building is 0. Here we use a bit manipulation technique to represent different subsets.

We start by iterating over all integers from 0 to 2^requests.length. For each such integer, we iterate over each bit and, if it is set, include the corresponding request from the list of requests. Then, we calculate the net employee changes in each building based on this subset of requests. If after updating the net employee changes, all the entries in the building change array are still 0, it means the current subset of requests meets the requirements.

We then update the maximum number of achievable requests if the current count of requests is greater than the previous maximum one. We return the maximum achievable number of requests after checking all sets of requests.

The time complexity of this solution is O(2^R * (R + N)), where R is requests.length and N is the number of buildings.

## A solution in Python

```python
def maximumRequests(n, requests):
    req_size = len(requests)
    max_requests = 0

    for i in range(1 << req_size):
        net_transfers = [0] * n
        count = 0

        for j in range(req_size):
            if i & (1 << j):
                net_transfers[requests[j][0]] -= 1
                net_transfers[requests[j][1]] += 1
                count += 1

        valid = all(val == 0 for val in net_transfers)

        if valid:
            max_requests = max(max_requests, count)

    return max_requests
```
To solve this problem, we need to iterate through all the possible combinations of employee requests, and for each combination, we check if it satisfies the building transfer constraints where the net change of employees to every building is 0. Here we use a bit manipulation technique to represent different subsets.

We start by iterating over all integers from 0 to 2^requests.length. For each such integer, we iterate over each bit and, if it is set, include the corresponding request from the list of requests. Then, we calculate the net employee changes in each building based on this subset of requests. If after updating the net employee changes, all the entries in the building change array are still 0, it means the current subset of requests meets the requirements.

We then update the maximum number of achievable requests if the current count of requests is greater than the previous maximum one. We return the maximum achievable number of requests after checking all sets of requests.

The time complexity of this solution is O(2^R * (R + N)), where R is requests.length and N is the number of buildings.

## A solution in Javascript

```javascript
function maximumRequests(n, requests) {
    const req_size = requests.length;
    let max_requests = 0;

    for (let i = 0; i < (1 << req_size); ++i) {
        const net_transfers = new Array(n).fill(0);
        let count = 0;

        for (let j = 0; j < req_size; ++j) {
            if (i & (1 << j)) {
                net_transfers[requests[j][0]]--;
                net_transfers[requests[j][1]]++;
                count++;
            }
        }

        const valid = net_transfers.every(val => val === 0);

        if (valid) {
            max_requests = Math.max(max_requests, count);
        }
    }

    return max_requests;
}
```
To solve this problem, we need to iterate through all the possible combinations of employee requests, and for each combination, we check if it satisfies the building transfer constraints where the net change of employees to every building is 0. Here we use a bit manipulation technique to represent different subsets.

We start by iterating over all integers from 0 to 2^requests.length. For each such integer, we iterate over each bit and, if it is set, include the corresponding request from the list of requests. Then, we calculate the net employee changes in each building based on this subset of requests. If after updating the net employee changes, all the entries in the building change array are still 0, it means the current subset of requests meets the requirements.

We then update the maximum number of achievable requests if the current count of requests is greater than the previous maximum one. We return the maximum achievable number of requests after checking all sets of requests.

The time complexity of this solution is O(2^R * (R + N)), where R is requests.length and N is the number of buildings.


# Find Nearest Right Node in Binary Tree

- slug: find-nearest-right-node-in-binary-tree
- difficulty: Medium

Given the `root` of a binary tree and a node `u` in the tree, return _the **nearest** node on the **same level** that is to the **right** of_ `u`_, or return_ `null` _if_ `u` _is the rightmost node in its level_.

**Example 1:**

**Input:** root = \[1,2,3,null,4,5,6\], u = 4
**Output:** 5
**Explanation:** The nearest node on the same level to the right of node 4 is node 5.

**Example 2:**

**Input:** root = \[3,null,4,2\], u = 2
**Output:** null
**Explanation:** There are no nodes to the right of 2.

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 105]`.
*   `1 <= Node.val <= 105`
*   All values in the tree are **distinct**.
*   `u` is a node in the binary tree rooted at `root`.

## A solution in Java

```java
import java.util.Queue;
import java.util.LinkedList;

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode() {}
    TreeNode(int val) { this.val = val; }
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public TreeNode findNearestRightNode(TreeNode root, TreeNode u) {
    if (root == null) return null;

    Queue<TreeNode> q = new LinkedList<>();
    q.add(root);

    while (!q.isEmpty()) {
        int n = q.size();

        for (int i = 0; i < n; i++) {
            TreeNode current = q.poll();

            if (current == u) {
                return i < n - 1 ? q.peek() : null;
            }

            if (current.left != null) q.add(current.left);
            if (current.right != null) q.add(current.right);
        }
    }

    return null;
}
```
The algorithm is based on level-order traversal (breadth-first search). We use a queue to traverse the tree nodes level by level.

1. We first check if the root is not null, otherwise, return null.
2. Initialize an empty queue and push the root node into it.
3. While the queue is not empty, we start a loop:
   1. Store the current size of the queue (n).
   2. Loop through the nodes in the current level (from 0 to n).
      1. Pop the front node from the queue (current).
      2. Check if this node is equal to the target node (u).
         1. If yes, return the next node in the queue if the current node is not the last node in the level. Otherwise, return null.
      3. If the current node has any left and/or right child, push them into the queue.
4. If we finished traversing the tree and didn't find any nearest node, return null.

## A solution in C++

```cpp
#include <queue>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

TreeNode* findNearestRightNode(TreeNode* root, TreeNode* u) {
    if (!root) return nullptr;

    std::queue<TreeNode*> q;
    q.push(root);

    while (!q.empty()) {
        int n = q.size();

        for (int i = 0; i < n; i++) {
            TreeNode* current = q.front();
            q.pop();

            if (current == u) {
                return i < n - 1 ? q.front() : nullptr;
            }

            if (current->left) q.push(current->left);
            if (current->right) q.push(current->right);
        }
    }

    return nullptr;
}
```
The algorithm is based on level-order traversal (breadth-first search). We use a queue to traverse the tree nodes level by level.

1. We first check if the root is not null, otherwise, return null.
2. Initialize an empty queue and push the root node into it.
3. While the queue is not empty, we start a loop:
   1. Store the current size of the queue (n).
   2. Loop through the nodes in the current level (from 0 to n).
      1. Pop the front node from the queue (current).
      2. Check if this node is equal to the target node (u).
         1. If yes, return the next node in the queue if the current node is not the last node in the level. Otherwise, return null.
      3. If the current node has any left and/or right child, push them into the queue.
4. If we finished traversing the tree and didn't find any nearest node, return null.

## A solution in Python

```python
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def find_nearest_right_node(root, u):
    if not root:
        return None

    q = [root]

    while q:
        n = len(q)

        for i in range(n):
            current = q.pop(0)

            if current == u:
                return q[0] if i < n - 1 else None

            if current.left:
                q.append(current.left)
            if current.right:
                q.append(current.right)

    return None
```
The algorithm is based on level-order traversal (breadth-first search). We use a queue to traverse the tree nodes level by level.

1. We first check if the root is not null, otherwise, return null.
2. Initialize an empty queue and push the root node into it.
3. While the queue is not empty, we start a loop:
   1. Store the current size of the queue (n).
   2. Loop through the nodes in the current level (from 0 to n).
      1. Pop the front node from the queue (current).
      2. Check if this node is equal to the target node (u).
         1. If yes, return the next node in the queue if the current node is not the last node in the level. Otherwise, return null.
      3. If the current node has any left and/or right child, push them into the queue.
4. If we finished traversing the tree and didn't find any nearest node, return null.

## A solution in Javascript

```javascript
class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

function findNearestRightNode(root, u) {
  if (!root) return null;

  const q = [root];

  while (q.length > 0) {
    const n = q.length;

    for (let i = 0; i < n; i++) {
      const current = q.shift();

      if (current === u) {
        return i < n - 1 ? q[0] : null;
      }

      if (current.left) q.push(current.left);
      if (current.right) q.push(current.right);
    }
  }

  return null;
}
```
The algorithm is based on level-order traversal (breadth-first search). We use a queue to traverse the tree nodes level by level.

1. We first check if the root is not null, otherwise, return null.
2. Initialize an empty queue and push the root node into it.
3. While the queue is not empty, we start a loop:
   1. Store the current size of the queue (n).
   2. Loop through the nodes in the current level (from 0 to n).
      1. Pop the front node from the queue (current).
      2. Check if this node is equal to the target node (u).
         1. If yes, return the next node in the queue if the current node is not the last node in the level. Otherwise, return null.
      3. If the current node has any left and/or right child, push them into the queue.
4. If we finished traversing the tree and didn't find any nearest node, return null.


# Design Parking System

- slug: design-parking-system
- difficulty: Easy

Design a parking system for a parking lot. The parking lot has three kinds of parking spaces: big, medium, and small, with a fixed number of slots for each size.

Implement the `ParkingSystem` class:

*   `ParkingSystem(int big, int medium, int small)` Initializes object of the `ParkingSystem` class. The number of slots for each parking space are given as part of the constructor.
*   `bool addCar(int carType)` Checks whether there is a parking space of `carType` for the car that wants to get into the parking lot. `carType` can be of three kinds: big, medium, or small, which are represented by `1`, `2`, and `3` respectively. **A car can only park in a parking space of its** `carType`. If there is no space available, return `false`, else park the car in that size space and return `true`.

**Example 1:**

**Input**
\[ "ParkingSystem ",  "addCar ",  "addCar ",  "addCar ",  "addCar "\]
\[\[1, 1, 0\], \[1\], \[2\], \[3\], \[1\]\]
**Output**
\[null, true, true, false, false\]

**Explanation**
ParkingSystem parkingSystem = new ParkingSystem(1, 1, 0);
parkingSystem.addCar(1); // return true because there is 1 available slot for a big car
parkingSystem.addCar(2); // return true because there is 1 available slot for a medium car
parkingSystem.addCar(3); // return false because there is no available slot for a small car
parkingSystem.addCar(1); // return false because there is no available slot for a big car. It is already occupied.

**Constraints:**

*   `0 <= big, medium, small <= 1000`
*   `carType` is `1`, `2`, or `3`
*   At most `1000` calls will be made to `addCar`

## A solution in Java

```java
public int[] runningSum(int[] nums) {
    for (int i = 1; i < nums.length; i++) {
        nums[i] += nums[i - 1];
    }
    return nums;
}
```
The algorithm iterates over the input array starting from the second element (i = 1). In each iteration, it adds the (i-1)-th element to the i-th element of the array (nums[i] += nums[i-1]).

This operation computes the running sum of the array by essentially summing up every previous element with the current element. This is an in-place operation, and the modified input array is returned as output.

The time complexity of this algorithm is O(n), where n is the length of the input array, as the loop iterates once over each of the n elements in the array. The space complexity is O(1), since it only modifies the input array in-place and requires no additional memory.

## A solution in C++

```cpp
vector<int> runningSum(vector<int>& nums) {
    for (int i = 1; i < nums.size(); i++) {
        nums[i] += nums[i - 1];
    }
    return nums;
}
```
The algorithm iterates over the input array starting from the second element (i = 1). In each iteration, it adds the (i-1)-th element to the i-th element of the array (nums[i] += nums[i-1]).

This operation computes the running sum of the array by essentially summing up every previous element with the current element. This is an in-place operation, and the modified input array is returned as output.

The time complexity of this algorithm is O(n), where n is the length of the input array, as the loop iterates once over each of the n elements in the array. The space complexity is O(1), since it only modifies the input array in-place and requires no additional memory.

## A solution in Python

```python
def runningSum(nums):
    for i in range(1, len(nums)):
        nums[i] += nums[i - 1]
    return nums
```
The algorithm iterates over the input array starting from the second element (i = 1). In each iteration, it adds the (i-1)-th element to the i-th element of the array (nums[i] += nums[i-1]).

This operation computes the running sum of the array by essentially summing up every previous element with the current element. This is an in-place operation, and the modified input array is returned as output.

The time complexity of this algorithm is O(n), where n is the length of the input array, as the loop iterates once over each of the n elements in the array. The space complexity is O(1), since it only modifies the input array in-place and requires no additional memory.

## A solution in Javascript

```javascript
function runningSum(nums) {
    for (let i = 1; i < nums.length; i++) {
        nums[i] += nums[i - 1];
    }
    return nums;
}
```
The algorithm iterates over the input array starting from the second element (i = 1). In each iteration, it adds the (i-1)-th element to the i-th element of the array (nums[i] += nums[i-1]).

This operation computes the running sum of the array by essentially summing up every previous element with the current element. This is an in-place operation, and the modified input array is returned as output.

The time complexity of this algorithm is O(n), where n is the length of the input array, as the loop iterates once over each of the n elements in the array. The space complexity is O(1), since it only modifies the input array in-place and requires no additional memory.


# Alert Using Same Key-Card Three or More Times in a One Hour Period

- slug: alert-using-same-key-card-three-or-more-times-in-a-one-hour-period
- difficulty: Medium

LeetCode company workers use key-cards to unlock office doors. Each time a worker uses their key-card, the security system saves the worker's name and the time when it was used. The system emits an **alert** if any worker uses the key-card **three or more times** in a one-hour period.

You are given a list of strings `keyName` and `keyTime` where `[keyName[i], keyTime[i]]` corresponds to a person's name and the time when their key-card was used **in a** **single day**.

Access times are given in the **24-hour time format "HH:MM "**, such as `"23:51 "` and `"09:49 "`.

Return a _list of unique worker names who received an alert for frequent keycard use_. Sort the names in **ascending order alphabetically**.

Notice that `"10:00 "` - `"11:00 "` is considered to be within a one-hour period, while `"22:51 "` - `"23:52 "` is not considered to be within a one-hour period.

**Example 1:**

**Input:** keyName = \[ "daniel ", "daniel ", "daniel ", "luis ", "luis ", "luis ", "luis "\], keyTime = \[ "10:00 ", "10:40 ", "11:00 ", "09:00 ", "11:00 ", "13:00 ", "15:00 "\]
**Output:** \[ "daniel "\]
**Explanation:**  "daniel " used the keycard 3 times in a one-hour period ( "10:00 ", "10:40 ",  "11:00 ").

**Example 2:**

**Input:** keyName = \[ "alice ", "alice ", "alice ", "bob ", "bob ", "bob ", "bob "\], keyTime = \[ "12:01 ", "12:00 ", "18:00 ", "21:00 ", "21:20 ", "21:30 ", "23:00 "\]
**Output:** \[ "bob "\]
**Explanation:**  "bob " used the keycard 3 times in a one-hour period ( "21:00 ", "21:20 ",  "21:30 ").

**Constraints:**

*   `1 <= keyName.length, keyTime.length <= 105`
*   `keyName.length == keyTime.length`
*   `keyTime[i]` is in the format **"HH:MM "**.
*   `[keyName[i], keyTime[i]]` is **unique**.
*   `1 <= keyName[i].length <= 10`
*   `keyName[i] contains only lowercase English letters.`

## A solution in Java

```java
import java.util.HashMap;
import java.util.PriorityQueue;

public int findLeastNumOfUniqueInts(int[] arr, int k) {
    HashMap<Integer, Integer> freqMap = new HashMap<>();
    for (int n : arr) {
        freqMap.put(n, freqMap.getOrDefault(n, 0) + 1);
    }

    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    for (int count : freqMap.values()) {
        minHeap.offer(count);
    }

    while (k > 0) {
        k -= minHeap.poll();
    }

    return k == 0 ? minHeap.size() : minHeap.size() + 1;
}
```
The algorithm works as follows:
1. Create a frequency map for the given array of integers. This is a map where keys are the integers in the array and values are their frequency counts.
2. Create a min-heap (priority queue) from the frequency map's values.
3. While k (the number of elements to remove) is greater than 0, keep popping elements from the min-heap (which will be the one with the least frequency) and decrement the value of k by that frequency. This step simulates removing k elements.
4. If k turns out to be zero, return the size of the min-heap as the least number of unique integers. If k becomes negative (i.e., k != 0), return the size of the min-heap plus 1 as the answer.

The algorithm has a time complexity of O(n + mlogm), where n is the size of the input array, and m is the number of unique integers in it. The space complexity is also O(m) due to the frequency map and the min-heap.

## A solution in C++

```cpp
#include <vector>
#include <unordered_map>
#include <queue>
#include <algorithm>

int findLeastNumOfUniqueInts(std::vector<int> &arr, int k) {
    std::unordered_map<int, int> freqMap;
    for(int n : arr) {
        freqMap[n]++;
    }

    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;
    for (const auto &it : freqMap) {
        minHeap.push(it.second);
    }

    while (k > 0) {
        k -= minHeap.top();
        minHeap.pop();
    }

    return k == 0 ? minHeap.size() : minHeap.size() + 1;
}
```
The algorithm works as follows:
1. Create a frequency map for the given array of integers. This is a map where keys are the integers in the array and values are their frequency counts.
2. Create a min-heap (priority queue) from the frequency map's values.
3. While k (the number of elements to remove) is greater than 0, keep popping elements from the min-heap (which will be the one with the least frequency) and decrement the value of k by that frequency. This step simulates removing k elements.
4. If k turns out to be zero, return the size of the min-heap as the least number of unique integers. If k becomes negative (i.e., k != 0), return the size of the min-heap plus 1 as the answer.

The algorithm has a time complexity of O(n + mlogm), where n is the size of the input array, and m is the number of unique integers in it. The space complexity is also O(m) due to the frequency map and the min-heap.

## A solution in Python

```python
import heapq
from collections import Counter

def find_least_num_of_unique_ints(arr, k):
    freq_map = Counter(arr)
    min_heap = list(freq_map.values())
    heapq.heapify(min_heap)

    while k > 0:
        k -= heapq.heappop(min_heap)

    return len(min_heap) if k == 0 else len(min_heap) + 1
```
The algorithm works as follows:
1. Create a frequency map for the given array of integers. This is a map where keys are the integers in the array and values are their frequency counts.
2. Create a min-heap (priority queue) from the frequency map's values.
3. While k (the number of elements to remove) is greater than 0, keep popping elements from the min-heap (which will be the one with the least frequency) and decrement the value of k by that frequency. This step simulates removing k elements.
4. If k turns out to be zero, return the size of the min-heap as the least number of unique integers. If k becomes negative (i.e., k != 0), return the size of the min-heap plus 1 as the answer.

The algorithm has a time complexity of O(n + mlogm), where n is the size of the input array, and m is the number of unique integers in it. The space complexity is also O(m) due to the frequency map and the min-heap.

## A solution in Javascript

```javascript
function findLeastNumOfUniqueInts(arr, k) {
    let freqMap = {};
    for (let n of arr) {
        freqMap[n] = (freqMap[n] || 0) + 1;
    }

    let minHeap = Object.values(freqMap).sort((a, b) => a - b);

    while (k > 0) {
        k -= minHeap.shift();
    }

    return k === 0 ? minHeap.length : minHeap.length + 1;
}
```
The algorithm works as follows:
1. Create a frequency map for the given array of integers. This is a map where keys are the integers in the array and values are their frequency counts.
2. Create a min-heap (priority queue) from the frequency map's values.
3. While k (the number of elements to remove) is greater than 0, keep popping elements from the min-heap (which will be the one with the least frequency) and decrement the value of k by that frequency. This step simulates removing k elements.
4. If k turns out to be zero, return the size of the min-heap as the least number of unique integers. If k becomes negative (i.e., k != 0), return the size of the min-heap plus 1 as the answer.

The algorithm has a time complexity of O(n + mlogm), where n is the size of the input array, and m is the number of unique integers in it. The space complexity is also O(m) due to the frequency map and the min-heap.


# Find Valid Matrix Given Row and Column Sums

- slug: find-valid-matrix-given-row-and-column-sums
- difficulty: Medium

You are given two arrays `rowSum` and `colSum` of non-negative integers where `rowSum[i]` is the sum of the elements in the `ith` row and `colSum[j]` is the sum of the elements of the `jth` column of a 2D matrix. In other words, you do not know the elements of the matrix, but you do know the sums of each row and column.

Find any matrix of **non-negative** integers of size `rowSum.length x colSum.length` that satisfies the `rowSum` and `colSum` requirements.

Return _a 2D array representing **any** matrix that fulfills the requirements_. It's guaranteed that **at least one** matrix that fulfills the requirements exists.

**Example 1:**

**Input:** rowSum = \[3,8\], colSum = \[4,7\]
**Output:** \[\[3,0\],
         \[1,7\]\]
**Explanation:**
0th row: 3 + 0 = 3 == rowSum\[0\]
1st row: 1 + 7 = 8 == rowSum\[1\]
0th column: 3 + 1 = 4 == colSum\[0\]
1st column: 0 + 7 = 7 == colSum\[1\]
The row and column sums match, and all matrix elements are non-negative.
Another possible matrix is: \[\[1,2\],
                             \[3,5\]\]

**Example 2:**

**Input:** rowSum = \[5,7,10\], colSum = \[8,6,8\]
**Output:** \[\[0,5,0\],
         \[6,1,0\],
         \[2,0,8\]\]

**Constraints:**

*   `1 <= rowSum.length, colSum.length <= 500`
*   `0 <= rowSum[i], colSum[i] <= 108`
*   `sum(rowSum) == sum(colSum)`

## A solution in Java

```java
public int minDays(int[] bloomDay, int m, int k) {
    int left = Arrays.stream(bloomDay).min().getAsInt();
    int right = Arrays.stream(bloomDay).max().getAsInt();

    while (left < right) {
        int mid = left + (right - left) / 2;
        int bouquets = 0, flowers = 0;
        for (int day : bloomDay) {
            if (day > mid) {
                flowers = 0;
            } else {
                flowers++;
                if (flowers == k) {
                    bouquets++;
                    flowers = 0;
                }
            }
        }
        if (bouquets >= m) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return m == 0 ? -1 : left;
}
```
We will use binary search to approach this problem. We first find the minimum and maximum bloom days, which will be the left and right boundaries of the search range. In each iteration, we calculate the middle value, and calculate the number of bouquets we can make with the bloom days less than or equal to the middle value. If the number of bouquets is greater than or equal to m, we update the right boundary to mid. Otherwise, we update the left boundary to mid + 1. The search ends when the left boundary is equal to the right boundary. The final return value will be -1 if m is 0, otherwise, it will be left boundary value.

## A solution in C++

```cpp
int minDays(vector<int>& bloomDay, int m, int k) {
    int left = *min_element(bloomDay.begin(), bloomDay.end());
    int right = *max_element(bloomDay.begin(), bloomDay.end());

    while (left < right) {
        int mid = left + (right - left) / 2;
        int bouquets = 0, flowers = 0;
        for (int day : bloomDay) {
            if (day > mid) {
                flowers = 0;
            } else {
                flowers++;
                if (flowers == k) {
                    bouquets++;
                    flowers = 0;
                }
            }
        }
        if (bouquets >= m) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return m == 0 ? -1 : left;
}
```
We will use binary search to approach this problem. We first find the minimum and maximum bloom days, which will be the left and right boundaries of the search range. In each iteration, we calculate the middle value, and calculate the number of bouquets we can make with the bloom days less than or equal to the middle value. If the number of bouquets is greater than or equal to m, we update the right boundary to mid. Otherwise, we update the left boundary to mid + 1. The search ends when the left boundary is equal to the right boundary. The final return value will be -1 if m is 0, otherwise, it will be left boundary value.

## A solution in Python

```python
def minDays(bloomDay, m, k):
    left, right = min(bloomDay), max(bloomDay)

    while left < right:
        mid = left + (right - left) // 2
        bouquets = flowers = 0
        for day in bloomDay:
            if day > mid:
                flowers = 0
            else:
                flowers += 1
                if flowers == k:
                    bouquets += 1
                    flowers = 0

        if bouquets >= m:
            right = mid
        else:
            left = mid + 1

    return -1 if m == 0 else left
```
We will use binary search to approach this problem. We first find the minimum and maximum bloom days, which will be the left and right boundaries of the search range. In each iteration, we calculate the middle value, and calculate the number of bouquets we can make with the bloom days less than or equal to the middle value. If the number of bouquets is greater than or equal to m, we update the right boundary to mid. Otherwise, we update the left boundary to mid + 1. The search ends when the left boundary is equal to the right boundary. The final return value will be -1 if m is 0, otherwise, it will be left boundary value.

## A solution in Javascript

```javascript
function minDays(bloomDay, m, k) {
    let left = Math.min(...bloomDay), right = Math.max(...bloomDay);

    while (left < right) {
        let mid = left + Math.floor((right - left) / 2);
        let bouquets = 0, flowers = 0;
        for (let day of bloomDay) {
            if (day > mid) {
                flowers = 0;
            } else {
                flowers++;
                if (flowers === k) {
                    bouquets++;
                    flowers = 0;
                }
            }
        }
        if (bouquets >= m) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return m === 0 ? -1 : left;
}
```
We will use binary search to approach this problem. We first find the minimum and maximum bloom days, which will be the left and right boundaries of the search range. In each iteration, we calculate the middle value, and calculate the number of bouquets we can make with the bloom days less than or equal to the middle value. If the number of bouquets is greater than or equal to m, we update the right boundary to mid. Otherwise, we update the left boundary to mid + 1. The search ends when the left boundary is equal to the right boundary. The final return value will be -1 if m is 0, otherwise, it will be left boundary value.