# Sum Game

- slug: sum-game
- difficulty: Medium

Alice and Bob take turns playing a game, with **Alice** **starting first**.

You are given a string `num` of **even length** consisting of digits and `'?'` characters. On each turn, a player will do the following if there is still at least one `'?'` in `num`:

1.  Choose an index `i` where `num[i] == '?'`.
2.  Replace `num[i]` with any digit between `'0'` and `'9'`.

The game ends when there are no more `'?'` characters in `num`.

For Bob to win, the sum of the digits in the first half of `num` must be **equal** to the sum of the digits in the second half. For Alice to win, the sums must **not be equal**.

*   For example, if the game ended with `num = "243801 "`, then Bob wins because `2+4+3 = 8+0+1`. If the game ended with `num = "243803 "`, then Alice wins because `2+4+3 != 8+0+3`.

Assuming Alice and Bob play **optimally**, return `true` _if Alice will win and_ `false` _if Bob will win_.

**Example 1:**

**Input:** num =  "5023 "
**Output:** false
**Explanation:** There are no moves to be made.
The sum of the first half is equal to the sum of the second half: 5 + 0 = 2 + 3.

**Example 2:**

**Input:** num =  "25?? "
**Output:** true
**Explanation:** Alice can replace one of the '?'s with '9' and it will be impossible for Bob to make the sums equal.

**Example 3:**

**Input:** num =  "?3295??? "
**Output:** false
**Explanation:** It can be proven that Bob will always win. One possible outcome is:
- Alice replaces the first '?' with '9'. num =  "93295??? ".
- Bob replaces one of the '?' in the right half with '9'. num =  "932959?? ".
- Alice replaces one of the '?' in the right half with '2'. num =  "9329592? ".
- Bob replaces the last '?' in the right half with '7'. num =  "93295927 ".
Bob wins because 9 + 3 + 2 + 9 = 5 + 9 + 2 + 7.

**Constraints:**

*   `2 <= num.length <= 105`
*   `num.length` is **even**.
*   `num` consists of only digits and `'?'`.

## A solution in Java

```java
public int maxAscendingSum(int[] nums) {
    int maxSum = 0, currentSum = nums[0];

    for (int i = 1; i < nums.length; ++i) {
        if (nums[i] > nums[i - 1]) {
            currentSum += nums[i];
        } else {
            maxSum = Math.max(maxSum, currentSum);
            currentSum = nums[i];
        }
    }

    return Math.max(maxSum, currentSum);
}
```
1. Initialize `maxSum` and `currentSum` as the first element of the input array.
2. Iterate through the input array, starting from the second element.
3. If the current element is greater than the previous element, add the current element to `currentSum`. Else, Compare and get the maximum between `maxSum` and `currentSum`, and set `currentSum` to the current element.
4. After iteration, compare and get the maximum between `maxSum` and `currentSum` one last time, and return the result.

## A solution in C++

```cpp
int maxAscendingSum(vector<int>& nums) {
    int maxSum = 0, currentSum = nums[0];

    for (int i = 1; i < nums.size(); ++i) {
        if (nums[i] > nums[i - 1]) {
            currentSum += nums[i];
        } else {
            maxSum = max(maxSum, currentSum);
            currentSum = nums[i];
        }
    }

    return max(maxSum, currentSum);
}
```
1. Initialize `maxSum` and `currentSum` as the first element of the input array.
2. Iterate through the input array, starting from the second element.
3. If the current element is greater than the previous element, add the current element to `currentSum`. Else, Compare and get the maximum between `maxSum` and `currentSum`, and set `currentSum` to the current element.
4. After iteration, compare and get the maximum between `maxSum` and `currentSum` one last time, and return the result.

## A solution in Python

```python
def max_ascending_sum(nums):
    max_sum = current_sum = nums[0]

    for i in range(1, len(nums)):
        if nums[i] > nums[i - 1]:
            current_sum += nums[i]
        else:
            max_sum = max(max_sum, current_sum)
            current_sum = nums[i]

    return max(max_sum, current_sum)
```
1. Initialize `maxSum` and `currentSum` as the first element of the input array.
2. Iterate through the input array, starting from the second element.
3. If the current element is greater than the previous element, add the current element to `currentSum`. Else, Compare and get the maximum between `maxSum` and `currentSum`, and set `currentSum` to the current element.
4. After iteration, compare and get the maximum between `maxSum` and `currentSum` one last time, and return the result.

## A solution in Javascript

```javascript
function maxAscendingSum(nums) {
    let maxSum = 0, currentSum = nums[0];

    for (let i = 1; i < nums.length; ++i) {
        if (nums[i] > nums[i - 1]) {
            currentSum += nums[i];
        } else {
            maxSum = Math.max(maxSum, currentSum);
            currentSum = nums[i];
        }
    }

    return Math.max(maxSum, currentSum);
}
```
1. Initialize `maxSum` and `currentSum` as the first element of the input array.
2. Iterate through the input array, starting from the second element.
3. If the current element is greater than the previous element, add the current element to `currentSum`. Else, Compare and get the maximum between `maxSum` and `currentSum`, and set `currentSum` to the current element.
4. After iteration, compare and get the maximum between `maxSum` and `currentSum` one last time, and return the result.


# Minimum Cost to Reach Destination in Time

- slug: minimum-cost-to-reach-destination-in-time
- difficulty: Hard

There is a country of `n` cities numbered from `0` to `n - 1` where **all the cities are connected** by bi-directional roads. The roads are represented as a 2D integer array `edges` where `edges[i] = [xi, yi, timei]` denotes a road between cities `xi` and `yi` that takes `timei` minutes to travel. There may be multiple roads of differing travel times connecting the same two cities, but no road connects a city to itself.

Each time you pass through a city, you must pay a passing fee. This is represented as a **0-indexed** integer array `passingFees` of length `n` where `passingFees[j]` is the amount of dollars you must pay when you pass through city `j`.

In the beginning, you are at city `0` and want to reach city `n - 1` in `maxTime` **minutes or less**. The **cost** of your journey is the **summation of passing fees** for each city that you passed through at some moment of your journey (**including** the source and destination cities).

Given `maxTime`, `edges`, and `passingFees`, return _the **minimum cost** to complete your journey, or_ `-1` _if you cannot complete it within_ `maxTime` _minutes_.

**Example 1:**

**Input:** maxTime = 30, edges = \[\[0,1,10\],\[1,2,10\],\[2,5,10\],\[0,3,1\],\[3,4,10\],\[4,5,15\]\], passingFees = \[5,1,2,20,20,3\]
**Output:** 11
**Explanation:** The path to take is 0 -> 1 -> 2 -> 5, which takes 30 minutes and has $11 worth of passing fees.

**Example 2:**

**Input:** maxTime = 29, edges = \[\[0,1,10\],\[1,2,10\],\[2,5,10\],\[0,3,1\],\[3,4,10\],\[4,5,15\]\], passingFees = \[5,1,2,20,20,3\]
**Output:** 48
**Explanation:** The path to take is 0 -> 3 -> 4 -> 5, which takes 26 minutes and has $48 worth of passing fees.
You cannot take path 0 -> 1 -> 2 -> 5 since it would take too long.

**Example 3:**

**Input:** maxTime = 25, edges = \[\[0,1,10\],\[1,2,10\],\[2,5,10\],\[0,3,1\],\[3,4,10\],\[4,5,15\]\], passingFees = \[5,1,2,20,20,3\]
**Output:** -1
**Explanation:** There is no way to reach city 5 from city 0 within 25 minutes.

**Constraints:**

*   `1 <= maxTime <= 1000`
*   `n == passingFees.length`
*   `2 <= n <= 1000`
*   `n - 1 <= edges.length <= 1000`
*   `0 <= xi, yi <= n - 1`
*   `1 <= timei <= 1000`
*   `1 <= passingFees[j] <= 1000`
*   The graph may contain multiple edges between two nodes.
*   The graph does not contain self loops.

## A solution in Java

```java
import java.util.*;

class Solution {
    public int getNumberOfBacklogOrders(int[][] orders) {
        PriorityQueue<int[]> sell = new PriorityQueue<>((a, b) -> a[0] - b[0]);
        PriorityQueue<int[]> buy = new PriorityQueue<>((a, b) -> b[0] - a[0]);

        for (int[] order : orders) {
            if (order[2] == 0) {
                while (!sell.isEmpty() && order[1] > 0 && sell.peek()[0] <= order[0]) {
                    int executedAmount = Math.min(order[1], sell.peek()[1]);
                    order[1] -= executedAmount;
                    sell.peek()[1] -= executedAmount;
                    if (sell.peek()[1] == 0) sell.poll();
                }
                if (order[1] > 0) buy.offer(order);
            } else {
                while (!buy.isEmpty() && order[1] > 0 && buy.peek()[0] >= order[0]) {
                    int executedAmount = Math.min(order[1], buy.peek()[1]);
                    order[1] -= executedAmount;
                    buy.peek()[1] -= executedAmount;
                    if (buy.peek()[1] == 0) buy.poll();
                }
                if (order[1] > 0) sell.offer(order);
            }
        }

        long res = 0;
        while (!buy.isEmpty()) res += buy.poll()[1];
        while (!sell.isEmpty()) res += sell.poll()[1];
        res %= 1_000_000_007;

        return (int) res;
    }
}
```
The algorithm uses two priority queues, one for buy orders and one for sell orders. When iterating over the input orders, for each buy order if there are sell orders that can be executed, execute them and update the current buy order amount accordingly. If the buy order still has residual amount, add it to the buy order queue. Same goes for sell orders.

After processing all input orders, the residual orders in the buy and sell queues are the ones that couldn't be executed, sum their amounts and return the result modulo 1,000,000,007.

## A solution in C++

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

int getNumberOfBacklogOrders(std::vector<std::vector<int>>& orders) {
    auto cmpSell = [](std::vector<int>& a, std::vector<int>& b) {
        return a[0] > b[0];
    };
    auto cmpBuy = [](std::vector<int>& a, std.stringvector<int>&b) {
        return a[0] < b[0];
    };

    std::priority_queue<std::vector<int>, std::vector<std::vector<int>>, decltype(cmpSell)> sell(cmpSell);
    std::priority_queue<std::vector<int>, std::vector<std::vector<int>>, decltype(cmpBuy)> buy(cmpBuy);

    for (auto& order : orders) {
        if (order[2] == 0) {
            while (!sell.empty() && order[1] > 0 && sell.top()[0] <= order[0]) {
                std::vector<int>& currOrder = sell.top();
                int executedAmount = std::min(order[1], currOrder[1]);
                order[1] -= executedAmount;
                currOrder[1] -= executedAmount;
                if (currOrder[1] == 0) {
                    sell.pop();
                }
            }
            if (order[1] > 0) {
                buy.push(order);
            }
        } else {
            while (!buy.empty() && order[1] > 0 && buy.top()[0] >= order[0]) {
                std::vector<int>& currOrder = buy.top();
                int executedAmount = std::min(order[1], currOrder[1]);
                order[1] -= executedAmount;
                currOrder[1] -= executedAmount;
                if (currOrder[1] == 0) {
                    buy.pop();
                }
            }
            if (order[1] > 0) {
                sell.push(order);
            }
        }
    }

    int64_t res = 0;
    while (!buy.empty()) {
        res += buy.top()[1];
        buy.pop();
    }
    while (!sell.empty()) {
        res += sell.top()[1];
        sell.pop();
    }

    res %= 1000000007;
    return static_cast<int>(res);
}
```
The algorithm uses two priority queues, one for buy orders and one for sell orders. When iterating over the input orders, for each buy order if there are sell orders that can be executed, execute them and update the current buy order amount accordingly. If the buy order still has residual amount, add it to the buy order queue. Same goes for sell orders.

After processing all input orders, the residual orders in the buy and sell queues are the ones that couldn't be executed, sum their amounts and return the result modulo 1,000,000,007.

## A solution in Python

```python
from heapq import heappush, heappop

def getNumberOfBacklogOrders(orders):
    buy, sell = [], []

    for price, amount, orderType in orders:
        if orderType == 0:
            while amount > 0 and sell and -sell[0][0] <= price:
                executedAmount = min(amount, sell[0][1])
                amount -= executedAmount
                sell[0] = [-sell[0][0], sell[0][1] - executedAmount]
                if sell[0][1] == 0:
                    heappop(sell)
            if amount:
                heappush(buy, [-price, amount])
        else:
            while amount > 0 and buy and buy[0][0] >= price:
                executedAmount = min(amount, buy[0][1])
                amount -= executedAmount
                buy[0] = [buy[0][0], buy[0][1] - executedAmount]
                if buy[0][1] == 0:
                    heappop(buy)
            if amount:
                heappush(sell, [-price, amount])

    res = sum(item[1] for item in buy) + sum(item[1] for item in sell)
    return res % 1000000007
```
The algorithm uses two priority queues, one for buy orders and one for sell orders. When iterating over the input orders, for each buy order if there are sell orders that can be executed, execute them and update the current buy order amount accordingly. If the buy order still has residual amount, add it to the buy order queue. Same goes for sell orders.

After processing all input orders, the residual orders in the buy and sell queues are the ones that couldn't be executed, sum their amounts and return the result modulo 1,000,000,007.

## A solution in Javascript

```javascript
function getNumberOfBacklogOrders(orders) {
    const sell = new PriorityQueue((a, b) => a[0] - b[0]);
    const buy = new PriorityQueue((a, b) => b[0] - a[0]);

    for (const order of orders) {
        const [price, amount, orderType] = order;
        let currAmount = amount;
        if (orderType === 0) {
            while (currAmount > 0 && sell.size() > 0 && sell.peek()[0] <= price) {
                const executedAmount = Math.min(currAmount, sell.peek()[1]);
                currAmount -= executedAmount;
                sell.peek()[1] -= executedAmount;
                if (sell.peek()[1] === 0) sell.pop();
            }
            if (currAmount > 0) buy.push([price, currAmount]);
        } else {
            while (currAmount > 0 && buy.size() > 0 && buy.peek()[0] >= price) {
                const executedAmount = Math.min(currAmount, buy.peek()[1]);
                currAmount -= executedAmount;
                buy.peek()[1] -= executedAmount;
                if (buy.peek()[1] === 0) buy.pop();
            }
            if (currAmount > 0) sell.push([price, currAmount]);
        }
    }

    let res = 0;
    while (buy.size() > 0) res += buy.pop()[1];
    while (sell.size() > 0) res += sell.pop()[1];

    return res % 1000000007;
}
```
The algorithm uses two priority queues, one for buy orders and one for sell orders. When iterating over the input orders, for each buy order if there are sell orders that can be executed, execute them and update the current buy order amount accordingly. If the buy order still has residual amount, add it to the buy order queue. Same goes for sell orders.

After processing all input orders, the residual orders in the buy and sell queues are the ones that couldn't be executed, sum their amounts and return the result modulo 1,000,000,007.


# Concatenation of Array

- slug: concatenation-of-array
- difficulty: Easy

Given an integer array `nums` of length `n`, you want to create an array `ans` of length `2n` where `ans[i] == nums[i]` and `ans[i + n] == nums[i]` for `0 <= i < n` (**0-indexed**).

Specifically, `ans` is the **concatenation** of two `nums` arrays.

Return _the array_ `ans`.

**Example 1:**

**Input:** nums = \[1,2,1\]
**Output:** \[1,2,1,1,2,1\]
**Explanation:** The array ans is formed as follows:
- ans = \[nums\[0\],nums\[1\],nums\[2\],nums\[0\],nums\[1\],nums\[2\]\]
- ans = \[1,2,1,1,2,1\]

**Example 2:**

**Input:** nums = \[1,3,2,1\]
**Output:** \[1,3,2,1,1,3,2,1\]
**Explanation:** The array ans is formed as follows:
- ans = \[nums\[0\],nums\[1\],nums\[2\],nums\[3\],nums\[0\],nums\[1\],nums\[2\],nums\[3\]\]
- ans = \[1,3,2,1,1,3,2,1\]

**Constraints:**

*   `n == nums.length`
*   `1 <= n <= 1000`
*   `1 <= nums[i] <= 1000`

## A solution in Java

```java
public int maxValue(int n, int index, int maxSum) {
    maxSum -= n;
    int left = 0, right = maxSum, ans = 0;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        long sum = (long)Math.min(mid, index) * (Math.min(mid, index) + 1) / 2 + (long)Math.min(mid, n - index - 1) * (Math.min(mid, n - index) + 1) / 2;
        if (mid > index) {
            sum += (long)(mid - index - 1) * (mid - index) / 2;
        }
        if (mid > n - index) {
            sum += (long)(mid - n + index) * (mid - n + index + 1) / 2;
        }
        if (sum <= maxSum) {
            ans = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ans + 1;
}
```
The problem asks to find the maximum value of nums[index] for a given array size n, position index, and maximum sum maxSum.

We have to use a binary search algorithm to maximize nums[index] in this problem. Firstly, subtract n from maxSum. This is because we want to consider the extra sum required for nums[index], as each element in nums should be at least 1. Set the initial search range as (0, maxSum). Next, we iterate until left <= right, calculating the mid-value in each iteration. For the current mid-value, we calculate its contribution to the sum on both sides of index. If the mid-value is greater than index, we add its difference to the sum. We do the same if the mid-value is greater than n-index. If the sum is within maxSum, set the answer to be the current mid-value and update the left boundary; otherwise, update the right boundary. Finally, return the answer incremented by 1 because we decreased maxSum by n earlier.

This algorithm is applied similarly in all four languages. In C++ and Java, we need to be careful with potential integer overflows and use long long (C++) or long (Java) when needed. In JavaScript, bitwise right shift (>>) is used to calculate mid-value in the binary search loop.

## A solution in C++

```cpp
int maxValue(int n, int index, int maxSum) {
    maxSum -= n;
    int left = 0, right = maxSum, ans = 0;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        long long sum = min(mid, index) * (min(mid, index) + 1LL) / 2 + min(mid, n - index - 1) * (min(mid, n - index) + 1LL) / 2;
        if (mid > index) {
            sum += (mid - index - 1LL) * (mid - index) / 2;
        }
        if (mid > n - index) {
            sum += (mid - n + index) * (mid - n + index + 1) / 2;
        }
        if (sum <= maxSum) {
            ans = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ans + 1;
}
```
The problem asks to find the maximum value of nums[index] for a given array size n, position index, and maximum sum maxSum.

We have to use a binary search algorithm to maximize nums[index] in this problem. Firstly, subtract n from maxSum. This is because we want to consider the extra sum required for nums[index], as each element in nums should be at least 1. Set the initial search range as (0, maxSum). Next, we iterate until left <= right, calculating the mid-value in each iteration. For the current mid-value, we calculate its contribution to the sum on both sides of index. If the mid-value is greater than index, we add its difference to the sum. We do the same if the mid-value is greater than n-index. If the sum is within maxSum, set the answer to be the current mid-value and update the left boundary; otherwise, update the right boundary. Finally, return the answer incremented by 1 because we decreased maxSum by n earlier.

This algorithm is applied similarly in all four languages. In C++ and Java, we need to be careful with potential integer overflows and use long long (C++) or long (Java) when needed. In JavaScript, bitwise right shift (>>) is used to calculate mid-value in the binary search loop.

## A solution in Python

```python
def maxValue(n, index, maxSum):
    maxSum -= n
    left, right, ans = 0, maxSum, 0
    while left <= right:
        mid = left + (right - left) // 2
        sum = min(mid, index) * (min(mid, index) + 1) // 2 + min(mid, n - index - 1) * (min(mid, n - index) + 1) // 2
        if mid > index:
            sum += (mid - index - 1) * (mid - index) // 2
        if mid > n - index:
            sum += (mid - n + index) * (mid - n + index + 1) // 2
        if sum <= maxSum:
            ans = mid
            left = mid + 1
        else:
            right = mid - 1
    return ans + 1
```
The problem asks to find the maximum value of nums[index] for a given array size n, position index, and maximum sum maxSum.

We have to use a binary search algorithm to maximize nums[index] in this problem. Firstly, subtract n from maxSum. This is because we want to consider the extra sum required for nums[index], as each element in nums should be at least 1. Set the initial search range as (0, maxSum). Next, we iterate until left <= right, calculating the mid-value in each iteration. For the current mid-value, we calculate its contribution to the sum on both sides of index. If the mid-value is greater than index, we add its difference to the sum. We do the same if the mid-value is greater than n-index. If the sum is within maxSum, set the answer to be the current mid-value and update the left boundary; otherwise, update the right boundary. Finally, return the answer incremented by 1 because we decreased maxSum by n earlier.

This algorithm is applied similarly in all four languages. In C++ and Java, we need to be careful with potential integer overflows and use long long (C++) or long (Java) when needed. In JavaScript, bitwise right shift (>>) is used to calculate mid-value in the binary search loop.

## A solution in Javascript

```javascript
function maxValue(n, index, maxSum) {
    maxSum -= n;
    let left = 0, right = maxSum, ans = 0;
    while (left <= right) {
        const mid = left + ((right - left) >> 1);
        let sum = Math.min(mid, index) * (Math.min(mid, index) + 1) / 2 + Math.min(mid, n - index - 1) * (Math.min(mid, n - index) + 1) / 2;
        if (mid > index) {
            sum += (mid - index - 1) * (mid - index) / 2;
        }
        if (mid > n - index) {
            sum += (mid - n + index) * (mid - n + index + 1) / 2;
        }
        if (sum <= maxSum) {
            ans = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ans + 1;
}
```
The problem asks to find the maximum value of nums[index] for a given array size n, position index, and maximum sum maxSum.

We have to use a binary search algorithm to maximize nums[index] in this problem. Firstly, subtract n from maxSum. This is because we want to consider the extra sum required for nums[index], as each element in nums should be at least 1. Set the initial search range as (0, maxSum). Next, we iterate until left <= right, calculating the mid-value in each iteration. For the current mid-value, we calculate its contribution to the sum on both sides of index. If the mid-value is greater than index, we add its difference to the sum. We do the same if the mid-value is greater than n-index. If the sum is within maxSum, set the answer to be the current mid-value and update the left boundary; otherwise, update the right boundary. Finally, return the answer incremented by 1 because we decreased maxSum by n earlier.

This algorithm is applied similarly in all four languages. In C++ and Java, we need to be careful with potential integer overflows and use long long (C++) or long (Java) when needed. In JavaScript, bitwise right shift (>>) is used to calculate mid-value in the binary search loop.


# Unique Length-3 Palindromic Subsequences

- slug: unique-length-3-palindromic-subsequences
- difficulty: Medium

Given a string `s`, return _the number of **unique palindromes of length three** that are a **subsequence** of_ `s`.

Note that even if there are multiple ways to obtain the same subsequence, it is still only counted **once**.

A **palindrome** is a string that reads the same forwards and backwards.

A **subsequence** of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

*   For example, `"ace "` is a subsequence of `"abcde "`.

**Example 1:**

**Input:** s =  "aabca "
**Output:** 3
**Explanation:** The 3 palindromic subsequences of length 3 are:
-  "aba " (subsequence of  "aabca ")
-  "aaa " (subsequence of  "aabca ")
-  "aca " (subsequence of  "aabca ")

**Example 2:**

**Input:** s =  "adc "
**Output:** 0
**Explanation:** There are no palindromic subsequences of length 3 in  "adc ".

**Example 3:**

**Input:** s =  "bbcbaba "
**Output:** 4
**Explanation:** The 4 palindromic subsequences of length 3 are:
-  "bbb " (subsequence of  "bbcbaba ")
-  "bcb " (subsequence of  "bbcbaba ")
-  "bab " (subsequence of  "bbcbaba ")
-  "aba " (subsequence of  "bbcbaba ")

**Constraints:**

*   `3 <= s.length <= 105`
*   `s` consists of only lowercase English letters.

## A solution in Java

```java
import java.util.Arrays;

public int maxConsecutiveValues(int[] coins) {
    Arrays.sort(coins);
    int maxValue = 0;
    for (int coin : coins) {
        if (coin <= maxValue + 1) {
            maxValue += coin;
        } else {
            break;
        }
    }
    return maxValue + 1;
}
```
The algorithm to solve this problem can be described as:

1. Sort the `coins` array in ascending order.
2. Initialize a variable `maxValue` to 0.
3. Loop through the sorted array `coins`, and for each `coin`, check if the `coin` is less than or equal to `maxValue + 1`. If true, add the `coin` value to `maxValue`.
4. If not, break out of the loop.
5. Return the final `maxValue + 1` as the result.

This algorithm works because by sorting the coins and accumulating them in order, we can easily track the maximum consecutive integer value that can be made without missing any integer. If we come across a coin that can't be combined with the previous coins to make a consecutive integer, we break the loop and return the maxValue so far.

## A solution in C++

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

int maxConsecutiveValues(std::vector<int>& coins) {
    std::sort(coins.begin(), coins.end());
    int maxValue = 0;
    for (int coin : coins) {
        if (coin <= maxValue + 1) {
            maxValue += coin;
        } else {
            break;
        }
    }
    return maxValue + 1;
}
```
The algorithm to solve this problem can be described as:

1. Sort the `coins` array in ascending order.
2. Initialize a variable `maxValue` to 0.
3. Loop through the sorted array `coins`, and for each `coin`, check if the `coin` is less than or equal to `maxValue + 1`. If true, add the `coin` value to `maxValue`.
4. If not, break out of the loop.
5. Return the final `maxValue + 1` as the result.

This algorithm works because by sorting the coins and accumulating them in order, we can easily track the maximum consecutive integer value that can be made without missing any integer. If we come across a coin that can't be combined with the previous coins to make a consecutive integer, we break the loop and return the maxValue so far.

## A solution in Python

```python
def max_consecutive_values(coins):
    coins.sort()
    max_value = 0
    for coin in coins:
        if coin <= max_value + 1:
            max_value += coin
        else:
            break
    return max_value + 1
```
The algorithm to solve this problem can be described as:

1. Sort the `coins` array in ascending order.
2. Initialize a variable `maxValue` to 0.
3. Loop through the sorted array `coins`, and for each `coin`, check if the `coin` is less than or equal to `maxValue + 1`. If true, add the `coin` value to `maxValue`.
4. If not, break out of the loop.
5. Return the final `maxValue + 1` as the result.

This algorithm works because by sorting the coins and accumulating them in order, we can easily track the maximum consecutive integer value that can be made without missing any integer. If we come across a coin that can't be combined with the previous coins to make a consecutive integer, we break the loop and return the maxValue so far.

## A solution in Javascript

```javascript
function maxConsecutiveValues(coins) {
    coins.sort((a, b) => a - b);
    let maxValue = 0;
    for (let coin of coins) {
        if (coin <= maxValue + 1) {
            maxValue += coin;
        } else {
            break;
        }
    }
    return maxValue + 1;
}
```
The algorithm to solve this problem can be described as:

1. Sort the `coins` array in ascending order.
2. Initialize a variable `maxValue` to 0.
3. Loop through the sorted array `coins`, and for each `coin`, check if the `coin` is less than or equal to `maxValue + 1`. If true, add the `coin` value to `maxValue`.
4. If not, break out of the loop.
5. Return the final `maxValue + 1` as the result.

This algorithm works because by sorting the coins and accumulating them in order, we can easily track the maximum consecutive integer value that can be made without missing any integer. If we come across a coin that can't be combined with the previous coins to make a consecutive integer, we break the loop and return the maxValue so far.


# Painting a Grid With Three Different Colors

- slug: painting-a-grid-with-three-different-colors
- difficulty: Hard

You are given two integers `m` and `n`. Consider an `m x n` grid where each cell is initially white. You can paint each cell **red**, **green**, or **blue**. All cells **must** be painted.

Return _the number of ways to color the grid with **no two adjacent cells having the same color**_. Since the answer can be very large, return it **modulo** `109 + 7`.

**Example 1:**

**Input:** m = 1, n = 1
**Output:** 3
**Explanation:** The three possible colorings are shown in the image above.

**Example 2:**

**Input:** m = 1, n = 2
**Output:** 6
**Explanation:** The six possible colorings are shown in the image above.

**Example 3:**

**Input:** m = 5, n = 5
**Output:** 580986

**Constraints:**

*   `1 <= m <= 5`
*   `1 <= n <= 1000`

## A solution in Java

```java
public int numOfWays(int m, int n) {
    long mod = 1000000007;
    long a = 6, b = 6, c = 3, d = 3;
    while (--n > 0) {
        long temp_a = a, temp_c = c;
        a = (a * 3 + b * 2) % mod;
        b = (temp_a * 2 + b * 2) % mod;
        c = (c * 3 + d * 2) % mod;
        d = (temp_c * 2 + d * 2) % mod;
    }
    return (int)(m == 1 ? b : (a + c) % mod);
}
```
The algorithm calculates the number of ways to color the m x n grid with no adjacent cells having the same color. If `m = 1`, we have a single column, and there are 2 ways to color one column (second cell differs from the first), and 3 ways to color two cells in a column (second cell differs from the first but matches the second row). If `m > 1`, there are two separate cases to consider when painting the third cell:

- Case 1: The third cell is not adjacent to any cells of the same color (it is safe). In this case, we have 3 options to paint the third cell, and the number of ways to paint the grid is multiplied by 3.
- Case 2: The third cell is adjacent to at least one cell of its color. In this case, we have 2 options to paint the third cell, and the number of ways is multiplied by 2.

We use dynamic programming to calculate the number of ways for each cell, starting from the initial values and updating the variables for cases 1 and 2 accordingly. Finally, we return the sum of ways depending on the value of `m`.

## A solution in C++

```cpp
int numOfWays(int m, int n) {
    long mod = 1e9 + 7;
    long a = 6, b = 6, c = 3, d = 3;
    while (--n) {
        long temp_a = a, temp_c = c;
        a = (a * 3 + b * 2) % mod;
        b = (temp_a * 2 + b * 2) % mod;
        c = (c * 3 + d * 2) % mod;
        d = (temp_c * 2 + d * 2) % mod;
    }
    return m == 1 ? b : (a + c) % mod;
}
```
The algorithm calculates the number of ways to color the m x n grid with no adjacent cells having the same color. If `m = 1`, we have a single column, and there are 2 ways to color one column (second cell differs from the first), and 3 ways to color two cells in a column (second cell differs from the first but matches the second row). If `m > 1`, there are two separate cases to consider when painting the third cell:

- Case 1: The third cell is not adjacent to any cells of the same color (it is safe). In this case, we have 3 options to paint the third cell, and the number of ways to paint the grid is multiplied by 3.
- Case 2: The third cell is adjacent to at least one cell of its color. In this case, we have 2 options to paint the third cell, and the number of ways is multiplied by 2.

We use dynamic programming to calculate the number of ways for each cell, starting from the initial values and updating the variables for cases 1 and 2 accordingly. Finally, we return the sum of ways depending on the value of `m`.

## A solution in Python

```python
def numOfWays(m, n):
    mod = 1000000007
    a, b, c, d = 6, 6, 3, 3
    while n > 1:
        n -= 1
        temp_a = a
        temp_c = c
        a = (a * 3 + b * 2) % mod
        b = (temp_a * 2 + b * 2) % mod
        c = (c * 3 + d * 2) % mod
        d = (temp_c * 2 + d * 2) % mod
    return b if m == 1 else (a + c) % mod
```
The algorithm calculates the number of ways to color the m x n grid with no adjacent cells having the same color. If `m = 1`, we have a single column, and there are 2 ways to color one column (second cell differs from the first), and 3 ways to color two cells in a column (second cell differs from the first but matches the second row). If `m > 1`, there are two separate cases to consider when painting the third cell:

- Case 1: The third cell is not adjacent to any cells of the same color (it is safe). In this case, we have 3 options to paint the third cell, and the number of ways to paint the grid is multiplied by 3.
- Case 2: The third cell is adjacent to at least one cell of its color. In this case, we have 2 options to paint the third cell, and the number of ways is multiplied by 2.

We use dynamic programming to calculate the number of ways for each cell, starting from the initial values and updating the variables for cases 1 and 2 accordingly. Finally, we return the sum of ways depending on the value of `m`.

## A solution in Javascript

```javascript
function numOfWays(m, n) {
    let mod = 1e9 + 7;
    let a = 6, b = 6, c = 3, d = 3;
    while (--n) {
        let temp_a = a, temp_c = c;
        a = (a * 3 + b * 2) % mod;
        b = (temp_a * 2 + b * 2) % mod;
        c = (c * 3 + d * 2) % mod;
        d = (temp_c * 2 + d * 2) % mod;
    }
    return m === 1 ? b : (a + c) % mod;
}
```
The algorithm calculates the number of ways to color the m x n grid with no adjacent cells having the same color. If `m = 1`, we have a single column, and there are 2 ways to color one column (second cell differs from the first), and 3 ways to color two cells in a column (second cell differs from the first but matches the second row). If `m > 1`, there are two separate cases to consider when painting the third cell:

- Case 1: The third cell is not adjacent to any cells of the same color (it is safe). In this case, we have 3 options to paint the third cell, and the number of ways to paint the grid is multiplied by 3.
- Case 2: The third cell is adjacent to at least one cell of its color. In this case, we have 2 options to paint the third cell, and the number of ways is multiplied by 2.

We use dynamic programming to calculate the number of ways for each cell, starting from the initial values and updating the variables for cases 1 and 2 accordingly. Finally, we return the sum of ways depending on the value of `m`.


# Merge BSTs to Create Single BST

- slug: merge-bsts-to-create-single-bst
- difficulty: Hard

You are given `n` **BST (binary search tree) root nodes** for `n` separate BSTs stored in an array `trees` (**0-indexed**). Each BST in `trees` has **at most 3 nodes**, and no two roots have the same value. In one operation, you can:

*   Select two **distinct** indices `i` and `j` such that the value stored at one of the **leaves** of `trees[i]` is equal to the **root value** of `trees[j]`.
*   Replace the leaf node in `trees[i]` with `trees[j]`.
*   Remove `trees[j]` from `trees`.

Return _the **root** of the resulting BST if it is possible to form a valid BST after performing_ `n - 1` _operations, or_ `null` _if it is impossible to create a valid BST_.

A BST (binary search tree) is a binary tree where each node satisfies the following property:

*   Every node in the node's left subtree has a value **strictly less** than the node's value.
*   Every node in the node's right subtree has a value **strictly greater** than the node's value.

A leaf is a node that has no children.

**Example 1:**

**Input:** trees = \[\[2,1\],\[3,2,5\],\[5,4\]\]
**Output:** \[3,2,5,1,null,4\]
**Explanation:**
In the first operation, pick i=1 and j=0, and merge trees\[0\] into trees\[1\].
Delete trees\[0\], so trees = \[\[3,2,5,1\],\[5,4\]\].

In the second operation, pick i=0 and j=1, and merge trees\[1\] into trees\[0\].
Delete trees\[1\], so trees = \[\[3,2,5,1,null,4\]\].

The resulting tree, shown above, is a valid BST, so return its root.

**Example 2:**

**Input:** trees = \[\[5,3,8\],\[3,2,6\]\]
**Output:** \[\]
**Explanation:**
Pick i=0 and j=1 and merge trees\[1\] into trees\[0\].
Delete trees\[1\], so trees = \[\[5,3,8,2,6\]\].

The resulting tree is shown above. This is the only valid operation that can be performed, but the resulting tree is not a valid BST, so return null.

**Example 3:**

**Input:** trees = \[\[5,4\],\[3\]\]
**Output:** \[\]
**Explanation:** It is impossible to perform any operations.

**Constraints:**

*   `n == trees.length`
*   `1 <= n <= 5 * 104`
*   The number of nodes in each tree is in the range `[1, 3]`.
*   Each node in the input may have children but no grandchildren.
*   No two roots of `trees` have the same value.
*   All the trees in the input are **valid BSTs**.
*   `1 <= TreeNode.val <= 5 * 104`.

## A solution in Java

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

public TreeNode canMerge(List<TreeNode> trees) {
    Map<Integer, Integer> leafCount = new HashMap<>();
    Map<Integer, TreeNode> rootMap = new HashMap<>();

    for (TreeNode tree : trees) {
        if (tree.left != null) {
            leafCount.put(tree.left.val, leafCount.getOrDefault(tree.left.val, 0) + 1);
        }
        if (tree.right != null) {
            leafCount.put(tree.right.val, leafCount.getOrDefault(tree.right.val, 0) + 1);
        }
        rootMap.put(tree.val, tree);
    }

    for (TreeNode tree : trees) {
        if (leafCount.getOrDefault(tree.val, 0) == 0) {
            if (isValidBST(tree, 0, 5 * (int)Math.pow(10, 4) + 1, rootMap, leafCount)) {
                return tree;
            }
            break;
        }
    }
    return null;
}

private boolean isValidBST(TreeNode node, int minVal, int maxVal, Map<Integer, TreeNode> rootMap, Map<Integer, Integer> leafCount) {
    if (node == null) {
        return true;
    }
    if (node.val <= minVal || node.val >= maxVal) {
        return false;
    }
    if (rootMap.containsKey(node.left == null ? -1 : node.left.val)) {
        TreeNode leftChild = rootMap.remove(node.left.val);
        leafCount.put(node.left.val, leafCount.get(node.left.val) - 1);
        node.left = leftChild;
    }
    if (rootMap.containsKey(node.right == null ? -1 : node.right.val)) {
        TreeNode rightChild = rootMap.remove(node.right.val);
        leafCount.put(node.right.val, leafCount.get(node.right.val) - 1);
        node.right = rightChild;
    }
    return isValidBST(node.left, minVal, node.val, rootMap, leafCount) && isValidBST(node.right, node.val, maxVal, rootMap, leafCount);
}
```
The algorithm begins by creating two hash maps, one for counting the occurrence of each leaf value, and another one to map the root values to their corresponding trees.

Next, we define a helper function, `isValidBST`, that will recursively check if the tree is a valid binary search tree, given a specific minimum and maximum value. If a leaf node has a matching root node in the `rootMap`, we replace the leaf node with the matching tree and decrement the leaf count.

The next step is to loop through each tree in the input array `trees`. If a tree's root value has a leaf count of 0, that means it's a candidate for being the main root node of the final, merged tree. For each candidate, we then call our `isValidBST` function to check if it's possible to create a valid BST by performing `n - 1` operations.

If the `isValidBST` function returns true, we return the current tree's root node, as it's the final, merged tree. If no such tree exists, we return `null`, indicating that it's not possible to create a valid BST.

## A solution in C++

```cpp
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

TreeNode* canMerge(vector<TreeNode*>& trees) {
    unordered_map<int, int> leafCount;
    unordered_map<int, TreeNode*> rootMap;
    for (TreeNode* tree : trees) {
        if (tree->left) {
            leafCount[tree->left->val]++;
        }
        if (tree->right) {
            leafCount[tree->right->val]++;
        }
        rootMap[tree->val] = tree;
    }

    function<bool(TreeNode*, int, int)> isValidBST = [&](TreeNode* node, int minVal, int maxVal) {
        if (!node) {
            return true;
        }
        if (node->val <= minVal || node->val >= maxVal) {
            return false;
        }
        return isValidBST(node->left, minVal, node->val) && isValidBST(node->right, node->val, maxVal);
    };

    for (TreeNode* tree : trees) {
        if (leafCount[tree->val] == 0) {
            if (isValidBST(tree, 0, 5e4 + 1)) {
                return tree;
            }
            break;
        }
    }
    return NULL;
}
```
The algorithm begins by creating two hash maps, one for counting the occurrence of each leaf value, and another one to map the root values to their corresponding trees.

Next, we define a helper function, `isValidBST`, that will recursively check if the tree is a valid binary search tree, given a specific minimum and maximum value. If a leaf node has a matching root node in the `rootMap`, we replace the leaf node with the matching tree and decrement the leaf count.

The next step is to loop through each tree in the input array `trees`. If a tree's root value has a leaf count of 0, that means it's a candidate for being the main root node of the final, merged tree. For each candidate, we then call our `isValidBST` function to check if it's possible to create a valid BST by performing `n - 1` operations.

If the `isValidBST` function returns true, we return the current tree's root node, as it's the final, merged tree. If no such tree exists, we return `null`, indicating that it's not possible to create a valid BST.

## A solution in Python

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

def canMerge(trees):
    leaf_count = {}
    root_map = {}

    for tree in trees:
        if tree.left:
            leaf_count[tree.left.val] = leaf_count.get(tree.left.val, 0) + 1
        if tree.right:
            leaf_count[tree.right.val] = leaf_count.get(tree.right.val, 0) + 1
        root_map[tree.val] = tree

    def is_valid_bst(node, min_val, max_val):
        if not node:
            return True
        if node.val <= min_val or node.val >= max_val:
            return False
        if node.left and node.left.val in root_map:
            left_child = root_map.pop(node.left.val)
            leaf_count[tree.left.val] -= 1
            tree.left = left_child
        if node.right and node.right.val in root_map:
            right_child = root_map.pop(node.right.val)
            leaf_count[tree.right.val] -= 1
            tree.right = right_child
        return is_valid_bst(node.left, min_val, node.val) and is_valid_bst(node.right, node.val, max_val)

    for tree in trees:
        if leaf_count.get(tree.val, 0) == 0:
            if is_valid_bst(tree, 0, 5e4 + 1):
                return tree
            break

    return None
```
The algorithm begins by creating two hash maps, one for counting the occurrence of each leaf value, and another one to map the root values to their corresponding trees.

Next, we define a helper function, `isValidBST`, that will recursively check if the tree is a valid binary search tree, given a specific minimum and maximum value. If a leaf node has a matching root node in the `rootMap`, we replace the leaf node with the matching tree and decrement the leaf count.

The next step is to loop through each tree in the input array `trees`. If a tree's root value has a leaf count of 0, that means it's a candidate for being the main root node of the final, merged tree. For each candidate, we then call our `isValidBST` function to check if it's possible to create a valid BST by performing `n - 1` operations.

If the `isValidBST` function returns true, we return the current tree's root node, as it's the final, merged tree. If no such tree exists, we return `null`, indicating that it's not possible to create a valid BST.

## A solution in Javascript

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

function canMerge(trees) {
    const leafCount = new Map();
    const rootMap = new Map();

    for (const tree of trees) {
        if (tree.left) {
            leafCount.set(tree.left.val, (leafCount.get(tree.left.val) || 0) + 1);
        }
        if (tree.right) {
            leafCount.set(tree.right.val, (leafCount.get(tree.right.val) || 0) + 1);
        }
        rootMap.set(tree.val, tree);
    }

    function isValidBST(node, minVal, maxVal) {
        if (!node) {
            return true;
        }
        if (node.val <= minVal || node.val >= maxVal) {
            return false;
        }
        if (node.left && rootMap.has(node.left.val)) {
            const leftChild = rootMap.get(node.left.val);
            leafCount.set(node.left.val, leafCount.get(node.left.val) - 1);
            rootMap.delete(node.left.val);
            node.left = leftChild;
        }
        if (node.right && rootMap.has(node.right.val)) {
            const rightChild = rootMap.get(node.right.val);
            leafCount.set(node.right.val, leafCount.get(node.right.val) - 1);
            rootMap.delete(node.right.val);
            node.right = rightChild;
        }
        return isValidBST(node.left, minVal, node.val) && isValidBST(node.right, node.val, maxVal);
    }

    for (const tree of trees) {
        if ((leafCount.get(tree.val) || 0) === 0) {
            if (isValidBST(tree, 0, 5e4 + 1)) {
                return tree;
            }
            break;
        }
    }

    return null;
}
```
The algorithm begins by creating two hash maps, one for counting the occurrence of each leaf value, and another one to map the root values to their corresponding trees.

Next, we define a helper function, `isValidBST`, that will recursively check if the tree is a valid binary search tree, given a specific minimum and maximum value. If a leaf node has a matching root node in the `rootMap`, we replace the leaf node with the matching tree and decrement the leaf count.

The next step is to loop through each tree in the input array `trees`. If a tree's root value has a leaf count of 0, that means it's a candidate for being the main root node of the final, merged tree. For each candidate, we then call our `isValidBST` function to check if it's possible to create a valid BST by performing `n - 1` operations.

If the `isValidBST` function returns true, we return the current tree's root node, as it's the final, merged tree. If no such tree exists, we return `null`, indicating that it's not possible to create a valid BST.


# Check if String Is Decomposable Into Value-Equal Substrings

- slug: check-if-string-is-decomposable-into-value-equal-substrings
- difficulty: Easy

A **value-equal** string is a string where **all** characters are the same.

*   For example, `"1111 "` and `"33 "` are value-equal strings.
*   In contrast, `"123 "` is not a value-equal string.

Given a digit string `s`, decompose the string into some number of **consecutive value-equal** substrings where **exactly one** substring has a **length of** `2` and the remaining substrings have a **length of** `3`.

Return `true` _if you can decompose_ `s` _according to the above rules. Otherwise, return_ `false`.

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

**Example 1:**

**Input:** s =  "000111000 "
**Output:** false
**Explanation:** s cannot be decomposed according to the rules because \[ "000 ",  "111 ",  "000 "\] does not have a substring of length 2.

**Example 2:**

**Input:** s =  "00011111222 "
**Output:** true
**Explanation:** s can be decomposed into \[ "000 ",  "111 ",  "11 ",  "222 "\].

**Example 3:**

**Input:** s =  "011100022233 "
**Output:** false
**Explanation:** s cannot be decomposed according to the rules because of the first '0'.

**Constraints:**

*   `1 <= s.length <= 1000`
*   `s` consists of only digits `'0'` through `'9'`.

## A solution in Java

```java
import java.util.HashSet;
import java.util.Set;

public int numDifferentIntegers(String word) {
    for (int i = 0; i < word.length(); i++) {
        if (!Character.isDigit(word.charAt(i))) {
            word = word.substring(0, i) + " " + word.substring(i + 1);
        }
    }
    String[] nums = word.split("\\s+");
    Set<String> uniqueNums = new HashSet<>();
    for (String num : nums) {
        num = num.replaceFirst("^0+(?!$)", "");
        uniqueNums.add(num);
    }
    return uniqueNums.size();
}
```
1. Replace all non-digit characters with a space in `word`.
2. Split the modified `word` by spaces to get the list of integers.
3. Initialize an empty Set named `uniqueNums` to store unique integers.
4. For each integer in the list, remove leading zeros (if any) and add it to the `uniqueNums` set.
5. Return the size of `uniqueNums` which is the count of unique integers.

## A solution in C++

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

int numDifferentIntegers(std::string word) {
    for (char &c : word) {
        if (c < '0' || c > '9') {
            c = ' ';
        }
    }
    std::istringstream iss(word);
    std::string num;
    std::unordered_set<std::string> uniqueNums;
    while (iss >> num) {
        num.erase(0, num.find_first_not_of('0'));
        uniqueNums.insert(num);
    }
    return uniqueNums.size();
}
```
1. Replace all non-digit characters with a space in `word`.
2. Split the modified `word` by spaces to get the list of integers.
3. Initialize an empty Set named `uniqueNums` to store unique integers.
4. For each integer in the list, remove leading zeros (if any) and add it to the `uniqueNums` set.
5. Return the size of `uniqueNums` which is the count of unique integers.

## A solution in Python

```python
def num_different_integers(word):
    for c in word:
        if not c.isdigit():
            word = word.replace(c, ' ')
    nums = word.split()
    unique_nums = set()
    for num in nums:
        num = num.lstrip('0') or '0'
        unique_nums.add(num)
    return len(unique_nums)
```
1. Replace all non-digit characters with a space in `word`.
2. Split the modified `word` by spaces to get the list of integers.
3. Initialize an empty Set named `uniqueNums` to store unique integers.
4. For each integer in the list, remove leading zeros (if any) and add it to the `uniqueNums` set.
5. Return the size of `uniqueNums` which is the count of unique integers.

## A solution in Javascript

```javascript
function numDifferentIntegers(word) {
  word = word.replace(/\D/g, " ");
  let nums = word.split(/\s+/).filter(Boolean);
  let uniqueNums = new Set();
  for (let num of nums) {
    num = num.replace(/^0+/, "") || "0";
    uniqueNums.add(num);
  }
  return uniqueNums.size;
}
```
1. Replace all non-digit characters with a space in `word`.
2. Split the modified `word` by spaces to get the list of integers.
3. Initialize an empty Set named `uniqueNums` to store unique integers.
4. For each integer in the list, remove leading zeros (if any) and add it to the `uniqueNums` set.
5. Return the size of `uniqueNums` which is the count of unique integers.


# Maximum Number of Words You Can Type

- slug: maximum-number-of-words-you-can-type
- difficulty: Easy

There is a malfunctioning keyboard where some letter keys do not work. All other keys on the keyboard work properly.

Given a string `text` of words separated by a single space (no leading or trailing spaces) and a string `brokenLetters` of all **distinct** letter keys that are broken, return _the **number of words** in_ `text` _you can fully type using this keyboard_.

**Example 1:**

**Input:** text =  "hello world ", brokenLetters =  "ad "
**Output:** 1
**Explanation:** We cannot type  "world " because the 'd' key is broken.

**Example 2:**

**Input:** text =  "leet code ", brokenLetters =  "lt "
**Output:** 1
**Explanation:** We cannot type  "leet " because the 'l' and 't' keys are broken.

**Example 3:**

**Input:** text =  "leet code ", brokenLetters =  "e "
**Output:** 0
**Explanation:** We cannot type either word because the 'e' key is broken.

**Constraints:**

*   `1 <= text.length <= 104`
*   `0 <= brokenLetters.length <= 26`
*   `text` consists of words separated by a single space without any leading or trailing spaces.
*   Each word only consists of lowercase English letters.
*   `brokenLetters` consists of **distinct** lowercase English letters.

## A solution in Java

```java
public int min_operations(int n) {
    int count = 1;
    int temp = 1;

    while (temp % n != 0) {
        temp = (temp * 2) % n;
        count++;
    }

    return count;
}
```
The algorithm starts by initializing a counter count and a temporary variable temp to store the intermediate values. For each operation, the algorithm updates the value of temp by multiplying it by 2 and taking the modulo of n. This is repeated until the temporary value becomes zero modulo n (temp % n == 0), which means that the original permutation has been reached again. The counter count is updated after each iteration, and the algorithm returns the value of count as the minimum non-zero number of operations needed.

## A solution in C++

```cpp
int min_operations(int n) {
    int count = 1;
    int temp = 1;

    while (temp % n != 0) {
        temp = (temp * 2) % n;
        count++;
    }

    return count;
}
```
The algorithm starts by initializing a counter count and a temporary variable temp to store the intermediate values. For each operation, the algorithm updates the value of temp by multiplying it by 2 and taking the modulo of n. This is repeated until the temporary value becomes zero modulo n (temp % n == 0), which means that the original permutation has been reached again. The counter count is updated after each iteration, and the algorithm returns the value of count as the minimum non-zero number of operations needed.

## A solution in Python

```python
def min_operations(n):
    count = 1
    temp = 1

    while temp % n != 0:
        temp = (temp * 2) % n
        count += 1

    return count
```
The algorithm starts by initializing a counter count and a temporary variable temp to store the intermediate values. For each operation, the algorithm updates the value of temp by multiplying it by 2 and taking the modulo of n. This is repeated until the temporary value becomes zero modulo n (temp % n == 0), which means that the original permutation has been reached again. The counter count is updated after each iteration, and the algorithm returns the value of count as the minimum non-zero number of operations needed.

## A solution in Javascript

```javascript
function min_operations(n) {
    let count = 1;
    let temp = 1;

    while (temp % n !== 0) {
        temp = (temp * 2) % n;
        count++;
    }

    return count;
}
```
The algorithm starts by initializing a counter count and a temporary variable temp to store the intermediate values. For each operation, the algorithm updates the value of temp by multiplying it by 2 and taking the modulo of n. This is repeated until the temporary value becomes zero modulo n (temp % n == 0), which means that the original permutation has been reached again. The counter count is updated after each iteration, and the algorithm returns the value of count as the minimum non-zero number of operations needed.


# Add Minimum Number of Rungs

- slug: add-minimum-number-of-rungs
- difficulty: Medium

You are given a **strictly increasing** integer array `rungs` that represents the **height** of rungs on a ladder. You are currently on the **floor** at height `0`, and you want to reach the last rung.

You are also given an integer `dist`. You can only climb to the next highest rung if the distance between where you are currently at (the floor or on a rung) and the next rung is **at most** `dist`. You are able to insert rungs at any positive **integer** height if a rung is not already there.

Return _the **minimum** number of rungs that must be added to the ladder in order for you to climb to the last rung._

**Example 1:**

**Input:** rungs = \[1,3,5,10\], dist = 2
**Output:** 2
**Explanation:**
You currently cannot reach the last rung.
Add rungs at heights 7 and 8 to climb this ladder.
The ladder will now have rungs at \[1,3,5,7,8,10\].

**Example 2:**

**Input:** rungs = \[3,6,8,10\], dist = 3
**Output:** 0
**Explanation:**
This ladder can be climbed without adding additional rungs.

**Example 3:**

**Input:** rungs = \[3,4,6,7\], dist = 2
**Output:** 1
**Explanation:**
You currently cannot reach the first rung from the ground.
Add a rung at height 1 to climb this ladder.
The ladder will now have rungs at \[1,3,4,6,7\].

**Constraints:**

*   `1 <= rungs.length <= 105`
*   `1 <= rungs[i] <= 109`
*   `1 <= dist <= 109`
*   `rungs` is **strictly increasing**.

## A solution in Java

```java
public int numberOfNiceDivisors(int primeFactors) {
    int MOD = 1000000007;
    long result = 1;
    for (int p = 2; p <= primeFactors; ++p) {
        if (primeFactors % p == 0) {
            int count = 0;
            while (primeFactors % p == 0) {
                primeFactors /= p;
                ++count;
            }
            result = (result * (count * 2 + 1)) % MOD;
        }
    }
    return (int) result;
}
```
The algorithm iterates through all integers from 2 to the given positive integer `primeFactors`. For each of the divisors, it checks if it's divisible by the divisor. If it is, we increment the count and divide `primeFactors` by the divisor. We then update the result with the product of `(count * 2 + 1)` and the result modulo 10^9 + 7. Once the divisor loop is complete, we return the result as our answer.

## A solution in C++

```cpp
#include <cmath>

const int MOD = 1e9 + 7;

int numberOfNiceDivisors(int primeFactors) {
    long long result = 1;
    for (int p = 2; p <= primeFactors; ++p) {
        if (primeFactors % p == 0) {
            int count = 0;
            while (primeFactors % p == 0) {
                primeFactors /= p;
                ++count;
            }
            result = (result * (count * 2 + 1)) % MOD;
        }
    }
    return result;
}
```
The algorithm iterates through all integers from 2 to the given positive integer `primeFactors`. For each of the divisors, it checks if it's divisible by the divisor. If it is, we increment the count and divide `primeFactors` by the divisor. We then update the result with the product of `(count * 2 + 1)` and the result modulo 10^9 + 7. Once the divisor loop is complete, we return the result as our answer.

## A solution in Python

```python
def numberOfNiceDivisors(primeFactors):
    MOD = 1000000007
    result = 1
    p = 2
    while p <= primeFactors:
        if primeFactors % p == 0:
            count = 0
            while primeFactors % p == 0:
                primeFactors //= p
                count += 1
            result = (result * (count * 2 + 1)) % MOD
        p += 1
    return result
```
The algorithm iterates through all integers from 2 to the given positive integer `primeFactors`. For each of the divisors, it checks if it's divisible by the divisor. If it is, we increment the count and divide `primeFactors` by the divisor. We then update the result with the product of `(count * 2 + 1)` and the result modulo 10^9 + 7. Once the divisor loop is complete, we return the result as our answer.

## A solution in Javascript

```javascript
function numberOfNiceDivisors(primeFactors) {
    const MOD = 1000000007;
    let result = 1;
    for (let p = 2; p <= primeFactors; ++p) {
        if (primeFactors % p === 0) {
            let count = 0;
            while (primeFactors % p === 0) {
                primeFactors /= p;
                ++count;
            }
            result = (result * (count * 2 + 1)) % MOD;
        }
    }
    return result;
}
```
The algorithm iterates through all integers from 2 to the given positive integer `primeFactors`. For each of the divisors, it checks if it's divisible by the divisor. If it is, we increment the count and divide `primeFactors` by the divisor. We then update the result with the product of `(count * 2 + 1)` and the result modulo 10^9 + 7. Once the divisor loop is complete, we return the result as our answer.


# Maximum Number of Points with Cost

- slug: maximum-number-of-points-with-cost
- difficulty: Medium

You are given an `m x n` integer matrix `points` (**0-indexed**). Starting with `0` points, you want to **maximize** the number of points you can get from the matrix.

To gain points, you must pick one cell in **each row**. Picking the cell at coordinates `(r, c)` will **add** `points[r][c]` to your score.

However, you will lose points if you pick a cell too far from the cell that you picked in the previous row. For every two adjacent rows `r` and `r + 1` (where `0 <= r < m - 1`), picking cells at coordinates `(r, c1)` and `(r + 1, c2)` will **subtract** `abs(c1 - c2)` from your score.

Return _the **maximum** number of points you can achieve_.

`abs(x)` is defined as:

*   `x` for `x >= 0`.
*   `-x` for `x < 0`.

**Example 1:**

**Input:** points = \[\[1,2,3\],\[1,5,1\],\[3,1,1\]\]
**Output:** 9
**Explanation:**
The blue cells denote the optimal cells to pick, which have coordinates (0, 2), (1, 1), and (2, 0).
You add 3 + 5 + 3 = 11 to your score.
However, you must subtract abs(2 - 1) + abs(1 - 0) = 2 from your score.
Your final score is 11 - 2 = 9.

**Example 2:**

**Input:** points = \[\[1,5\],\[2,3\],\[4,2\]\]
**Output:** 11
**Explanation:**
The blue cells denote the optimal cells to pick, which have coordinates (0, 1), (1, 1), and (2, 0).
You add 5 + 3 + 4 = 12 to your score.
However, you must subtract abs(1 - 1) + abs(1 - 0) = 1 from your score.
Your final score is 12 - 1 = 11.

**Constraints:**

*   `m == points.length`
*   `n == points[r].length`
*   `1 <= m, n <= 105`
*   `1 <= m * n <= 105`
*   `0 <= points[r][c] <= 105`

## A solution in Java

```java
public int maxPoints(int[][] points) {
    int m = points.length, n = points[0].length;
    long[] dp = new long[n];
    for (int[] row : points) {
        long[] next_dp = new long[n];
        for (int c1 = 0; c1 < n; ++c1) {
            long score = dp[c1] + row[c1] - c1;
            for (int c2 = 0; c2 < n; ++c2) {
                next_dp[c2] = Math.max(next_dp[c2], score - row[c1] + c2);
            }
        }
        dp = next_dp;
    }
    long max_points = 0;
    for (long score : dp) {
        max_points = Math.max(max_points, score);
    }
    return (int) max_points;
}
```
The approach used is dynamic programming. For each row, we maintain a `dp` array where `dp[c]` is the maximum score we can achieve if we pick a cell in the current row with column equals to `c`. We iterate through each row, updating the maximum score in that row as we progress.

For each cell in current row, calculate its score by adding the points and subtracting the column index `c1`. Then subtract the points and add the neighboring column index `c2`, and update the maximum score for the next row.

Finally, return the maximum score among all the cells in the last row.

## A solution in C++

```cpp
int maxPoints(vector<vector<int>>& points) {
    int m = points.size(), n = points[0].size();
    vector<long> dp(n, 0);
    for (auto& row : points) {
        vector<long> next_dp(n, 0);
        for (int c1 = 0; c1 < n; ++c1) {
            long score = dp[c1] + row[c1] - c1;
            for (int c2 = 0; c2 < n; ++c2) {
                next_dp[c2] = max(next_dp[c2], score - row[c1] + c2);
            }
        }
        dp.swap(next_dp);
    }
    return *max_element(dp.begin(), dp.end());
}
```
The approach used is dynamic programming. For each row, we maintain a `dp` array where `dp[c]` is the maximum score we can achieve if we pick a cell in the current row with column equals to `c`. We iterate through each row, updating the maximum score in that row as we progress.

For each cell in current row, calculate its score by adding the points and subtracting the column index `c1`. Then subtract the points and add the neighboring column index `c2`, and update the maximum score for the next row.

Finally, return the maximum score among all the cells in the last row.

## A solution in Python

```python
def maxPoints(points):
    m, n = len(points), len(points[0])
    dp = [0] * n
    for row in points:
        next_dp = [0] * n
        for c1 in range(n):
            score = dp[c1] + row[c1] - c1
            for c2 in range(n):
                next_dp[c2] = max(next_dp[c2], score - row[c1] + c2)
        dp = next_dp
    return max(dp)
```
The approach used is dynamic programming. For each row, we maintain a `dp` array where `dp[c]` is the maximum score we can achieve if we pick a cell in the current row with column equals to `c`. We iterate through each row, updating the maximum score in that row as we progress.

For each cell in current row, calculate its score by adding the points and subtracting the column index `c1`. Then subtract the points and add the neighboring column index `c2`, and update the maximum score for the next row.

Finally, return the maximum score among all the cells in the last row.

## A solution in Javascript

```javascript
function maxPoints(points) {
    let m = points.length, n = points[0].length;
    let dp = new Array(n).fill(0);
    for (const row of points) {
        const next_dp = new Array(n).fill(0);
        for (let c1 = 0; c1 < n; ++c1) {
            const score = dp[c1] + row[c1] - c1;
            for (let c2 = 0; c2 < n; ++c2) {
                next_dp[c2] = Math.max(next_dp[c2], score - row[c1] + c2);
            }
        }
        dp = next_dp;
    }
    return Math.max(...dp);
}
```
The approach used is dynamic programming. For each row, we maintain a `dp` array where `dp[c]` is the maximum score we can achieve if we pick a cell in the current row with column equals to `c`. We iterate through each row, updating the maximum score in that row as we progress.

For each cell in current row, calculate its score by adding the points and subtracting the column index `c1`. Then subtract the points and add the neighboring column index `c2`, and update the maximum score for the next row.

Finally, return the maximum score among all the cells in the last row.


# Maximum Genetic Difference Query

- slug: maximum-genetic-difference-query
- difficulty: Hard

There is a rooted tree consisting of `n` nodes numbered `0` to `n - 1`. Each node's number denotes its **unique genetic value** (i.e. the genetic value of node `x` is `x`). The **genetic difference** between two genetic values is defined as the **bitwise-****XOR** of their values. You are given the integer array `parents`, where `parents[i]` is the parent for node `i`. If node `x` is the **root** of the tree, then `parents[x] == -1`.

You are also given the array `queries` where `queries[i] = [nodei, vali]`. For each query `i`, find the **maximum genetic difference** between `vali` and `pi`, where `pi` is the genetic value of any node that is on the path between `nodei` and the root (including `nodei` and the root). More formally, you want to maximize `vali XOR pi`.

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

**Example 1:**

**Input:** parents = \[-1,0,1,1\], queries = \[\[0,2\],\[3,2\],\[2,5\]\]
**Output:** \[2,3,7\]
**Explanation:** The queries are processed as follows:
- \[0,2\]: The node with the maximum genetic difference is 0, with a difference of 2 XOR 0 = 2.
- \[3,2\]: The node with the maximum genetic difference is 1, with a difference of 2 XOR 1 = 3.
- \[2,5\]: The node with the maximum genetic difference is 2, with a difference of 5 XOR 2 = 7.

**Example 2:**

**Input:** parents = \[3,7,-1,2,0,7,0,2\], queries = \[\[4,6\],\[1,15\],\[0,5\]\]
**Output:** \[6,14,7\]
**Explanation:** The queries are processed as follows:
- \[4,6\]: The node with the maximum genetic difference is 0, with a difference of 6 XOR 0 = 6.
- \[1,15\]: The node with the maximum genetic difference is 1, with a difference of 15 XOR 1 = 14.
- \[0,5\]: The node with the maximum genetic difference is 2, with a difference of 5 XOR 2 = 7.

**Constraints:**

*   `2 <= parents.length <= 105`
*   `0 <= parents[i] <= parents.length - 1` for every node `i` that is **not** the root.
*   `parents[root] == -1`
*   `1 <= queries.length <= 3 * 104`
*   `0 <= nodei <= parents.length - 1`
*   `0 <= vali <= 2 * 105`

## A solution in Java

```java
public int minOperations(int[] nums) {
    int operations = 0;
    for (int i = 1; i < nums.length; ++i) {
        if (nums[i] <= nums[i - 1]) {
            operations += nums[i - 1] - nums[i] + 1;
            nums[i] = nums[i - 1] + 1;
        }
    }
    return operations;
}
```
We iterate through the array starting from the second element. For each element, we check if it's smaller or equal to the previous one. If it is, we calculate the difference in value between the current and previous elements, add 1 to this difference, and accumulate it into a variable that keeps track of the operations needed to make the array strictly increasing. After that, we update the current element by adding 1 to the previous element, making them strictly increasing. We do this for all elements in the array, and finally return the accumulated operations needed. This approach has a time complexity of O(n) where n is the length of the array.

## A solution in C++

```cpp
int minOperations(vector<int>& nums) {
    int operations = 0;
    for (int i = 1; i < nums.size(); ++i) {
        if (nums[i] <= nums[i - 1]) {
            operations += nums[i - 1] - nums[i] + 1;
            nums[i] = nums[i - 1] + 1;
        }
    }
    return operations;
}
```
We iterate through the array starting from the second element. For each element, we check if it's smaller or equal to the previous one. If it is, we calculate the difference in value between the current and previous elements, add 1 to this difference, and accumulate it into a variable that keeps track of the operations needed to make the array strictly increasing. After that, we update the current element by adding 1 to the previous element, making them strictly increasing. We do this for all elements in the array, and finally return the accumulated operations needed. This approach has a time complexity of O(n) where n is the length of the array.

## A solution in Python

```python
def min_operations(nums):
    operations = 0
    for i in range(1, len(nums)):
        if nums[i] <= nums[i - 1]:
            operations += nums[i - 1] - nums[i] + 1
            nums[i] = nums[i - 1] + 1
    return operations
```
We iterate through the array starting from the second element. For each element, we check if it's smaller or equal to the previous one. If it is, we calculate the difference in value between the current and previous elements, add 1 to this difference, and accumulate it into a variable that keeps track of the operations needed to make the array strictly increasing. After that, we update the current element by adding 1 to the previous element, making them strictly increasing. We do this for all elements in the array, and finally return the accumulated operations needed. This approach has a time complexity of O(n) where n is the length of the array.

## A solution in Javascript

```javascript
function minOperations(nums) {
    let operations = 0;
    for (let i = 1; i < nums.length; ++i) {
        if (nums[i] <= nums[i - 1]) {
            operations += nums[i - 1] - nums[i] + 1;
            nums[i] = nums[i - 1] + 1;
        }
    }
    return operations;
}
```
We iterate through the array starting from the second element. For each element, we check if it's smaller or equal to the previous one. If it is, we calculate the difference in value between the current and previous elements, add 1 to this difference, and accumulate it into a variable that keeps track of the operations needed to make the array strictly increasing. After that, we update the current element by adding 1 to the previous element, making them strictly increasing. We do this for all elements in the array, and finally return the accumulated operations needed. This approach has a time complexity of O(n) where n is the length of the array.


# Check if All Characters Have Equal Number of Occurrences

- slug: check-if-all-characters-have-equal-number-of-occurrences
- difficulty: Easy

Given a string `s`, return `true` _if_ `s` _is a **good** string, or_ `false` _otherwise_.

A string `s` is **good** if **all** the characters that appear in `s` have the **same** number of occurrences (i.e., the same frequency).

**Example 1:**

**Input:** s =  "abacbc "
**Output:** true
**Explanation:** The characters that appear in s are 'a', 'b', and 'c'. All characters occur 2 times in s.

**Example 2:**

**Input:** s =  "aaabb "
**Output:** false
**Explanation:** The characters that appear in s are 'a' and 'b'.
'a' occurs 3 times while 'b' occurs 2 times, which is not the same number of times.

**Constraints:**

*   `1 <= s.length <= 1000`
*   `s` consists of lowercase English letters.

## A solution in Java

```java
public int makeStringSorted(String s) {
    final int mod = 1000000007;
    int n = s.length();
    int[] fact = new int[n + 1];
    int[] inv = new int[n + 1];
    fact[0] = inv[0] = 1;
    for (int i = 1; i <= n; ++i) {
        fact[i] = (int)((1L * fact[i - 1] * i) % mod);
        inv[i] = (int)((1L * inv[i - 1] * (mod - mod / i)) % mod);
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        int less_than = 0;
        for (int j = i + 1; j < n; ++j) {
            if (s.charAt(j) < s.charAt(i)) ++less_than;
        }
        ans = (int)((ans + 1L * less_than * fact[n - i - 1]) % mod);
    }
    return ans;
}
```
The algorithm consists of the following steps:

1. Initialize the factorials and inverse factorials for numbers up to the length of the given string, using modulo arithmetic.
2. For each character in the string, count the number of characters to the right that are less than the current character.
3. Multiply that count by the factorial of the number of remaining characters to the right, modulo the large prime number, and add it to the result.

In this way, the algorithm takes into account all possible permutations generated through the process of sorting, accumulating the required operations to make the string sorted.

## A solution in C++

```cpp
int makeStringSorted(string s) {
    const int mod = 1e9 + 7;
    int n = s.size();
    vector<int> fact(n + 1, 1);
    vector<int> inv(n + 1, 1);
    for (int i = 1; i <= n; ++i) {
        fact[i] = 1LL * fact[i - 1] * i % mod;
        inv[i] = 1LL * inv[i - 1] * (mod - mod / i) % mod;
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        int less_than = 0;
        for (int j = i + 1; j < n; ++j) {
            if (s[j] < s[i]) ++less_than;
        }
        ans = (ans + 1LL * less_than * fact[n - i - 1] % mod) % mod;
    }
    return ans;
}
```
The algorithm consists of the following steps:

1. Initialize the factorials and inverse factorials for numbers up to the length of the given string, using modulo arithmetic.
2. For each character in the string, count the number of characters to the right that are less than the current character.
3. Multiply that count by the factorial of the number of remaining characters to the right, modulo the large prime number, and add it to the result.

In this way, the algorithm takes into account all possible permutations generated through the process of sorting, accumulating the required operations to make the string sorted.

## A solution in Python

```python
def make_string_sorted(s):
    mod = 1000000007
    n = len(s)
    fact = [1] * (n + 1)
    inv = [1] * (n + 1)
    for i in range(1, n + 1):
        fact[i] = fact[i - 1] * i % mod
        inv[i] = inv[i - 1] * (mod - mod // i) % mod

    ans = 0
    for i in range(n):
        less_than = 0
        for j in range(i + 1, n):
            if s[j] < s[i]:
                less_than += 1
        ans = (ans + less_than * fact[n - i - 1]) % mod
    return ans
```
The algorithm consists of the following steps:

1. Initialize the factorials and inverse factorials for numbers up to the length of the given string, using modulo arithmetic.
2. For each character in the string, count the number of characters to the right that are less than the current character.
3. Multiply that count by the factorial of the number of remaining characters to the right, modulo the large prime number, and add it to the result.

In this way, the algorithm takes into account all possible permutations generated through the process of sorting, accumulating the required operations to make the string sorted.

## A solution in Javascript

```javascript
function makeStringSorted(s) {
    const mod = 1e9 + 7;
    const n = s.length;
    const fact = new Array(n + 1).fill(1);
    const inv = new Array(n + 1).fill(1);

    for (let i = 1; i <= n; ++i) {
        fact[i] = BigInt(fact[i - 1] * i % mod);
        inv[i] = BigInt(inv[i - 1] * (mod - Math.floor(mod / i)) % mod);
    }

    let ans = 0;
    for (let i = 0; i < n; ++i) {
        let less_than = 0;
        for (let j = i + 1; j < n; ++j) {
            if (s[j] < s[i]) ++less_than;
        }
        ans = Number((BigInt(ans) + BigInt(less_than) * fact[n - i - 1]) % BigInt(mod));
    }

    return ans;
}
```
The algorithm consists of the following steps:

1. Initialize the factorials and inverse factorials for numbers up to the length of the given string, using modulo arithmetic.
2. For each character in the string, count the number of characters to the right that are less than the current character.
3. Multiply that count by the factorial of the number of remaining characters to the right, modulo the large prime number, and add it to the result.

In this way, the algorithm takes into account all possible permutations generated through the process of sorting, accumulating the required operations to make the string sorted.


# The Number of the Smallest Unoccupied Chair

- slug: the-number-of-the-smallest-unoccupied-chair
- difficulty: Medium

There is a party where `n` friends numbered from `0` to `n - 1` are attending. There is an **infinite** number of chairs in this party that are numbered from `0` to `infinity`. When a friend arrives at the party, they sit on the unoccupied chair with the **smallest number**.

*   For example, if chairs `0`, `1`, and `5` are occupied when a friend comes, they will sit on chair number `2`.

When a friend leaves the party, their chair becomes unoccupied at the moment they leave. If another friend arrives at that same moment, they can sit in that chair.

You are given a **0-indexed** 2D integer array `times` where `times[i] = [arrivali, leavingi]`, indicating the arrival and leaving times of the `ith` friend respectively, and an integer `targetFriend`. All arrival times are **distinct**.

Return _the **chair number** that the friend numbered_ `targetFriend` _will sit on_.

**Example 1:**

**Input:** times = \[\[1,4\],\[2,3\],\[4,6\]\], targetFriend = 1
**Output:** 1
**Explanation:**
- Friend 0 arrives at time 1 and sits on chair 0.
- Friend 1 arrives at time 2 and sits on chair 1.
- Friend 1 leaves at time 3 and chair 1 becomes empty.
- Friend 0 leaves at time 4 and chair 0 becomes empty.
- Friend 2 arrives at time 4 and sits on chair 0.
Since friend 1 sat on chair 1, we return 1.

**Example 2:**

**Input:** times = \[\[3,10\],\[1,5\],\[2,6\]\], targetFriend = 0
**Output:** 2
**Explanation:**
- Friend 1 arrives at time 1 and sits on chair 0.
- Friend 2 arrives at time 2 and sits on chair 1.
- Friend 0 arrives at time 3 and sits on chair 2.
- Friend 1 leaves at time 5 and chair 0 becomes empty.
- Friend 2 leaves at time 6 and chair 1 becomes empty.
- Friend 0 leaves at time 10 and chair 2 becomes empty.
Since friend 0 sat on chair 2, we return 2.

**Constraints:**

*   `n == times.length`
*   `2 <= n <= 104`
*   `times[i].length == 2`
*   `1 <= arrivali < leavingi <= 105`
*   `0 <= targetFriend <= n - 1`
*   Each `arrivali` time is **distinct**.

## A solution in Java

```java
import java.util.*;

public int smallestChair(int[][] times, int targetFriend) {
    TreeMap<Integer, Integer> events = new TreeMap<>();
    for (int i = 0; i < times.length; ++i) {
        events.put(times[i][0], i);
        events.put(times[i][1], ~i);
    }

    TreeSet<Integer> availableChairs = new TreeSet<>();

    for (int i = 0; i < times.length; i++) {
        availableChairs.add(i);
    }

    int[] assignedChair = new int[times.length];

    for (Map.Entry<Integer, Integer> entry : events.entrySet()) {
        int idx = entry.getValue();
        if (idx >= 0) {
            int chair = availableChairs.first();
            availableChairs.remove(chair);
            assignedChair[idx] = chair;
            if (idx == targetFriend) return chair;
        } else {
            availableChairs.add(assignedChair[~idx]);
        }
    }

    return -1;
}
```
First, create a data structure `events` to store the arrival and leaving events sorted by time. Then, initialize `availableChairs` as a sorted set containing integers from 0 to n-1, and `assignedChair` as a list of size n.

Then, iterate through the events. If the current event is an arrival event, pop the smallest chair from `availableChairs` and assign it to the current friend, storing the assigned chair in `assignedChair`. If the current friend is `targetFriend`, return the assigned chair immediately. If the current event is a leaving event, add the assigned chair back to `availableChairs`.

The time complexity is O(n log n) due to the time required for inserting and deleting elements in the sorted data structures.

## A solution in C++

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

int smallestChair(std::vector<std::vector<int>>& times, int targetFriend) {
    std::multimap<int, int> events;
    for (int i = 0; i < times.size(); ++i) {
        events.insert({times[i][0], i});
        events.insert({times[i][1], ~i});
    }

    std::set<int> availableChairs;
    std::vector<int> assignedChair(times.size());

    for (const auto &[time, idx] : events) {
        if (idx >= 0) {
            int chair = *availableChairs.begin();
            availableChairs.erase(availableChairs.begin());
            assignedChair[idx] = chair;
            if (idx == targetFriend) return chair;
        } else {
            availableChairs.insert(assignedChair[~idx]);
        }
    }

    return -1;
}
```
First, create a data structure `events` to store the arrival and leaving events sorted by time. Then, initialize `availableChairs` as a sorted set containing integers from 0 to n-1, and `assignedChair` as a list of size n.

Then, iterate through the events. If the current event is an arrival event, pop the smallest chair from `availableChairs` and assign it to the current friend, storing the assigned chair in `assignedChair`. If the current friend is `targetFriend`, return the assigned chair immediately. If the current event is a leaving event, add the assigned chair back to `availableChairs`.

The time complexity is O(n log n) due to the time required for inserting and deleting elements in the sorted data structures.

## A solution in Python

```python
from sortedcontainers import SortedDict
from sortedcontainers import SortedSet

def smallestChair(times, targetFriend):
    events = SortedDict()
    for i, (arrival, leaving) in enumerate(times):
        events[arrival] = i
        events[leaving] = ~i

    availableChairs = SortedSet(range(len(times)))
    assignedChair = [0] * len(times)

    for time, idx in events.items():
        if idx >= 0:
            chair = availableChairs.pop(0)
            assignedChair[idx] = chair
            if idx == targetFriend:
                return chair
        else:
            availableChairs.add(assignedChair[~idx])

    return -1
```
First, create a data structure `events` to store the arrival and leaving events sorted by time. Then, initialize `availableChairs` as a sorted set containing integers from 0 to n-1, and `assignedChair` as a list of size n.

Then, iterate through the events. If the current event is an arrival event, pop the smallest chair from `availableChairs` and assign it to the current friend, storing the assigned chair in `assignedChair`. If the current friend is `targetFriend`, return the assigned chair immediately. If the current event is a leaving event, add the assigned chair back to `availableChairs`.

The time complexity is O(n log n) due to the time required for inserting and deleting elements in the sorted data structures.

## A solution in Javascript

```javascript
function smallestChair(times, targetFriend) {
    const events = new Map();
    for (let i = 0; i < times.length; ++i) {
        events.set(times[i][0], i);
        events.set(times[i][1], ~i);
    }

    const availableChairs = new Set(Array.from({length: times.length}, (_, i) => i));

    const assignedChair = [];

    for (const [time, idx] of events) {
        if (idx >= 0) {
            const chair = Math.min(...availableChairs);
            availableChairs.delete(chair);
            assignedChair[idx] = chair;
            if (idx == targetFriend) return chair;
        } else {
            availableChairs.add(assignedChair[~idx]);
        }
    }

    return -1;
}
```
First, create a data structure `events` to store the arrival and leaving events sorted by time. Then, initialize `availableChairs` as a sorted set containing integers from 0 to n-1, and `assignedChair` as a list of size n.

Then, iterate through the events. If the current event is an arrival event, pop the smallest chair from `availableChairs` and assign it to the current friend, storing the assigned chair in `assignedChair`. If the current friend is `targetFriend`, return the assigned chair immediately. If the current event is a leaving event, add the assigned chair back to `availableChairs`.

The time complexity is O(n log n) due to the time required for inserting and deleting elements in the sorted data structures.


# Describe the Painting

- slug: describe-the-painting
- difficulty: Medium

There is a long and thin painting that can be represented by a number line. The painting was painted with multiple overlapping segments where each segment was painted with a **unique** color. You are given a 2D integer array `segments`, where `segments[i] = [starti, endi, colori]` represents the **half-closed segment** `[starti, endi)` with `colori` as the color.

The colors in the overlapping segments of the painting were **mixed** when it was painted. When two or more colors mix, they form a new color that can be represented as a **set** of mixed colors.

*   For example, if colors `2`, `4`, and `6` are mixed, then the resulting mixed color is `{2,4,6}`.

For the sake of simplicity, you should only output the **sum** of the elements in the set rather than the full set.

You want to **describe** the painting with the **minimum** number of non-overlapping **half-closed segments** of these mixed colors. These segments can be represented by the 2D array `painting` where `painting[j] = [leftj, rightj, mixj]` describes a **half-closed segment** `[leftj, rightj)` with the mixed color **sum** of `mixj`.

*   For example, the painting created with `segments = [[1,4,5],[1,7,7]]` can be described by `painting = [[1,4,12],[4,7,7]]` because:
    *   `[1,4)` is colored `{5,7}` (with a sum of `12`) from both the first and second segments.
    *   `[4,7)` is colored `{7}` from only the second segment.

Return _the 2D array_ `painting` _describing the finished painting (excluding any parts that are **not** painted). You may return the segments in **any order**_.

A **half-closed segment** `[a, b)` is the section of the number line between points `a` and `b` **including** point `a` and **not including** point `b`.

**Example 1:**

**Input:** segments = \[\[1,4,5\],\[4,7,7\],\[1,7,9\]\]
**Output:** \[\[1,4,14\],\[4,7,16\]\]
**Explanation:** The painting can be described as follows:
- \[1,4) is colored {5,9} (with a sum of 14) from the first and third segments.
- \[4,7) is colored {7,9} (with a sum of 16) from the second and third segments.

**Example 2:**

**Input:** segments = \[\[1,7,9\],\[6,8,15\],\[8,10,7\]\]
**Output:** \[\[1,6,9\],\[6,7,24\],\[7,8,15\],\[8,10,7\]\]
**Explanation:** The painting can be described as follows:
- \[1,6) is colored 9 from the first segment.
- \[6,7) is colored {9,15} (with a sum of 24) from the first and second segments.
- \[7,8) is colored 15 from the second segment.
- \[8,10) is colored 7 from the third segment.

**Example 3:**

**Input:** segments = \[\[1,4,5\],\[1,4,7\],\[4,7,1\],\[4,7,11\]\]
**Output:** \[\[1,4,12\],\[4,7,12\]\]
**Explanation:** The painting can be described as follows:
- \[1,4) is colored {5,7} (with a sum of 12) from the first and second segments.
- \[4,7) is colored {1,11} (with a sum of 12) from the third and fourth segments.
Note that returning a single segment \[1,7) is incorrect because the mixed color sets are different.

**Constraints:**

*   `1 <= segments.length <= 2 * 104`
*   `segments[i].length == 3`
*   `1 <= starti < endi <= 105`
*   `1 <= colori <= 109`
*   Each `colori` is distinct.

## A solution in Java

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

public List<List<Integer>> splitPainting(int[][] segments) {
    TreeMap<Integer, Integer> line = new TreeMap<>();
    for (int[] s : segments) {
        int start = s[0];
        int end = s[1];
        int color = s[2];
        line.put(start, line.getOrDefault(start, 0) + color);
        line.put(end, line.getOrDefault(end, 0) - color);
    }
    List<List<Integer>> res = new ArrayList<>();
    int pre = 0, sum = 0;
    for (Map.Entry<Integer, Integer> entry : line.entrySet()) {
        if (pre > 0) {
            if (sum > 0) {
                List<Integer> temp = new ArrayList<>();
                temp.add(pre);
                temp.add(entry.getKey());
                temp.add(sum);
                res.add(temp);
            }
        }
        pre = entry.getKey();
        sum += entry.getValue();
    }
    return res;
}
```
The algorithm uses a sweep line approach to solve the problem. First, we traverse through the input segments, and maintain a map `line` that stores the sum of the colors at each starting and ending point of the segments. The starting points will have positive values, and the ending points will have negative values.

Next, we iterate through the sorted keys (i.e., the points) of the map, and for each key, we update the sum of colors until we reach the next point. During this process, we construct the non-overlapping segments with their respective mixed color sums and add them to the result.

Finally, we return the resulting 2D array containing the non-overlapping segments describing the painting. Note that the segments can be returned in any order since there is no specific requirement about the order in which they appear in the output.

## A solution in C++

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

vector<vector<int>> splitPainting(vector<vector<int>>& segments) {
    map<int, int> line;
    for (const vector<int>& s : segments) {
        int start = s[0];
        int end = s[1];
        int color = s[2];
        line[start] += color;
        line[end] -= color;
    }
    vector<vector<int>> res;
    int pre = 0, sum = 0;
    for (auto it = line.begin(); it != line.end(); ++it) {
        if (pre > 0) {
            if (sum > 0) {
                res.push_back({pre, it->first, sum});
            }
        }
        pre = it->first;
        sum += it->second;
    }
    return res;
}
```
The algorithm uses a sweep line approach to solve the problem. First, we traverse through the input segments, and maintain a map `line` that stores the sum of the colors at each starting and ending point of the segments. The starting points will have positive values, and the ending points will have negative values.

Next, we iterate through the sorted keys (i.e., the points) of the map, and for each key, we update the sum of colors until we reach the next point. During this process, we construct the non-overlapping segments with their respective mixed color sums and add them to the result.

Finally, we return the resulting 2D array containing the non-overlapping segments describing the painting. Note that the segments can be returned in any order since there is no specific requirement about the order in which they appear in the output.

## A solution in Python

```python
def splitPainting(segments):
    line = {}
    for s in segments:
        start, end, color = s
        if start not in line:
            line[start] = 0
        if end not in line:
            line[end] = 0
        line[start] += color
        line[end] -= color
    res = []
    pre = 0
    sum = 0
    for key in sorted(line.keys()):
        if pre > 0:
            if sum > 0:
                res.append([pre, key, sum])
        pre = key
        sum += line[key]
    return res
```
The algorithm uses a sweep line approach to solve the problem. First, we traverse through the input segments, and maintain a map `line` that stores the sum of the colors at each starting and ending point of the segments. The starting points will have positive values, and the ending points will have negative values.

Next, we iterate through the sorted keys (i.e., the points) of the map, and for each key, we update the sum of colors until we reach the next point. During this process, we construct the non-overlapping segments with their respective mixed color sums and add them to the result.

Finally, we return the resulting 2D array containing the non-overlapping segments describing the painting. Note that the segments can be returned in any order since there is no specific requirement about the order in which they appear in the output.

## A solution in Javascript

```javascript
function splitPainting(segments) {
    let line = new Map();
    for (const s of segments) {
        let start = s[0];
        let end = s[1];
        let color = s[2];
        line.set(start, (line.get(start) || 0) + color);
        line.set(end, (line.get(end) || 0) - color);
    }
    let res = [];
    let pre = 0, sum = 0;
    for (const [key, value] of Array.from(line.entries()).sort()) {
        if (pre > 0) {
            if (sum > 0) {
                res.push([pre, key, sum]);
            }
        }
        pre = key;
        sum += value;
    }
    return res;
}
```
The algorithm uses a sweep line approach to solve the problem. First, we traverse through the input segments, and maintain a map `line` that stores the sum of the colors at each starting and ending point of the segments. The starting points will have positive values, and the ending points will have negative values.

Next, we iterate through the sorted keys (i.e., the points) of the map, and for each key, we update the sum of colors until we reach the next point. During this process, we construct the non-overlapping segments with their respective mixed color sums and add them to the result.

Finally, we return the resulting 2D array containing the non-overlapping segments describing the painting. Note that the segments can be returned in any order since there is no specific requirement about the order in which they appear in the output.