# Check if Numbers Are Ascending in a Sentence

- slug: check-if-numbers-are-ascending-in-a-sentence
- difficulty: Easy

A sentence is a list of **tokens** separated by a **single** space with no leading or trailing spaces. Every token is either a **positive number** consisting of digits `0-9` with no leading zeros, or a **word** consisting of lowercase English letters.

*   For example, `"a puppy has 2 eyes 4 legs "` is a sentence with seven tokens: `"2 "` and `"4 "` are numbers and the other tokens such as `"puppy "` are words.

Given a string `s` representing a sentence, you need to check if **all** the numbers in `s` are **strictly increasing** from left to right (i.e., other than the last number, **each** number is **strictly smaller** than the number on its **right** in `s`).

Return `true` _if so, or_ `false` _otherwise_.

**Example 1:**

**Input:** s =  "1 box has 3 blue 4 red 6 green and 12 yellow marbles "
**Output:** true
**Explanation:** The numbers in s are: 1, 3, 4, 6, 12.
They are strictly increasing from left to right: 1 < 3 < 4 < 6 < 12.

**Example 2:**

**Input:** s =  "hello world 5 x 5 "
**Output:** false
**Explanation:** The numbers in s are: **5**, **5**. They are not strictly increasing.

**Example 3:**

**Input:** s =  "sunset is at 7 51 pm overnight lows will be in the low 50 and 60 s "
**Output:** false
**Explanation:** The numbers in s are: 7, **51**, **50**, 60. They are not strictly increasing.

**Constraints:**

*   `3 <= s.length <= 200`
*   `s` consists of lowercase English letters, spaces, and digits from `0` to `9`, inclusive.
*   The number of tokens in `s` is between `2` and `100`, inclusive.
*   The tokens in `s` are separated by a single space.
*   There are at least **two** numbers in `s`.
*   Each number in `s` is a **positive** number **less** than `100`, with no leading zeros.
*   `s` contains no leading or trailing spaces.

## A solution in Java

```java
public int maxProductDifference(int[] nums) {
    int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE, max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE;
    for (int num : nums) {
        if (num < min1) {
            min2 = min1;
            min1 = num;
        } else if (num < min2) {
            min2 = num;
        }
        if (num > max1) {
            max2 = max1;
            max1 = num;
        } else if (num > max2) {
            max2 = num;
        }
    }
    return max1 * max2 - min1 * min2;
}
```
We need to find two smallest numbers (min1, min2) and two largest numbers (max1, max2) in the given array. Initialize all four variables with appropriate extreme values, then loop through the array and update them on each iteration. The maximum product difference is (max1 * max2) - (min1 * min2).

## A solution in C++

```cpp
int maxProductDifference(vector<int>& nums) {
    int min1 = INT_MAX, min2 = INT_MAX, max1 = INT_MIN, max2 = INT_MIN;
    for (int num : nums) {
        if (num < min1) {
            min2 = min1;
            min1 = num;
        } else if (num < min2) {
            min2 = num;
        }
        if (num > max1) {
            max2 = max1;
            max1 = num;
        } else if (num > max2) {
            max2 = num;
        }
    }
    return max1 * max2 - min1 * min2;
}
```
We need to find two smallest numbers (min1, min2) and two largest numbers (max1, max2) in the given array. Initialize all four variables with appropriate extreme values, then loop through the array and update them on each iteration. The maximum product difference is (max1 * max2) - (min1 * min2).

## A solution in Python

```python
def maxProductDifference(nums):
    min1, min2, max1, max2 = float('inf'), float('inf'), float('-inf'), float('-inf')
    for num in nums:
        if num < min1:
            min2, min1 = min1, num
        elif num < min2:
            min2 = num
        if num > max1:
            max2, max1 = max1, num
        elif num > max2:
            max2 = num
    return max1 * max2 - min1 * min2
```
We need to find two smallest numbers (min1, min2) and two largest numbers (max1, max2) in the given array. Initialize all four variables with appropriate extreme values, then loop through the array and update them on each iteration. The maximum product difference is (max1 * max2) - (min1 * min2).

## A solution in Javascript

```javascript
function maxProductDifference(nums) {
    let min1 = Number.MAX_SAFE_INTEGER, min2 = Number.MAX_SAFE_INTEGER, max1 = Number.MIN_SAFE_INTEGER, max2 = Number.MIN_SAFE_INTEGER;
    for (let num of nums) {
        if (num < min1) {
            min2 = min1;
            min1 = num;
        } else if (num < min2) {
            min2 = num;
        }
        if (num > max1) {
            max2 = max1;
            max1 = num;
        } else if (num > max2) {
            max2 = num;
        }
    }
    return max1 * max2 - min1 * min2;
}
```
We need to find two smallest numbers (min1, min2) and two largest numbers (max1, max2) in the given array. Initialize all four variables with appropriate extreme values, then loop through the array and update them on each iteration. The maximum product difference is (max1 * max2) - (min1 * min2).


# Simple Bank System

- slug: simple-bank-system
- difficulty: Medium

You have been tasked with writing a program for a popular bank that will automate all its incoming transactions (transfer, deposit, and withdraw). The bank has `n` accounts numbered from `1` to `n`. The initial balance of each account is stored in a **0-indexed** integer array `balance`, with the `(i + 1)th` account having an initial balance of `balance[i]`.

Execute all the **valid** transactions. A transaction is **valid** if:

*   The given account number(s) are between `1` and `n`, and
*   The amount of money withdrawn or transferred from is **less than or equal** to the balance of the account.

Implement the `Bank` class:

*   `Bank(long[] balance)` Initializes the object with the **0-indexed** integer array `balance`.
*   `boolean transfer(int account1, int account2, long money)` Transfers `money` dollars from the account numbered `account1` to the account numbered `account2`. Return `true` if the transaction was successful, `false` otherwise.
*   `boolean deposit(int account, long money)` Deposit `money` dollars into the account numbered `account`. Return `true` if the transaction was successful, `false` otherwise.
*   `boolean withdraw(int account, long money)` Withdraw `money` dollars from the account numbered `account`. Return `true` if the transaction was successful, `false` otherwise.

**Example 1:**

**Input**
\[ "Bank ",  "withdraw ",  "transfer ",  "deposit ",  "transfer ",  "withdraw "\]
\[\[\[10, 100, 20, 50, 30\]\], \[3, 10\], \[5, 1, 20\], \[5, 20\], \[3, 4, 15\], \[10, 50\]\]
**Output**
\[null, true, true, true, false, false\]

**Explanation**
Bank bank = new Bank(\[10, 100, 20, 50, 30\]);
bank.withdraw(3, 10);    // return true, account 3 has a balance of $20, so it is valid to withdraw $10.
                         // Account 3 has $20 - $10 = $10.
bank.transfer(5, 1, 20); // return true, account 5 has a balance of $30, so it is valid to transfer $20.
                         // Account 5 has $30 - $20 = $10, and account 1 has $10 + $20 = $30.
bank.deposit(5, 20);     // return true, it is valid to deposit $20 to account 5.
                         // Account 5 has $10 + $20 = $30.
bank.transfer(3, 4, 15); // return false, the current balance of account 3 is $10,
                         // so it is invalid to transfer $15 from it.
bank.withdraw(10, 50);   // return false, it is invalid because account 10 does not exist.

**Constraints:**

*   `n == balance.length`
*   `1 <= n, account, account1, account2 <= 105`
*   `0 <= balance[i], money <= 1012`
*   At most `104` calls will be made to **each** function `transfer`, `deposit`, `withdraw`.

## A solution in Java

```java
public int[][] rotateGrid(int[][] grid, int k) {
    int m = grid.length, n = grid[0].length;
    int layers = Math.min(m, n) / 2;
    for (int layer = 0; layer < layers; layer++) {
        rotateLayer(grid, layer, k);
    }
    return grid;
}

private void rotateLayer(int[][] matrix, int layer, int k) {
    int m = matrix.length, n = matrix[0].length;
    int top = layer, bottom = m - 1 - layer;
    int left = layer, right = n - 1 - layer;
    int data_in_layer = (right - left + 1) * 2 + (bottom - top - 1) * 2;
    k %= data_in_layer;
    while (k-- > 0) {
        int temp = matrix[top][left];
        for (int j = left; j < right; j++) matrix[top][j] = matrix[top][j + 1];
        for (int i = top; i < bottom; i++) matrix[i][right] = matrix[i + 1][right];
        for (int j = right; j > left; j--) matrix[bottom][j] = matrix[bottom][j - 1];
        for (int i = bottom; i > top; i--) matrix[i][left] = matrix[i - 1][left];
        matrix[top + 1][left] = temp;
    }
}
```
The algorithm works as follows:
1. Calculate the number of layers in the matrix based on its dimensions, since m and n are both even integers, this number will always be an integer.
2. For each layer, create a helper function `rotateLayer` to rotate the layer k times counter-clockwise. Calculate data_in_layer which is the number of cells belonging to that layer.
3. Perform k % data_in_layer rotations to avoid unnecessary complete rotations.
4. Each rotation is done as follows: save the top-left corner value, move the top row cells to the left, move the right column cells up, move the bottom row cells to the right, move the left column cells down, save the stored top-left corner value to top row's second cell.

The algorithm performs the rotations for each layer, and returns the rotated grid.

## A solution in C++

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

void rotateLayer(vector<vector<int>>& matrix, int layer, int k) {
    int m = matrix.size(), n = matrix[0].size();
    int top = layer, bottom = m - 1 - layer;
    int left = layer, right = n - 1 - layer;
    int data_in_layer = (right - left + 1) * 2 + (bottom - top - 1) * 2;
    k %= data_in_layer;
    while (k--) {
        int temp = matrix[top][left];
        for (int j = left; j < right; j++) matrix[top][j] = matrix[top][j + 1];
        for (int i = top; i < bottom; i++) matrix[i][right] = matrix[i + 1][right];
        for (int j = right; j > left; j--) matrix[bottom][j] = matrix[bottom][j - 1];
        for (int i = bottom; i > top; i--) matrix[i][left] = matrix[i - 1][left];
        matrix[top + 1][left] = temp;
    }
}

vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k) {
    int m = grid.size(), n = grid[0].size();
    int layers = min(m, n) / 2;
    for (int layer = 0; layer < layers; layer++) {
        rotateLayer(grid, layer, k);
    }
    return grid;
}
```
The algorithm works as follows:
1. Calculate the number of layers in the matrix based on its dimensions, since m and n are both even integers, this number will always be an integer.
2. For each layer, create a helper function `rotateLayer` to rotate the layer k times counter-clockwise. Calculate data_in_layer which is the number of cells belonging to that layer.
3. Perform k % data_in_layer rotations to avoid unnecessary complete rotations.
4. Each rotation is done as follows: save the top-left corner value, move the top row cells to the left, move the right column cells up, move the bottom row cells to the right, move the left column cells down, save the stored top-left corner value to top row's second cell.

The algorithm performs the rotations for each layer, and returns the rotated grid.

## A solution in Python

```python
def rotateGrid(grid, k):
    def rotateLayer(layer, k):
        m, n = len(grid), len(grid[0])
        top, bottom = layer, m - 1 - layer
        left, right = layer, n - 1 - layer
        data_in_layer = (right - left + 1) * 2 + (bottom - top - 1) * 2
        k %= data_in_layer
        for _ in range(k):
            temp = grid[top][left]
            for j in range(left, right):
                grid[top][j] = grid[top][j + 1]
            for i in range(top, bottom):
                grid[i][right] = grid[i + 1][right]
            for j in range(right, left, -1):
                grid[bottom][j] = grid[bottom][j - 1]
            for i in range(bottom, top, -1):
                grid[i][left] = grid[i - 1][left]
            grid[top + 1][left] = temp

    m, n = len(grid), len(grid[0])
    layers = min(m, n) // 2
    for layer in range(layers):
        rotateLayer(layer, k)
    return grid
```
The algorithm works as follows:
1. Calculate the number of layers in the matrix based on its dimensions, since m and n are both even integers, this number will always be an integer.
2. For each layer, create a helper function `rotateLayer` to rotate the layer k times counter-clockwise. Calculate data_in_layer which is the number of cells belonging to that layer.
3. Perform k % data_in_layer rotations to avoid unnecessary complete rotations.
4. Each rotation is done as follows: save the top-left corner value, move the top row cells to the left, move the right column cells up, move the bottom row cells to the right, move the left column cells down, save the stored top-left corner value to top row's second cell.

The algorithm performs the rotations for each layer, and returns the rotated grid.

## A solution in Javascript

```javascript
function rotateGrid(grid, k) {
    function rotateLayer(layer, k) {
        const m = grid.length, n = grid[0].length;
        const top = layer, bottom = m - 1 - layer;
        const left = layer, right = n - 1 - layer;
        const data_in_layer = (right - left + 1) * 2 + (bottom - top - 1) * 2;
        k %= data_in_layer;
        while (k-- > 0) {
            const temp = grid[top][left];
            for (let j = left; j < right; j++) grid[top][j] = grid[top][j + 1];
            for (let i = top; i < bottom; i++) grid[i][right] = grid[i + 1][right];
            for (let j = right; j > left; j--) grid[bottom][j] = grid[bottom][j - 1];
            for (let i = bottom; i > top; i--) grid[i][left] = grid[i - 1][left];
            grid[top + 1][left] = temp;
        }
    }

    const m = grid.length, n = grid[0].length;
    const layers = Math.min(m, n) / 2;
    for (let layer = 0; layer < layers; layer++) {
        rotateLayer(layer, k);
    }
    return grid;
}
```
The algorithm works as follows:
1. Calculate the number of layers in the matrix based on its dimensions, since m and n are both even integers, this number will always be an integer.
2. For each layer, create a helper function `rotateLayer` to rotate the layer k times counter-clockwise. Calculate data_in_layer which is the number of cells belonging to that layer.
3. Perform k % data_in_layer rotations to avoid unnecessary complete rotations.
4. Each rotation is done as follows: save the top-left corner value, move the top row cells to the left, move the right column cells up, move the bottom row cells to the right, move the left column cells down, save the stored top-left corner value to top row's second cell.

The algorithm performs the rotations for each layer, and returns the rotated grid.


# Count Number of Maximum Bitwise-OR Subsets

- slug: count-number-of-maximum-bitwise-or-subsets
- difficulty: Medium

Given an integer array `nums`, find the **maximum** possible **bitwise OR** of a subset of `nums` and return _the **number of different non-empty subsets** with the maximum bitwise OR_.

An array `a` is a **subset** of an array `b` if `a` can be obtained from `b` by deleting some (possibly zero) elements of `b`. Two subsets are considered **different** if the indices of the elements chosen are different.

The bitwise OR of an array `a` is equal to `a[0] **OR** a[1] **OR** ... **OR** a[a.length - 1]` (**0-indexed**).

**Example 1:**

**Input:** nums = \[3,1\]
**Output:** 2
**Explanation:** The maximum possible bitwise OR of a subset is 3. There are 2 subsets with a bitwise OR of 3:
- \[3\]
- \[3,1\]

**Example 2:**

**Input:** nums = \[2,2,2\]
**Output:** 7
**Explanation:** All non-empty subsets of \[2,2,2\] have a bitwise OR of 2. There are 23 - 1 = 7 total subsets.

**Example 3:**

**Input:** nums = \[3,2,1,5\]
**Output:** 6
**Explanation:** The maximum possible bitwise OR of a subset is 7. There are 6 subsets with a bitwise OR of 7:
- \[3,5\]
- \[3,1,5\]
- \[3,2,5\]
- \[3,2,1,5\]
- \[2,5\]
- \[2,1,5\]

**Constraints:**

*   `1 <= nums.length <= 16`
*   `1 <= nums[i] <= 105`

## A solution in Java

```java
public long wonderfulSubstrings(String word) {
    long res = 0;
    int mask = 0;
    Map<Integer, Integer> count = new HashMap<>();
    count.put(0, 1);
    for (char c : word.toCharArray()) {
        mask ^= 1 << (c - 'a');
        res += count.getOrDefault(mask, 0);
        for (int i = 0; i < 10; ++i)
            res += count.getOrDefault(mask ^ (1 << i), 0);
        count.put(mask, count.getOrDefault(mask, 0) + 1);
    }
    return res;
}
```
The algorithm uses a bitmask, which is an integer where the i-th bit is set if the frequency of the character i is odd in the current substring. For each character in the given string, the algorithm updates the mask and the count hashmap, which keeps the frequency of the encountered masks.

The algorithm iterates through the string and, for each character, it XORs the mask with a bit shift. This updates the bit for the character in the mask to its correct parity. Then, it adds the count of the current mask to the result. Next, it iterates through the possible characters from 0 to 9, applies an XOR operation on the mask with the current bit, and adds the count of the updated mask to the result. Finally, it increments the count of the current mask in the hashmap.

This algorithm ensures that it counts all possible substrings that have at most one letter appearing an odd number of times.

## A solution in C++

```cpp
#include <unordered_map>
long long wonderfulSubstrings(string word) {
    long long res = 0;
    int mask = 0;
    unordered_map<int, int> count{{0, 1}};
    for (char c : word) {
        mask ^= 1 << (c - 'a');
        res += count[mask];
        for (int i = 0; i < 10; ++i)
            res += count[mask ^ (1 << i)];
        ++count[mask];
    }
    return res;
}
```
The algorithm uses a bitmask, which is an integer where the i-th bit is set if the frequency of the character i is odd in the current substring. For each character in the given string, the algorithm updates the mask and the count hashmap, which keeps the frequency of the encountered masks.

The algorithm iterates through the string and, for each character, it XORs the mask with a bit shift. This updates the bit for the character in the mask to its correct parity. Then, it adds the count of the current mask to the result. Next, it iterates through the possible characters from 0 to 9, applies an XOR operation on the mask with the current bit, and adds the count of the updated mask to the result. Finally, it increments the count of the current mask in the hashmap.

This algorithm ensures that it counts all possible substrings that have at most one letter appearing an odd number of times.

## A solution in Python

```python
def wonderfulSubstrings(word: str) -> int:
    res = 0
    mask = 0
    count = {0: 1}
    for c in word:
        mask ^= 1 << (ord(c) - ord('a'))
        res += count.get(mask, 0)
        for i in range(10):
            res += count.get(mask ^ (1 << i), 0)
        count[mask] = count.get(mask, 0) + 1
    return res
```
The algorithm uses a bitmask, which is an integer where the i-th bit is set if the frequency of the character i is odd in the current substring. For each character in the given string, the algorithm updates the mask and the count hashmap, which keeps the frequency of the encountered masks.

The algorithm iterates through the string and, for each character, it XORs the mask with a bit shift. This updates the bit for the character in the mask to its correct parity. Then, it adds the count of the current mask to the result. Next, it iterates through the possible characters from 0 to 9, applies an XOR operation on the mask with the current bit, and adds the count of the updated mask to the result. Finally, it increments the count of the current mask in the hashmap.

This algorithm ensures that it counts all possible substrings that have at most one letter appearing an odd number of times.

## A solution in Javascript

```javascript
function wonderfulSubstrings(word) {
    let res = 0;
    let mask = 0;
    let count = new Map();
    count.set(0, 1);
    for (let c of word) {
        mask ^= 1 << (c.charCodeAt(0) - 'a'.charCodeAt(0));
        res += (count.get(mask) || 0);
        for (let i = 0; i < 10; ++i)
            res += (count.get(mask ^ (1 << i)) || 0);
        count.set(mask, (count.get(mask) || 0) + 1);
    }
    return res;
}
```
The algorithm uses a bitmask, which is an integer where the i-th bit is set if the frequency of the character i is odd in the current substring. For each character in the given string, the algorithm updates the mask and the count hashmap, which keeps the frequency of the encountered masks.

The algorithm iterates through the string and, for each character, it XORs the mask with a bit shift. This updates the bit for the character in the mask to its correct parity. Then, it adds the count of the current mask to the result. Next, it iterates through the possible characters from 0 to 9, applies an XOR operation on the mask with the current bit, and adds the count of the updated mask to the result. Finally, it increments the count of the current mask in the hashmap.

This algorithm ensures that it counts all possible substrings that have at most one letter appearing an odd number of times.


# Second Minimum Time to Reach Destination

- slug: second-minimum-time-to-reach-destination
- difficulty: Hard

A city is represented as a **bi-directional connected** graph with `n` vertices where each vertex is labeled from `1` to `n` (**inclusive**). The edges in the graph are represented as a 2D integer array `edges`, where each `edges[i] = [ui, vi]` denotes a bi-directional edge between vertex `ui` and vertex `vi`. Every vertex pair is connected by **at most one** edge, and no vertex has an edge to itself. The time taken to traverse any edge is `time` minutes.

Each vertex has a traffic signal which changes its color from **green** to **red** and vice versa every `change` minutes. All signals change **at the same time**. You can enter a vertex at **any time**, but can leave a vertex **only when the signal is green**. You **cannot wait** at a vertex if the signal is **green**.

The **second minimum value** is defined as the smallest value **strictly larger** than the minimum value.

*   For example the second minimum value of `[2, 3, 4]` is `3`, and the second minimum value of `[2, 2, 4]` is `4`.

Given `n`, `edges`, `time`, and `change`, return _the **second minimum time** it will take to go from vertex_ `1` _to vertex_ `n`.

**Notes:**

*   You can go through any vertex **any** number of times, **including** `1` and `n`.
*   You can assume that when the journey **starts**, all signals have just turned **green**.

**Example 1:**

**Input:** n = 5, edges = \[\[1,2\],\[1,3\],\[1,4\],\[3,4\],\[4,5\]\], time = 3, change = 5
**Output:** 13
**Explanation:**
The figure on the left shows the given graph.
The blue path in the figure on the right is the minimum time path.
The time taken is:
- Start at 1, time elapsed=0
- 1 -> 4: 3 minutes, time elapsed=3
- 4 -> 5: 3 minutes, time elapsed=6
Hence the minimum time needed is 6 minutes.

The red path shows the path to get the second minimum time.
- Start at 1, time elapsed=0
- 1 -> 3: 3 minutes, time elapsed=3
- 3 -> 4: 3 minutes, time elapsed=6
- Wait at 4 for 4 minutes, time elapsed=10
- 4 -> 5: 3 minutes, time elapsed=13
Hence the second minimum time is 13 minutes.

**Example 2:**

**Input:** n = 2, edges = \[\[1,2\]\], time = 3, change = 2
**Output:** 11
**Explanation:**
The minimum time path is 1 -> 2 with time = 3 minutes.
The second minimum time path is 1 -> 2 -> 1 -> 2 with time = 11 minutes.

**Constraints:**

*   `2 <= n <= 104`
*   `n - 1 <= edges.length <= min(2 * 104, n * (n - 1) / 2)`
*   `edges[i].length == 2`
*   `1 <= ui, vi <= n`
*   `ui != vi`
*   There are no duplicate edges.
*   Each vertex can be reached directly or indirectly from every other vertex.
*   `1 <= time, change <= 103`

## A solution in Java

```java
import java.util.*;

public int secondMinimum(int n, int[][] edges, int time, int change) {
    List<List<Integer>> graph = new ArrayList<>();
    for (int i = 0; i <= n; i++) {
        graph.add(new ArrayList<>());
    }

    for (int[] edge : edges) {
        graph.get(edge[0]).add(edge[1]);
        graph.get(edge[1]).add(edge[0]);
    }

    int[] dist = new int[n + 1];
    int[] dist2 = new int[n + 1];
    Arrays.fill(dist, Integer.MAX_VALUE);
    Arrays.fill(dist2, Integer.MAX_VALUE);
    dist[1] = 0;

    Queue<Integer> q = new LinkedList<>();
    q.add(1);

    while (!q.isEmpty()) {
        int cur = q.poll();

        int nextDist = dist[cur] + time;
        int waitTime = (nextDist / change % 2 == 1) ? change : 0;
        nextDist += waitTime;

        for (int next : graph.get(cur)) {
            if (nextDist < dist[next]) {
                int tmp = nextDist;
                nextDist = dist[next];
                dist[next] = tmp;
                q.add(next);
            }
            if (nextDist < dist2[next]) {
                int tmp = nextDist;
                nextDist = dist2[next];
                dist2[next] = tmp;
                q.add(next);
            }
        }
    }
    return dist2[n];
}
```
The main idea is to find the second shortest time for each vertex to reach the target vertex `n` using a Breadth-First Search (BFS) algorithm. Start by constructing the adjacency list representation of the graph. Then create two arrays `dist` and `dist2` for keeping the minimum and 2nd minimum time to reach each vertex, respectively.

1. Initialize the distance arrays with infinity, except for `dist[1] = 0`, since the journey starts at vertex 1.
2. Use a queue (`deque` in Python, `Queue` in Java, and array in JavaScript) for BFS traversal. Add the starting vertex to the queue.
3. While the queue is not empty, do the following:
    a. Pop the vertex from the queue.
    b. Calculate the next distance by adding the current time to the current vertex's distance.
    c. Check if the signal at the current vertex is green or red. If it's red, add the wait time required to turn it green.
    d. Iterate through the neighbors of the current vertex.
        - If the next distance is less than the minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
        - If the next distance is less than the 2nd minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
4. Return the 2nd minimum distance value of vertex `n`.

## A solution in C++

```cpp
#include <vector>
#include <queue>
using namespace std;

int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
    vector<vector<int>> graph(n + 1);
    for (const auto &edge : edges) {
        graph[edge[0]].push_back(edge[1]);
        graph[edge[1]].push_back(edge[0]);
    }

    const int INF = 1e9;
    vector<int> dist(n + 1, INF);
    vector<int> dist2(n + 1, INF);
    dist[1] = 0;

    queue<int> q;
    q.push(1);

    while (!q.empty()) {
        int cur = q.front();
        q.pop();

        int nextDist = dist[cur] + time;
        int waitTime = (nextDist / change % 2 == 1) ? change : 0;
        nextDist += waitTime;

        for (int next : graph[cur]) {
            if (nextDist < dist[next]) {
                swap(nextDist, dist[next]);
                q.push(next);
            }
            if (nextDist < dist2[next]) {
                swap(nextDist, dist2[next]);
                q.push(next);
            }
        }
    }
    return dist2[n];
}
```
The main idea is to find the second shortest time for each vertex to reach the target vertex `n` using a Breadth-First Search (BFS) algorithm. Start by constructing the adjacency list representation of the graph. Then create two arrays `dist` and `dist2` for keeping the minimum and 2nd minimum time to reach each vertex, respectively.

1. Initialize the distance arrays with infinity, except for `dist[1] = 0`, since the journey starts at vertex 1.
2. Use a queue (`deque` in Python, `Queue` in Java, and array in JavaScript) for BFS traversal. Add the starting vertex to the queue.
3. While the queue is not empty, do the following:
    a. Pop the vertex from the queue.
    b. Calculate the next distance by adding the current time to the current vertex's distance.
    c. Check if the signal at the current vertex is green or red. If it's red, add the wait time required to turn it green.
    d. Iterate through the neighbors of the current vertex.
        - If the next distance is less than the minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
        - If the next distance is less than the 2nd minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
4. Return the 2nd minimum distance value of vertex `n`.

## A solution in Python

```python
from collections import defaultdict, deque

def secondMinimum(n, edges, time, change):
    graph = defaultdict(list)

    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    dist = [float('inf')] * (n + 1)
    dist2 = [float('inf')] * (n + 1)
    dist[1] = 0

    q = deque([1])

    while q:
        cur = q.popleft()

        nextDist = dist[cur] + time
        waitTime = change if (nextDist // change) % 2 == 1 else 0
        nextDist += waitTime

        for next in graph[cur]:
            if nextDist < dist[next]:
                nextDist, dist[next] = dist[next], nextDist
                q.append(next)
            if nextDist < dist2[next]:
                nextDist, dist2[next] = dist2[next], nextDist
                q.append(next)

    return dist2[n]
```
The main idea is to find the second shortest time for each vertex to reach the target vertex `n` using a Breadth-First Search (BFS) algorithm. Start by constructing the adjacency list representation of the graph. Then create two arrays `dist` and `dist2` for keeping the minimum and 2nd minimum time to reach each vertex, respectively.

1. Initialize the distance arrays with infinity, except for `dist[1] = 0`, since the journey starts at vertex 1.
2. Use a queue (`deque` in Python, `Queue` in Java, and array in JavaScript) for BFS traversal. Add the starting vertex to the queue.
3. While the queue is not empty, do the following:
    a. Pop the vertex from the queue.
    b. Calculate the next distance by adding the current time to the current vertex's distance.
    c. Check if the signal at the current vertex is green or red. If it's red, add the wait time required to turn it green.
    d. Iterate through the neighbors of the current vertex.
        - If the next distance is less than the minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
        - If the next distance is less than the 2nd minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
4. Return the 2nd minimum distance value of vertex `n`.

## A solution in Javascript

```javascript
function secondMinimum(n, edges, time, change) {
    const graph = Array(n + 1).fill(null).map(() => []);
    for (const [u, v] of edges) {
        graph[u].push(v);
        graph[v].push(u);
    }

    const dist = new Array(n + 1).fill(Infinity);
    const dist2 = new Array(n + 1).fill(Infinity);
    dist[1] = 0;

    const q = [1];

    while (q.length) {
        const cur = q.shift();

        let nextDist = dist[cur] + time;
        const waitTime = (nextDist / change) % 2 === 1 ? change : 0;
        nextDist += waitTime;

        for (const next of graph[cur]) {
            if (nextDist < dist[next]) {
                [nextDist, dist[next]] = [dist[next], nextDist];
                q.push(next);
            }
            if (nextDist < dist2[next]) {
                [nextDist, dist2[next]] = [dist2[next], nextDist];
                q.push(next);
            }
        }
    }
    return dist2[n];
}
```
The main idea is to find the second shortest time for each vertex to reach the target vertex `n` using a Breadth-First Search (BFS) algorithm. Start by constructing the adjacency list representation of the graph. Then create two arrays `dist` and `dist2` for keeping the minimum and 2nd minimum time to reach each vertex, respectively.

1. Initialize the distance arrays with infinity, except for `dist[1] = 0`, since the journey starts at vertex 1.
2. Use a queue (`deque` in Python, `Queue` in Java, and array in JavaScript) for BFS traversal. Add the starting vertex to the queue.
3. While the queue is not empty, do the following:
    a. Pop the vertex from the queue.
    b. Calculate the next distance by adding the current time to the current vertex's distance.
    c. Check if the signal at the current vertex is green or red. If it's red, add the wait time required to turn it green.
    d. Iterate through the neighbors of the current vertex.
        - If the next distance is less than the minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
        - If the next distance is less than the 2nd minimum distance of the neighbor vertex, swap them, and add the neighbor vertex to the queue.
4. Return the 2nd minimum distance value of vertex `n`.


# Sort Linked List Already Sorted Using Absolute Values

- slug: sort-linked-list-already-sorted-using-absolute-values
- difficulty: Medium

Given the `head` of a singly linked list that is sorted in **non-decreasing** order using the **absolute values** of its nodes, return _the list sorted in **non-decreasing** order using the **actual values** of its nodes_.

**Example 1:**

**Input:** head = \[0,2,-5,5,10,-10\]
**Output:** \[-10,-5,0,2,5,10\]
**Explanation:**
The list sorted in non-descending order using the absolute values of the nodes is \[0,2,-5,5,10,-10\].
The list sorted in non-descending order using the actual values is \[-10,-5,0,2,5,10\].

**Example 2:**

**Input:** head = \[0,1,2\]
**Output:** \[0,1,2\]
**Explanation:**
The linked list is already sorted in non-decreasing order.

**Example 3:**

**Input:** head = \[1\]
**Output:** \[1\]
**Explanation:**
The linked list is already sorted in non-decreasing order.

**Constraints:**

*   The number of nodes in the list is the range `[1, 105]`.
*   `-5000 <= Node.val <= 5000`
*   `head` is sorted in non-decreasing order using the absolute value of its nodes.

**Follow up:**

*   Can you think of a solution with `O(n)` time complexity?

## A solution in Java

```java
public class ListNode {
    int val;
    ListNode next;
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

public ListNode sortedList(ListNode head) {
    if (head == null || head.next == null) return head;

    ListNode prev = head;
    ListNode cur = head.next;

    while (cur != null) {
        if (cur.val < prev.val) {
            prev.next = cur.next;
            cur.next = head;
            head = cur;
            cur = prev;
        } else {
            prev = cur;
        }
        cur = cur.next;
    }
    return head;
}
```
The given linked list is sorted in non-decreasing order using absolute values of its nodes. We need to sort the linked list in non-decreasing order using the actual values of the nodes.
1. Start with two pointers, `prev` and `cur` initially pointing to the head and head's next respectively.
2. Traverse the linked list using a while loop.
3. Inside the loop, check if the value of `cur` is less than the value of `prev`.
   - If true, then move the current node to the front of the list, update `prev` and `cur`.
   - Else, set the `prev` to the current node.
4. Continue the traversal until the end of the list is reached.

Time complexity: O(n)

## A solution in C++

```cpp
class ListNode {
public:
    int val;
    ListNode* next;
    ListNode(int val, ListNode* next = nullptr) : val(val), next(next) {}
};

ListNode* sortedList(ListNode* head) {
    if (!head || !head->next) return head;

    ListNode* prev = head;
    ListNode* cur = head->next;

    while (cur) {
        if (cur->val < prev->val) {
            prev->next = cur->next;
            cur->next = head;
            head = cur;
            cur = prev;
        } else {
            prev = cur;
        }
        cur = cur->next;
    }
    return head;
}
```
The given linked list is sorted in non-decreasing order using absolute values of its nodes. We need to sort the linked list in non-decreasing order using the actual values of the nodes.
1. Start with two pointers, `prev` and `cur` initially pointing to the head and head's next respectively.
2. Traverse the linked list using a while loop.
3. Inside the loop, check if the value of `cur` is less than the value of `prev`.
   - If true, then move the current node to the front of the list, update `prev` and `cur`.
   - Else, set the `prev` to the current node.
4. Continue the traversal until the end of the list is reached.

Time complexity: O(n)

## A solution in Python

```python
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def sortedList(head):
    if not head or not head.next:
        return head

    prev = head
    cur = head.next

    while cur:
        if cur.val < prev.val:
            prev.next = cur.next
            cur.next = head
            head = cur
            cur = prev
        else:
            prev = cur
        cur = cur.next
    return head
```
The given linked list is sorted in non-decreasing order using absolute values of its nodes. We need to sort the linked list in non-decreasing order using the actual values of the nodes.
1. Start with two pointers, `prev` and `cur` initially pointing to the head and head's next respectively.
2. Traverse the linked list using a while loop.
3. Inside the loop, check if the value of `cur` is less than the value of `prev`.
   - If true, then move the current node to the front of the list, update `prev` and `cur`.
   - Else, set the `prev` to the current node.
4. Continue the traversal until the end of the list is reached.

Time complexity: O(n)

## A solution in Javascript

```javascript
class ListNode {
    constructor(val, next = null) {
        this.val = val;
        this.next = next;
    }
}

function sortedList(head) {
    if (!head || !head.next) return head;

    let prev = head;
    let cur = head.next;

    while (cur) {
        if (cur.val < prev.val) {
            prev.next = cur.next;
            cur.next = head;
            head = cur;
            cur = prev;
        } else {
            prev = cur;
        }
        cur = cur.next;
    }
    return head;
}
```
The given linked list is sorted in non-decreasing order using absolute values of its nodes. We need to sort the linked list in non-decreasing order using the actual values of the nodes.
1. Start with two pointers, `prev` and `cur` initially pointing to the head and head's next respectively.
2. Traverse the linked list using a while loop.
3. Inside the loop, check if the value of `cur` is less than the value of `prev`.
   - If true, then move the current node to the front of the list, update `prev` and `cur`.
   - Else, set the `prev` to the current node.
4. Continue the traversal until the end of the list is reached.

Time complexity: O(n)


# Number of Valid Words in a Sentence

- slug: number-of-valid-words-in-a-sentence
- difficulty: Easy

A sentence consists of lowercase letters (`'a'` to `'z'`), digits (`'0'` to `'9'`), hyphens (`'-'`), punctuation marks (`'!'`, `'.'`, and `','`), and spaces (`' '`) only. Each sentence can be broken down into **one or more tokens** separated by one or more spaces `' '`.

A token is a valid word if **all three** of the following are true:

*   It only contains lowercase letters, hyphens, and/or punctuation (**no** digits).
*   There is **at most one** hyphen `'-'`. If present, it **must** be surrounded by lowercase characters ( `"a-b "` is valid, but `"-ab "` and `"ab- "` are not valid).
*   There is **at most one** punctuation mark. If present, it **must** be at the **end** of the token ( `"ab, "`, `"cd! "`, and `". "` are valid, but `"a!b "` and `"c., "` are not valid).

Examples of valid words include `"a-b. "`, `"afad "`, `"ba-c "`, `"a! "`, and `"! "`.

Given a string `sentence`, return _the **number** of valid words in_ `sentence`.

**Example 1:**

**Input:** sentence =  "cat and  dog "
**Output:** 3
**Explanation:** The valid words in the sentence are  "cat ",  "and ", and  "dog ".

**Example 2:**

**Input:** sentence =  "!this  1-s b8d! "
**Output:** 0
**Explanation:** There are no valid words in the sentence.
 "!this " is invalid because it starts with a punctuation mark.
 "1-s " and  "b8d " are invalid because they contain digits.

**Example 3:**

**Input:** sentence =  "alice and  bob are playing stone-game10 "
**Output:** 5
**Explanation:** The valid words in the sentence are  "alice ",  "and ",  "bob ",  "are ", and  "playing ".
 "stone-game10 " is invalid because it contains digits.

**Constraints:**

*   `1 <= sentence.length <= 1000`
*   `sentence` only contains lowercase English letters, digits, `' '`, `'-'`, `'!'`, `'.'`, and `','`.
*   There will be at least `1` token.

## A solution in Java

```java
public int[] findPeakGrid(int[][] mat) {
    int m = mat.length, n = mat[0].length;
    int l = 0, r = n - 1;

    while (l < r) {
        int mid = (l + r) / 2;
        int max_row = 0;

        for (int i = 1; i < m; i++) {
            if (mat[i][mid] > mat[max_row][mid]) {
                max_row = i;
            }
        }

        if (mat[max_row][mid] < mat[max_row][mid + 1]) {
            l = mid + 1;
        } else {
            r = mid;
        }
    }

    int max_row = 0;
    for (int i = 1; i < m; i++) {
        if (mat[i][l] > mat[max_row][l]) {
            max_row = i;
        }
    }

    return new int[]{max_row, l};
}
```
The algorithm is a modification of the binary search algorithm. We start by finding the middle column `mid`. For this column, we find the row `max_row` with the maximum element. Then, we compare the maximum element with its right neighbor.

If the right neighbor is greater, we know that there must be a peak element in the columns to the right, so we update `l = mid + 1`. Otherwise, we know that there must be a peak element in the columns to the left or at the current column, so we update `r = mid`.

Repeat this process until `l == r`. At this point, the maximum element in the column `l` is a peak element. We find the row `max_row` with the maximum element in the column `l` and return its position `[max_row, l]`.

Since we are using binary search, the time complexity of the algorithm is O(m log(n)) or O(n log(m)).

## A solution in C++

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

vector<int> findPeakGrid(vector<vector<int>>& mat) {
    int m = mat.size(), n = mat[0].size();
    int l = 0, r = n - 1;

    while (l < r) {
        int mid = (l + r) / 2;
        int max_row = 0;

        for (int i = 1; i < m; i++) {
            if (mat[i][mid] > mat[max_row][mid]) {
                max_row = i;
            }
        }

        if (mat[max_row][mid] < mat[max_row][mid + 1]) {
            l = mid + 1;
        } else {
            r = mid;
        }
    }

    int max_row = 0;
    for (int i = 1; i < m; i++) {
        if (mat[i][l] > mat[max_row][l]) {
            max_row = i;
        }
    }

    return {max_row, l};
}
```
The algorithm is a modification of the binary search algorithm. We start by finding the middle column `mid`. For this column, we find the row `max_row` with the maximum element. Then, we compare the maximum element with its right neighbor.

If the right neighbor is greater, we know that there must be a peak element in the columns to the right, so we update `l = mid + 1`. Otherwise, we know that there must be a peak element in the columns to the left or at the current column, so we update `r = mid`.

Repeat this process until `l == r`. At this point, the maximum element in the column `l` is a peak element. We find the row `max_row` with the maximum element in the column `l` and return its position `[max_row, l]`.

Since we are using binary search, the time complexity of the algorithm is O(m log(n)) or O(n log(m)).

## A solution in Python

```python
def findPeakGrid(mat: List[List[int]]) -> List[int]:
    m, n = len(mat), len(mat[0])
    l, r = 0, n - 1

    while l < r:
        mid = (l + r) // 2
        max_row = 0

        for i in range(1, m):
            if mat[i][mid] > mat[max_row][mid]:
                max_row = i

        if mat[max_row][mid] < mat[max_row][mid + 1]:
            l = mid + 1
        else:
            r = mid

    max_row = 0
    for i in range(1, m):
        if mat[i][l] > mat[max_row][l]:
            max_row = i

    return [max_row, l]
```
The algorithm is a modification of the binary search algorithm. We start by finding the middle column `mid`. For this column, we find the row `max_row` with the maximum element. Then, we compare the maximum element with its right neighbor.

If the right neighbor is greater, we know that there must be a peak element in the columns to the right, so we update `l = mid + 1`. Otherwise, we know that there must be a peak element in the columns to the left or at the current column, so we update `r = mid`.

Repeat this process until `l == r`. At this point, the maximum element in the column `l` is a peak element. We find the row `max_row` with the maximum element in the column `l` and return its position `[max_row, l]`.

Since we are using binary search, the time complexity of the algorithm is O(m log(n)) or O(n log(m)).

## A solution in Javascript

```javascript
function findPeakGrid(mat) {
    let m = mat.length, n = mat[0].length;
    let l = 0, r = n - 1;

    while (l < r) {
        let mid = Math.floor((l + r) / 2);
        let max_row = 0;

        for (let i = 1; i < m; i++) {
            if (mat[i][mid] > mat[max_row][mid]) {
                max_row = i;
            }
        }

        if (mat[max_row][mid] < mat[max_row][mid + 1]) {
            l = mid + 1;
        } else {
            r = mid;
        }
    }

    let max_row = 0;
    for (let i = 1; i < m; i++) {
        if (mat[i][l] > mat[max_row][l]) {
            max_row = i;
        }
    }

    return [max_row, l];
}
```
The algorithm is a modification of the binary search algorithm. We start by finding the middle column `mid`. For this column, we find the row `max_row` with the maximum element. Then, we compare the maximum element with its right neighbor.

If the right neighbor is greater, we know that there must be a peak element in the columns to the right, so we update `l = mid + 1`. Otherwise, we know that there must be a peak element in the columns to the left or at the current column, so we update `r = mid`.

Repeat this process until `l == r`. At this point, the maximum element in the column `l` is a peak element. We find the row `max_row` with the maximum element in the column `l` and return its position `[max_row, l]`.

Since we are using binary search, the time complexity of the algorithm is O(m log(n)) or O(n log(m)).


# Next Greater Numerically Balanced Number

- slug: next-greater-numerically-balanced-number
- difficulty: Medium

An integer `x` is **numerically balanced** if for every digit `d` in the number `x`, there are **exactly** `d` occurrences of that digit in `x`.

Given an integer `n`, return _the **smallest numerically balanced** number **strictly greater** than_ `n`_._

**Example 1:**

**Input:** n = 1
**Output:** 22
**Explanation:**
22 is numerically balanced since:
- The digit 2 occurs 2 times.
It is also the smallest numerically balanced number strictly greater than 1.

**Example 2:**

**Input:** n = 1000
**Output:** 1333
**Explanation:**
1333 is numerically balanced since:
- The digit 1 occurs 1 time.
- The digit 3 occurs 3 times.
It is also the smallest numerically balanced number strictly greater than 1000.
Note that 1022 cannot be the answer because 0 appeared more than 0 times.

**Example 3:**

**Input:** n = 3000
**Output:** 3133
**Explanation:**
3133 is numerically balanced since:
- The digit 1 occurs 1 time.
- The digit 3 occurs 3 times.
It is also the smallest numerically balanced number strictly greater than 3000.

**Constraints:**

*   `0 <= n <= 106`

## A solution in Java

```java
public int[] buildArray(int[] nums) {
    int[] ans = new int[nums.length];
    for(int i = 0; i < nums.length; i++) {
        ans[i] = nums[nums[i]];
    }
    return ans;
}
```
We initialize a new array `ans` with the same length as the input numbers array `nums`. Then, we iterate through each element `i` in the `nums` array. For each `i`, we use the index value stored in `nums[i]` to access the value at that index in `nums`. We then add this value to the `ans` array at the corresponding index `i`. Finally, we return the `ans` array containing the values determined by the permutation.

## A solution in C++

```cpp
#include <vector>

std::vector<int> buildArray(std::vector<int>& nums) {
    std::vector<int> ans(nums.size());
    for(int i = 0; i < nums.size(); i++) {
        ans[i] = nums[nums[i]];
    }
    return ans;
}
```
We initialize a new array `ans` with the same length as the input numbers array `nums`. Then, we iterate through each element `i` in the `nums` array. For each `i`, we use the index value stored in `nums[i]` to access the value at that index in `nums`. We then add this value to the `ans` array at the corresponding index `i`. Finally, we return the `ans` array containing the values determined by the permutation.

## A solution in Python

```python
def build_array(nums):
    ans = []
    for i in range(len(nums)):
        ans.append(nums[nums[i]])
    return ans
```
We initialize a new array `ans` with the same length as the input numbers array `nums`. Then, we iterate through each element `i` in the `nums` array. For each `i`, we use the index value stored in `nums[i]` to access the value at that index in `nums`. We then add this value to the `ans` array at the corresponding index `i`. Finally, we return the `ans` array containing the values determined by the permutation.

## A solution in Javascript

```javascript
function buildArray(nums) {
    let ans = [];
    for(let i = 0; i < nums.length; i++) {
        ans.push(nums[nums[i]]);
    }
    return ans;
}
```
We initialize a new array `ans` with the same length as the input numbers array `nums`. Then, we iterate through each element `i` in the `nums` array. For each `i`, we use the index value stored in `nums[i]` to access the value at that index in `nums`. We then add this value to the `ans` array at the corresponding index `i`. Finally, we return the `ans` array containing the values determined by the permutation.


# Count Nodes With the Highest Score

- slug: count-nodes-with-the-highest-score
- difficulty: Medium

There is a **binary** tree rooted at `0` consisting of `n` nodes. The nodes are labeled from `0` to `n - 1`. You are given a **0-indexed** integer array `parents` representing the tree, where `parents[i]` is the parent of node `i`. Since node `0` is the root, `parents[0] == -1`.

Each node has a **score**. To find the score of a node, consider if the node and the edges connected to it were **removed**. The tree would become one or more **non-empty** subtrees. The **size** of a subtree is the number of the nodes in it. The **score** of the node is the **product of the sizes** of all those subtrees.

Return _the **number** of nodes that have the **highest score**_.

**Example 1:**

**Input:** parents = \[-1,2,0,2,0\]
**Output:** 3
**Explanation:**
- The score of node 0 is: 3 \* 1 = 3
- The score of node 1 is: 4 = 4
- The score of node 2 is: 1 \* 1 \* 2 = 2
- The score of node 3 is: 4 = 4
- The score of node 4 is: 4 = 4
The highest score is 4, and three nodes (node 1, node 3, and node 4) have the highest score.

**Example 2:**

**Input:** parents = \[-1,2,0\]
**Output:** 2
**Explanation:**
- The score of node 0 is: 2 = 2
- The score of node 1 is: 2 = 2
- The score of node 2 is: 1 \* 1 = 1
The highest score is 2, and two nodes (node 0 and node 1) have the highest score.

**Constraints:**

*   `n == parents.length`
*   `2 <= n <= 105`
*   `parents[0] == -1`
*   `0 <= parents[i] <= n - 1` for `i != 0`
*   `parents` represents a valid binary tree.

## A solution in Java

```java
import java.util.ArrayList;
import java.util.Collections;

public int eliminateMonsters(int[] dist, int[] speed) {
    int n = dist.length;
    ArrayList<Double> timeToReach = new ArrayList<>();
    for (int i = 0; i < n; ++i) {
        timeToReach.add(dist[i] / (double) speed[i]);
    }
    Collections.sort(timeToReach);
    int monstersEliminated = 0;
    for (int i = 0; i < n; ++i) {
        if (monstersEliminated < timeToReach.get(i)) {
            monstersEliminated++;
        }
    }
    return monstersEliminated;
}
```
1. First, create an array `time_to_reach` that stores the time required for each monster to reach the city by dividing the distance by the speed.
2. Sort the `time_to_reach` array in ascending order.
3. Initialize a variable `monsters_eliminated` to zero.
4. Loop through the sorted `time_to_reach` array, and for each element, compare it with the current value of `monsters_eliminated`. If the element is greater, increase the `monsters_eliminated` by 1.
5. Return the `monsters_eliminated` variable as the maximum number of monsters that can be eliminated before losing the game.

The intuition behind the algorithm is by eliminating monsters in the order of their arrival time, we can ensure to eliminate as many monsters as possible before any of them reaches the city. As we progress through the sorted times, we check if we have enough time to eliminate the current monster before it reaches the city. If we do, we increase the count of eliminated monsters.

## A solution in C++

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

int eliminateMonsters(std::vector<int>& dist, std::vector<int>& speed) {
    int n = dist.size();
    std::vector<double> time_to_reach(n);
    for (int i = 0; i < n; ++i) {
        time_to_reach[i] = dist[i] / static_cast<double>(speed[i]);
    }
    std::sort(time_to_reach.begin(), time_to_reach.end());
    int monsters_eliminated = 0;
    for (int i = 0; i < n; ++i) {
        if (monsters_eliminated < time_to_reach[i]) {
            monsters_eliminated++;
        }
    }
    return monsters_eliminated;
}
```
1. First, create an array `time_to_reach` that stores the time required for each monster to reach the city by dividing the distance by the speed.
2. Sort the `time_to_reach` array in ascending order.
3. Initialize a variable `monsters_eliminated` to zero.
4. Loop through the sorted `time_to_reach` array, and for each element, compare it with the current value of `monsters_eliminated`. If the element is greater, increase the `monsters_eliminated` by 1.
5. Return the `monsters_eliminated` variable as the maximum number of monsters that can be eliminated before losing the game.

The intuition behind the algorithm is by eliminating monsters in the order of their arrival time, we can ensure to eliminate as many monsters as possible before any of them reaches the city. As we progress through the sorted times, we check if we have enough time to eliminate the current monster before it reaches the city. If we do, we increase the count of eliminated monsters.

## A solution in Python

```python
def eliminate_monsters(dist, speed):
    n = len(dist)
    time_to_reach = sorted(dist[i] / speed[i] for i in range(n))
    monsters_eliminated = 0
    for time in time_to_reach:
        if monsters_eliminated < time:
            monsters_eliminated += 1
    return monsters_eliminated
```
1. First, create an array `time_to_reach` that stores the time required for each monster to reach the city by dividing the distance by the speed.
2. Sort the `time_to_reach` array in ascending order.
3. Initialize a variable `monsters_eliminated` to zero.
4. Loop through the sorted `time_to_reach` array, and for each element, compare it with the current value of `monsters_eliminated`. If the element is greater, increase the `monsters_eliminated` by 1.
5. Return the `monsters_eliminated` variable as the maximum number of monsters that can be eliminated before losing the game.

The intuition behind the algorithm is by eliminating monsters in the order of their arrival time, we can ensure to eliminate as many monsters as possible before any of them reaches the city. As we progress through the sorted times, we check if we have enough time to eliminate the current monster before it reaches the city. If we do, we increase the count of eliminated monsters.

## A solution in Javascript

```javascript
function eliminateMonsters(dist, speed) {
    const n = dist.length;
    const timeToReach = dist.map((distance, i) => distance / speed[i]).sort((a, b) => a - b);
    let monstersEliminated = 0;
    for (let i = 0; i < n; ++i) {
        if (monstersEliminated < timeToReach[i]) {
            monstersEliminated++;
        }
    }
    return monstersEliminated;
}
```
1. First, create an array `time_to_reach` that stores the time required for each monster to reach the city by dividing the distance by the speed.
2. Sort the `time_to_reach` array in ascending order.
3. Initialize a variable `monsters_eliminated` to zero.
4. Loop through the sorted `time_to_reach` array, and for each element, compare it with the current value of `monsters_eliminated`. If the element is greater, increase the `monsters_eliminated` by 1.
5. Return the `monsters_eliminated` variable as the maximum number of monsters that can be eliminated before losing the game.

The intuition behind the algorithm is by eliminating monsters in the order of their arrival time, we can ensure to eliminate as many monsters as possible before any of them reaches the city. As we progress through the sorted times, we check if we have enough time to eliminate the current monster before it reaches the city. If we do, we increase the count of eliminated monsters.


# Parallel Courses III

- slug: parallel-courses-iii
- difficulty: Hard

You are given an integer `n`, which indicates that there are `n` courses labeled from `1` to `n`. You are also given a 2D integer array `relations` where `relations[j] = [prevCoursej, nextCoursej]` denotes that course `prevCoursej` has to be completed **before** course `nextCoursej` (prerequisite relationship). Furthermore, you are given a **0-indexed** integer array `time` where `time[i]` denotes how many **months** it takes to complete the `(i+1)th` course.

You must find the **minimum** number of months needed to complete all the courses following these rules:

*   You may start taking a course at **any time** if the prerequisites are met.
*   **Any number of courses** can be taken at the **same time**.

Return _the **minimum** number of months needed to complete all the courses_.

**Note:** The test cases are generated such that it is possible to complete every course (i.e., the graph is a directed acyclic graph).

**Example 1:**

**Input:** n = 3, relations = \[\[1,3\],\[2,3\]\], time = \[3,2,5\]
**Output:** 8
**Explanation:** The figure above represents the given graph and the time required to complete each course.
We start course 1 and course 2 simultaneously at month 0.
Course 1 takes 3 months and course 2 takes 2 months to complete respectively.
Thus, the earliest time we can start course 3 is at month 3, and the total time required is 3 + 5 = 8 months.

**Example 2:**

**Input:** n = 5, relations = \[\[1,5\],\[2,5\],\[3,5\],\[3,4\],\[4,5\]\], time = \[1,2,3,4,5\]
**Output:** 12
**Explanation:** The figure above represents the given graph and the time required to complete each course.
You can start courses 1, 2, and 3 at month 0.
You can complete them after 1, 2, and 3 months respectively.
Course 4 can be taken only after course 3 is completed, i.e., after 3 months. It is completed after 3 + 4 = 7 months.
Course 5 can be taken only after courses 1, 2, 3, and 4 have been completed, i.e., after max(1,2,3,7) = 7 months.
Thus, the minimum time needed to complete all the courses is 7 + 5 = 12 months.

**Constraints:**

*   `1 <= n <= 5 * 104`
*   `0 <= relations.length <= min(n * (n - 1) / 2, 5 * 104)`
*   `relations[j].length == 2`
*   `1 <= prevCoursej, nextCoursej <= n`
*   `prevCoursej != nextCoursej`
*   All the pairs `[prevCoursej, nextCoursej]` are **unique**.
*   `time.length == n`
*   `1 <= time[i] <= 104`
*   The given graph is a directed acyclic graph.

## A solution in Java

```java
public int count_good_digit_strings(int n) {
    final int mod = (int)1e9 + 7;
    int even_digits = 5, prime_digits = 4;
    long total = 1;
    for (int i = 0; i < n; ++i) {
        total = (total * (i % 2 == 0 ? even_digits : prime_digits)) % mod;
    }
    return (int)total;
}
```
The algorithm counts good digit strings of length n. There are 5 even digits (0, 2, 4, 6, 8) and 4 prime digits (2, 3, 5, 7). We initialize the count of good digit strings with a value of 1.

We then loop through the range [0, n). For each index i, if i is even, we multiply the total count by the number of even digits, and if i is odd, we multiply it by the number of prime digits. This takes into account all possible combinations of good digit strings.

After iterating through the range, we return the total count modulo 1e9 + 7. This is done to keep the result within a specified range and prevent integer overflow.

## A solution in C++

```cpp
int count_good_digit_strings(int n) {
    const int mod = 1e9 + 7;
    long long even_digits = 5, prime_digits = 4, total = 1;
    for (int i = 0; i < n; ++i) {
        total = (total * (i % 2 == 0 ? even_digits : prime_digits)) % mod;
    }
    return total;
}
```
The algorithm counts good digit strings of length n. There are 5 even digits (0, 2, 4, 6, 8) and 4 prime digits (2, 3, 5, 7). We initialize the count of good digit strings with a value of 1.

We then loop through the range [0, n). For each index i, if i is even, we multiply the total count by the number of even digits, and if i is odd, we multiply it by the number of prime digits. This takes into account all possible combinations of good digit strings.

After iterating through the range, we return the total count modulo 1e9 + 7. This is done to keep the result within a specified range and prevent integer overflow.

## A solution in Python

```python
def count_good_digit_strings(n):
    mod = 10 ** 9 + 7
    even_digits, prime_digits = 5, 4
    total = 1
    for i in range(n):
        total = total * (even_digits if i % 2 == 0 else prime_digits) % mod
    return total
```
The algorithm counts good digit strings of length n. There are 5 even digits (0, 2, 4, 6, 8) and 4 prime digits (2, 3, 5, 7). We initialize the count of good digit strings with a value of 1.

We then loop through the range [0, n). For each index i, if i is even, we multiply the total count by the number of even digits, and if i is odd, we multiply it by the number of prime digits. This takes into account all possible combinations of good digit strings.

After iterating through the range, we return the total count modulo 1e9 + 7. This is done to keep the result within a specified range and prevent integer overflow.

## A solution in Javascript

```javascript
function count_good_digit_strings(n) {
    const mod = 1e9 + 7;
    let even_digits = 5, prime_digits = 4, total = 1;
    for (let i = 0; i < n; ++i) {
        total = (total * (i % 2 === 0 ? even_digits : prime_digits)) % mod;
    }
    return total;
}
```
The algorithm counts good digit strings of length n. There are 5 even digits (0, 2, 4, 6, 8) and 4 prime digits (2, 3, 5, 7). We initialize the count of good digit strings with a value of 1.

We then loop through the range [0, n). For each index i, if i is even, we multiply the total count by the number of even digits, and if i is odd, we multiply it by the number of prime digits. This takes into account all possible combinations of good digit strings.

After iterating through the range, we return the total count modulo 1e9 + 7. This is done to keep the result within a specified range and prevent integer overflow.


# Minimum Cost to Separate Sentence Into Rows

- slug: minimum-cost-to-separate-sentence-into-rows
- difficulty: Medium

You are given a string `sentence` containing words separated by spaces, and an integer `k`. Your task is to separate `sentence` into **rows** where the number of characters in each row is **at most** `k`. You may assume that `sentence` does not begin or end with a space, and the words in `sentence` are separated by a single space.

You can split `sentence` into rows by inserting line breaks between words in `sentence`. A word **cannot** be split between two rows. Each word must be used exactly once, and the word order cannot be rearranged. Adjacent words in a row should be separated by a single space, and rows should not begin or end with spaces.

The **cost** of a row with length `n` is `(k - n)2`, and the **total cost** is the sum of the **costs** for all rows **except** the last one.

*   For example if `sentence = "i love leetcode "` and `k = 12`:
    *   Separating `sentence` into `"i "`, `"love "`, and `"leetcode "` has a cost of `(12 - 1)2 + (12 - 4)2 = 185`.
    *   Separating `sentence` into `"i love "`, and `"leetcode "` has a cost of `(12 - 6)2 = 36`.
    *   Separating `sentence` into `"i "`, and `"love leetcode "` is not possible because the length of `"love leetcode "` is greater than `k`.

Return _the **minimum** possible total cost of separating_ `sentence` _into rows._

**Example 1:**

**Input:** sentence =  "i love leetcode ", k = 12
**Output:** 36
**Explanation:**
Separating sentence into  "i ",  "love ", and  "leetcode " has a cost of (12 - 1)2 + (12 - 4)2 = 185.
Separating sentence into  "i love ", and  "leetcode " has a cost of (12 - 6)2 = 36.
Separating sentence into  "i ",  "love leetcode " is not possible because  "love leetcode " has length 13.
36 is the minimum possible total cost so return it.

**Example 2:**

**Input:** sentence =  "apples and bananas taste great ", k = 7
**Output:** 21
**Explanation**
Separating sentence into  "apples ",  "and ",  "bananas ",  "taste ", and  "great " has a cost of (7 - 6)2 + (7 - 3)2 + (7 - 7)2 + (7 - 5)2 \= 21.
21 is the minimum possible total cost so return it.

**Example 3:**

**Input:** sentence =  "a ", k = 5
**Output:** 0
**Explanation:**
The cost of the last row is not included in the total cost, and since there is only one row, return 0.

**Constraints:**

*   `1 <= sentence.length <= 5000`
*   `1 <= k <= 5000`
*   The length of each word in `sentence` is at most `k`.
*   `sentence` consists of only lowercase English letters and spaces.
*   `sentence` does not begin or end with a space.
*   Words in `sentence` are separated by a single space.

## A solution in Java

```java
import java.util.*;

public int minCost(String sentence, int k) {
	String[] words = sentence.split(" ");
	int[] dp = new int[words.length + 1];
	Arrays.fill(dp, Integer.MAX_VALUE);
	dp[0] = 0;
	for (int i = 0; i < words.length; i++) {
		int length = 0;
		for (int j = i; j >= 0; j--) {
			length += words[j].length();
			if (length + (i - j) <= k) {
				dp[i + 1] = Math.min(dp[i + 1], dp[j] + (k - length - (i - j)) * (k - length - (i - j)));
			} else {
				break;
			}
			length += 1;
		}
	}
	return dp[dp.length - 1];
}
```
1. Split `sentence` into words separated by spaces.
2. Initialize the dynamic programming table `dp` to store the minimum total cost of splitting the `i` first words. `dp[0] = 0`.
3. For each word with index `i` in the smaller string, calculate the cost for putting it in a single row with some of the previous words. This is done by iterating backwards through the words from `i`, joining consecutive words one at a time until the row length is greater than `k`.
4. If the row length is less or equal to `k`, calculate the row cost for this combination of words and update `dp[i + 1] = min(dp[i + 1], dp[j] + cost)`. Otherwise, break the inner loop since adding more words will only make the row length even larger.
5. Return the last value in `dp`, which represents the minimum total cost for splitting the entire sentence into rows.

## A solution in C++

```cpp
#include <vector>
#include <string>
#include <limits>

using namespace std;

int minCost(string sentence, int k) {
    vector<string> words;
    string word;
    for (const char c : sentence) {
        if (c == ' ') {
            words.push_back(word);
            word.clear();
        } else {
            word.push_back(c);
        }
    }
    words.push_back(word);
    vector<int> dp(words.size() + 1, numeric_limits<int>::max());
    dp[0] = 0;
    for (int i = 0; i < words.size(); ++i) {
        int length = 0;
        for (int j = i; j >= 0; --j) {
            length += words[j].size();
            if (length + (i - j) <= k) {
                dp[i + 1] = min(dp[i + 1], dp[j] + (k - length - (i - j)) * (k - length - (i - j)));
            } else {
                break;
            }
            length += 1;
        }
    }
    return dp.back();
}
```
1. Split `sentence` into words separated by spaces.
2. Initialize the dynamic programming table `dp` to store the minimum total cost of splitting the `i` first words. `dp[0] = 0`.
3. For each word with index `i` in the smaller string, calculate the cost for putting it in a single row with some of the previous words. This is done by iterating backwards through the words from `i`, joining consecutive words one at a time until the row length is greater than `k`.
4. If the row length is less or equal to `k`, calculate the row cost for this combination of words and update `dp[i + 1] = min(dp[i + 1], dp[j] + cost)`. Otherwise, break the inner loop since adding more words will only make the row length even larger.
5. Return the last value in `dp`, which represents the minimum total cost for splitting the entire sentence into rows.

## A solution in Python

```python
def minCost(sentence: str, k: int) -> int:
    words = sentence.split()
    dp = [float('inf')] * (len(words) + 1)
    dp[0] = 0
    for i in range(len(words)):
        length = 0
        j = i
        while j >= 0:
            length += len(words[j])
            if length + (i - j) <= k:
                dp[i + 1] = min(dp[i + 1], dp[j] + (k - length - (i - j)) * (k - length - (i - j)))
            else:
                break
            length += 1
            j -= 1
    return dp[-1]
```
1. Split `sentence` into words separated by spaces.
2. Initialize the dynamic programming table `dp` to store the minimum total cost of splitting the `i` first words. `dp[0] = 0`.
3. For each word with index `i` in the smaller string, calculate the cost for putting it in a single row with some of the previous words. This is done by iterating backwards through the words from `i`, joining consecutive words one at a time until the row length is greater than `k`.
4. If the row length is less or equal to `k`, calculate the row cost for this combination of words and update `dp[i + 1] = min(dp[i + 1], dp[j] + cost)`. Otherwise, break the inner loop since adding more words will only make the row length even larger.
5. Return the last value in `dp`, which represents the minimum total cost for splitting the entire sentence into rows.

## A solution in Javascript

```javascript
function minCost(sentence, k) {
    const words = sentence.split(' ');
    const dp = new Array(words.length + 1).fill(Infinity);
    dp[0] = 0;
    for (let i = 0; i < words.length; ++i) {
        let length = 0;
        for (let j = i; j >= 0; --j) {
            length += words[j].length;
            if (length + (i - j) <= k) {
                dp[i + 1] = Math.min(dp[i + 1], dp[j] + (k - length - (i - j)) * (k - length - (i - j)));
            } else {
                break;
            }
            length += 1;
        }
    }
    return dp[dp.length - 1];
}
```
1. Split `sentence` into words separated by spaces.
2. Initialize the dynamic programming table `dp` to store the minimum total cost of splitting the `i` first words. `dp[0] = 0`.
3. For each word with index `i` in the smaller string, calculate the cost for putting it in a single row with some of the previous words. This is done by iterating backwards through the words from `i`, joining consecutive words one at a time until the row length is greater than `k`.
4. If the row length is less or equal to `k`, calculate the row cost for this combination of words and update `dp[i + 1] = min(dp[i + 1], dp[j] + cost)`. Otherwise, break the inner loop since adding more words will only make the row length even larger.
5. Return the last value in `dp`, which represents the minimum total cost for splitting the entire sentence into rows.


# Kth Distinct String in an Array

- slug: kth-distinct-string-in-an-array
- difficulty: Easy

A **distinct string** is a string that is present only **once** in an array.

Given an array of strings `arr`, and an integer `k`, return _the_ `kth` _**distinct string** present in_ `arr`. If there are **fewer** than `k` distinct strings, return _an **empty string**_ `" "`.

Note that the strings are considered in the **order in which they appear** in the array.

**Example 1:**

**Input:** arr = \[ "d ", "b ", "c ", "b ", "c ", "a "\], k = 2
**Output:**  "a "
**Explanation:**
The only distinct strings in arr are  "d " and  "a ".
 "d " appears 1st, so it is the 1st distinct string.
 "a " appears 2nd, so it is the 2nd distinct string.
Since k == 2,  "a " is returned.

**Example 2:**

**Input:** arr = \[ "aaa ", "aa ", "a "\], k = 1
**Output:**  "aaa "
**Explanation:**
All strings in arr are distinct, so the 1st string  "aaa " is returned.

**Example 3:**

**Input:** arr = \[ "a ", "b ", "a "\], k = 3
**Output:**  " "
**Explanation:**
The only distinct string is  "b ". Since there are fewer than 3 distinct strings, we return an empty string  " ".

**Constraints:**

*   `1 <= k <= arr.length <= 1000`
*   `1 <= arr[i].length <= 5`
*   `arr[i]` consists of lowercase English letters.

## A solution in Java

```java
import java.util.HashMap;

public boolean isGoodString(String s) {
    HashMap<Character, Integer> freq_map = new HashMap<>();
    for (char c : s.toCharArray()) {
        freq_map.put(c, freq_map.getOrDefault(c, 0) + 1);
    }

    int count = freq_map.values().iterator().next();
    for (int value : freq_map.values()) {
        if (value != count) {
            return false;
        }
    }
    return true;
}
```
The algorithm for each implementation is as follows:

1. Create a dictionary/hash map to store the frequencies of each character in the string.
2. Iterate through the input string and update the dictionary with the character frequencies.
3. Get the count of the first character in the dictionary.
4. Iterate through the dictionary, compare the count of each character to the initial count obtained in step 3. If the counts are not equal, return false. In the end, if all counts are equal, return true.

This algorithm works in O(n) time complexity, where n is the length of the input string, since it traverses the input string and dictionary in linear time.

## A solution in C++

```cpp
#include <string>
#include <unordered_map>

bool isGoodString(const std::string& s) {
    std::unordered_map<char, int> freq_map;
    for (char c : s) {
        freq_map[c]++;
    }

    int count = freq_map.begin()->second;
    for (const auto& entry : freq_map) {
        if (entry.second != count) {
            return false;
        }
    }
    return true;
}
```
The algorithm for each implementation is as follows:

1. Create a dictionary/hash map to store the frequencies of each character in the string.
2. Iterate through the input string and update the dictionary with the character frequencies.
3. Get the count of the first character in the dictionary.
4. Iterate through the dictionary, compare the count of each character to the initial count obtained in step 3. If the counts are not equal, return false. In the end, if all counts are equal, return true.

This algorithm works in O(n) time complexity, where n is the length of the input string, since it traverses the input string and dictionary in linear time.

## A solution in Python

```python
def is_good_string(s: str) -> bool:
    freq_map = {}
    for c in s:
        if c in freq_map:
            freq_map[c] += 1
        else:
            freq_map[c] = 1

    count = next(iter(freq_map.values()))
    for value in freq_map.values():
        if value != count:
            return False
    return True
```
The algorithm for each implementation is as follows:

1. Create a dictionary/hash map to store the frequencies of each character in the string.
2. Iterate through the input string and update the dictionary with the character frequencies.
3. Get the count of the first character in the dictionary.
4. Iterate through the dictionary, compare the count of each character to the initial count obtained in step 3. If the counts are not equal, return false. In the end, if all counts are equal, return true.

This algorithm works in O(n) time complexity, where n is the length of the input string, since it traverses the input string and dictionary in linear time.

## A solution in Javascript

```javascript
function isGoodString(s) {
    let freqMap = new Map();
    for (let c of s) {
        if (freqMap.has(c)) {
            freqMap.set(c, freqMap.get(c) + 1);
        } else {
            freqMap.set(c, 1);
        }
    }

    let count = freqMap.values().next().value;
    for (let value of freqMap.values()) {
        if (value !== count) {
            return false;
        }
    }
    return true;
}
```
The algorithm for each implementation is as follows:

1. Create a dictionary/hash map to store the frequencies of each character in the string.
2. Iterate through the input string and update the dictionary with the character frequencies.
3. Get the count of the first character in the dictionary.
4. Iterate through the dictionary, compare the count of each character to the initial count obtained in step 3. If the counts are not equal, return false. In the end, if all counts are equal, return true.

This algorithm works in O(n) time complexity, where n is the length of the input string, since it traverses the input string and dictionary in linear time.


# Two Best Non-Overlapping Events

- slug: two-best-non-overlapping-events
- difficulty: Medium

You are given a **0-indexed** 2D integer array of `events` where `events[i] = [startTimei, endTimei, valuei]`. The `ith` event starts at `startTimei` and ends at `endTimei`, and if you attend this event, you will receive a value of `valuei`. You can choose **at most** **two** **non-overlapping** events to attend such that the sum of their values is **maximized**.

Return _this **maximum** sum._

Note that the start time and end time is **inclusive**: that is, you cannot attend two events where one of them starts and the other ends at the same time. More specifically, if you attend an event with end time `t`, the next event must start at or after `t + 1`.

**Example 1:**

**Input:** events = \[\[1,3,2\],\[4,5,2\],\[2,4,3\]\]
**Output:** 4
**Explanation:** Choose the green events, 0 and 1 for a sum of 2 + 2 = 4.

**Example 2:**

**Input:** events = \[\[1,3,2\],\[4,5,2\],\[1,5,5\]\]
**Output:** 5
**Explanation:** Choose event 2 for a sum of 5.

**Example 3:**

**Input:** events = \[\[1,5,3\],\[1,5,1\],\[6,6,5\]\]
**Output:** 8
**Explanation:** Choose events 0 and 2 for a sum of 3 + 5 = 8.

**Constraints:**

*   `2 <= events.length <= 105`
*   `events[i].length == 3`
*   `1 <= startTimei <= endTimei <= 109`
*   `1 <= valuei <= 106`

## A solution in Java

```java
public int findChair(int[][] times, int targetFriend) {
    int n = times.length;
    List<int[]> events = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        events.add(new int[]{times[i][0], i});
        events.add(new int[]{times[i][1], ~i});
    }
    events.sort((a, b) -> Integer.compare(a[0], b[0]));
    int[] chairs = new int[n];
    TreeSet<Integer> availableChairs = new TreeSet<>();
    for (int i = 0; i < n; i++) {
        availableChairs.add(i);
    }
    for (int[] event : events) {
        if (event[1] >= 0) {
            int friendId = event[1];
            chairs[friendId] = availableChairs.first();
            availableChairs.remove(availableChairs.first());
            if (friendId == targetFriend) {
                return chairs[friendId];
            }
        } else {
            int friendId = ~event[1];
            availableChairs.add(chairs[friendId]);
        }
    }
    return -1;
}
```
The main algorithm idea is to use events to keep track of arrival and leaving moments. For each person, we add two events: one for arrival (with a positive or zero friend ID) and one for leaving (with a negative friend ID).

1. Create a list called `events`, adding arrival and leave events for each friend. The length of `events` will be 2 * n.
2. Sort the events by ascending time.
3. Create an array called `chairs` with -1 values and length of n.
4. Create a sorted set (C++, Java), list (Python), or array (JavaScript) called `availableChairs` with integer values from 0 to n - 1.
5. Iterate through the events in order. At each event:
   - If friend_id is non-negative, it's an arrival event:
     - Assign the first element of the `availableChairs`.
     - Remove that element from `availableChairs`.
     - If the arrived friend is `targetFriend`, return the assigned chair.
   - If friend_id is negative, it's a leaving event:
     - Add the leaving friend's chair back into `availableChairs`.
     - Then sort the `availableChairs`.

6. If `targetFriend` has not yet arrived, return -1.

As all arrival times are distinct, there is no need to worry about tie-breaking for chair allocation.

## A solution in C++

```cpp
int find_chair(vector<vector<int>>& times, int target_friend) {
    int n = times.size();
    vector<pair<int, int>> events;
    for (int i = 0; i < n; ++i) {
        events.push_back({times[i][0], i});
        events.push_back({times[i][1], ~i});
    }
    sort(events.begin(), events.end());
    vector<int> chairs(n, -1);
    set<int> available_chairs;
    for (int i = 0; i < n; ++i) {
        available_chairs.insert(i);
    }
    for (auto& event : events) {
        if (event.second >= 0) {
            int friend_id = event.second;
            chairs[friend_id] = *available_chairs.begin();
            available_chairs.erase(available_chairs.begin());
            if (friend_id == target_friend) {
                return chairs[friend_id];
            }
        } else {
            int friend_id = ~event.second;
            available_chairs.insert(chairs[friend_id]);
        }
    }
    return -1;
}
```
The main algorithm idea is to use events to keep track of arrival and leaving moments. For each person, we add two events: one for arrival (with a positive or zero friend ID) and one for leaving (with a negative friend ID).

1. Create a list called `events`, adding arrival and leave events for each friend. The length of `events` will be 2 * n.
2. Sort the events by ascending time.
3. Create an array called `chairs` with -1 values and length of n.
4. Create a sorted set (C++, Java), list (Python), or array (JavaScript) called `availableChairs` with integer values from 0 to n - 1.
5. Iterate through the events in order. At each event:
   - If friend_id is non-negative, it's an arrival event:
     - Assign the first element of the `availableChairs`.
     - Remove that element from `availableChairs`.
     - If the arrived friend is `targetFriend`, return the assigned chair.
   - If friend_id is negative, it's a leaving event:
     - Add the leaving friend's chair back into `availableChairs`.
     - Then sort the `availableChairs`.

6. If `targetFriend` has not yet arrived, return -1.

As all arrival times are distinct, there is no need to worry about tie-breaking for chair allocation.

## A solution in Python

```python
def find_chair(times, target_friend):
    n = len(times)
    events = []
    for i, (arrival, leaving) in enumerate(times):
        events.append((arrival, i))
        events.append((leaving, ~i))
    events.sort()
    chairs = [-1] * n
    available_chairs = sorted(range(n))
    for time, friend_id in events:
        if friend_id >= 0:
            chairs[friend_id] = available_chairs.pop(0)
            if friend_id == target_friend:
                return chairs[friend_id]
        else:
            available_chairs.append(chairs[~friend_id])
            available_chairs.sort()
    return -1
```
The main algorithm idea is to use events to keep track of arrival and leaving moments. For each person, we add two events: one for arrival (with a positive or zero friend ID) and one for leaving (with a negative friend ID).

1. Create a list called `events`, adding arrival and leave events for each friend. The length of `events` will be 2 * n.
2. Sort the events by ascending time.
3. Create an array called `chairs` with -1 values and length of n.
4. Create a sorted set (C++, Java), list (Python), or array (JavaScript) called `availableChairs` with integer values from 0 to n - 1.
5. Iterate through the events in order. At each event:
   - If friend_id is non-negative, it's an arrival event:
     - Assign the first element of the `availableChairs`.
     - Remove that element from `availableChairs`.
     - If the arrived friend is `targetFriend`, return the assigned chair.
   - If friend_id is negative, it's a leaving event:
     - Add the leaving friend's chair back into `availableChairs`.
     - Then sort the `availableChairs`.

6. If `targetFriend` has not yet arrived, return -1.

As all arrival times are distinct, there is no need to worry about tie-breaking for chair allocation.

## A solution in Javascript

```javascript
function findChair(times, targetFriend) {
    const n = times.length;
    const events = [];
    for (let i = 0; i < n; i++) {
        events.push([times[i][0], i]);
        events.push([times[i][1], ~i]);
    }
    events.sort((a, b) => a[0] - b[0]);
    const chairs = new Array(n).fill(-1);
    const availableChairs = [...Array(n).keys()];
    for (const [time, friendId] of events) {
        if (friendId >= 0) {
            chairs[friendId] = availableChairs.shift();
            if (friendId === targetFriend) {
                return chairs[friendId];
            }
        } else {
            availableChairs.push(chairs[~friendId]);
            availableChairs.sort((a, b) => a - b);
        }
    }
    return -1;
}
```
The main algorithm idea is to use events to keep track of arrival and leaving moments. For each person, we add two events: one for arrival (with a positive or zero friend ID) and one for leaving (with a negative friend ID).

1. Create a list called `events`, adding arrival and leave events for each friend. The length of `events` will be 2 * n.
2. Sort the events by ascending time.
3. Create an array called `chairs` with -1 values and length of n.
4. Create a sorted set (C++, Java), list (Python), or array (JavaScript) called `availableChairs` with integer values from 0 to n - 1.
5. Iterate through the events in order. At each event:
   - If friend_id is non-negative, it's an arrival event:
     - Assign the first element of the `availableChairs`.
     - Remove that element from `availableChairs`.
     - If the arrived friend is `targetFriend`, return the assigned chair.
   - If friend_id is negative, it's a leaving event:
     - Add the leaving friend's chair back into `availableChairs`.
     - Then sort the `availableChairs`.

6. If `targetFriend` has not yet arrived, return -1.

As all arrival times are distinct, there is no need to worry about tie-breaking for chair allocation.


# Plates Between Candles

- slug: plates-between-candles
- difficulty: Medium

There is a long table with a line of plates and candles arranged on top of it. You are given a **0-indexed** string `s` consisting of characters `'*'` and `'|'` only, where a `'*'` represents a **plate** and a `'|'` represents a **candle**.

You are also given a **0-indexed** 2D integer array `queries` where `queries[i] = [lefti, righti]` denotes the **substring** `s[lefti...righti]` (**inclusive**). For each query, you need to find the **number** of plates **between candles** that are **in the substring**. A plate is considered **between candles** if there is at least one candle to its left **and** at least one candle to its right **in the substring**.

*   For example, `s = "||**||**|* "`, and a query `[3, 8]` denotes the substring `"*||******| "`. The number of plates between candles in this substring is `2`, as each of the two plates has at least one candle **in the substring** to its left **and** right.

Return _an integer array_ `answer` _where_ `answer[i]` _is the answer to the_ `ith` _query_.

**Example 1:**

**Input:** s =  "\*\*|\*\*|\*\*\*| ", queries = \[\[2,5\],\[5,9\]\]
**Output:** \[2,3\]
**Explanation:**
- queries\[0\] has two plates between candles.
- queries\[1\] has three plates between candles.

**Example 2:**

**Input:** s =  "\*\*\*|\*\*|\*\*\*\*\*|\*\*||\*\*|\* ", queries = \[\[1,17\],\[4,5\],\[14,17\],\[5,11\],\[15,16\]\]
**Output:** \[9,0,0,0,0\]
**Explanation:**
- queries\[0\] has nine plates between candles.
- The other queries have zero plates between candles.

**Constraints:**

*   `3 <= s.length <= 105`
*   `s` consists of `'*'` and `'|'` characters.
*   `1 <= queries.length <= 105`
*   `queries[i].length == 2`
*   `0 <= lefti <= righti < s.length`

## A solution in Java

```java
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

public class Solution {
    public List<List<Integer>> splitPainting(int[][] segments) {
        TreeMap<Integer, Integer> changes = new TreeMap<>();
        for (int[] segment : segments) {
            changes.put(segment[0], changes.getOrDefault(segment[0], 0) + segment[2]);
            changes.put(segment[1], changes.getOrDefault(segment[1], 0) - segment[2]);
        }

        List<List<Integer>> result = new ArrayList<>();
        int start = 0, color_sum = 0;
        for (int key : changes.keySet()) {
            if (start != key) {
                if (color_sum != 0) {
                    List<Integer> temp = new ArrayList<>();
                    temp.add(start);
                    temp.add(key);
                    temp.add(color_sum);
                    result.add(temp);
                }
                start = key;
            }
            color_sum += changes.getOrDefault(key, 0);
        }

        return result;
    }
}
```
1. Create a map (called "changes") to store the color changes (both positive and negative) at each point (key) on the number line.
2. Loop through the given segments, and for each segment, add the color value to the starting point and subtract it from the ending point in the changes map.
3. Initialize the "result" array and variables "start" and "color_sum" to store the start of a new segment and the sum of mixed colors of the current segment, respectively.
4. Loop through the sorted keys in changes map. For each key:
   a) If the current key is not equal to the start, then check if color_sum is not zero. If true, push the segment [start, key, color_sum] into the result array.
   b) Update the start variable to the current key and add the color change value of the current key to color_sum.
5. Return the result array containing the non-overlapping segments with mixed color sums.

This algorithm effectively compresses the overlapping segments into non-overlapping segments with the summed color values, using a map to record the color changes at each point, resulting in a representation of the finished painting.

## A solution in C++

```cpp
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

vector<vector<int>> splitPainting(vector<vector<int>>& segments) {
    map<int, int> changes;
    for (auto& segment : segments) {
        changes[segment[0]] += segment[2];
        changes[segment[1]] -= segment[2];
    }

    vector<vector<int>> result;
    int start = 0, color_sum = 0;
    for (auto& change : changes) {
        if (start != change.first) {
            if (color_sum) result.push_back({start, change.first, color_sum});
            start = change.first;
        }
        color_sum += change.second;
    }

    return result;
}
```
1. Create a map (called "changes") to store the color changes (both positive and negative) at each point (key) on the number line.
2. Loop through the given segments, and for each segment, add the color value to the starting point and subtract it from the ending point in the changes map.
3. Initialize the "result" array and variables "start" and "color_sum" to store the start of a new segment and the sum of mixed colors of the current segment, respectively.
4. Loop through the sorted keys in changes map. For each key:
   a) If the current key is not equal to the start, then check if color_sum is not zero. If true, push the segment [start, key, color_sum] into the result array.
   b) Update the start variable to the current key and add the color change value of the current key to color_sum.
5. Return the result array containing the non-overlapping segments with mixed color sums.

This algorithm effectively compresses the overlapping segments into non-overlapping segments with the summed color values, using a map to record the color changes at each point, resulting in a representation of the finished painting.

## A solution in Python

```python
from collections import defaultdict

def splitPainting(segments):
    changes = defaultdict(int)
    for start, end, color in segments:
        changes[start] += color
        changes[end] -= color

    result = []
    start, color_sum = 0, 0
    for key in sorted(changes.keys()):
        if start != key:
            if color_sum:
                result.append([start, key, color_sum])
            start = key
        color_sum += changes[key]

    return result
```
1. Create a map (called "changes") to store the color changes (both positive and negative) at each point (key) on the number line.
2. Loop through the given segments, and for each segment, add the color value to the starting point and subtract it from the ending point in the changes map.
3. Initialize the "result" array and variables "start" and "color_sum" to store the start of a new segment and the sum of mixed colors of the current segment, respectively.
4. Loop through the sorted keys in changes map. For each key:
   a) If the current key is not equal to the start, then check if color_sum is not zero. If true, push the segment [start, key, color_sum] into the result array.
   b) Update the start variable to the current key and add the color change value of the current key to color_sum.
5. Return the result array containing the non-overlapping segments with mixed color sums.

This algorithm effectively compresses the overlapping segments into non-overlapping segments with the summed color values, using a map to record the color changes at each point, resulting in a representation of the finished painting.

## A solution in Javascript

```javascript
function splitPainting(segments) {
    const changes = new Map();
    for (const [start, end, color] of segments) {
        changes.set(start, (changes.get(start) || 0) + color);
        changes.set(end, (changes.get(end) || 0) - color);
    }

    const result = [];
    let start = 0, color_sum = 0;
    for (const key of [...changes.keys()].sort((a, b) => a - b)) {
        if (start !== key) {
            if (color_sum) {
                result.push([start, key, color_sum]);
            }
            start = key;
        }
        color_sum += changes.get(key);
    }

    return result;
}
```
1. Create a map (called "changes") to store the color changes (both positive and negative) at each point (key) on the number line.
2. Loop through the given segments, and for each segment, add the color value to the starting point and subtract it from the ending point in the changes map.
3. Initialize the "result" array and variables "start" and "color_sum" to store the start of a new segment and the sum of mixed colors of the current segment, respectively.
4. Loop through the sorted keys in changes map. For each key:
   a) If the current key is not equal to the start, then check if color_sum is not zero. If true, push the segment [start, key, color_sum] into the result array.
   b) Update the start variable to the current key and add the color change value of the current key to color_sum.
5. Return the result array containing the non-overlapping segments with mixed color sums.

This algorithm effectively compresses the overlapping segments into non-overlapping segments with the summed color values, using a map to record the color changes at each point, resulting in a representation of the finished painting.