# Brace Expansion

- slug: brace-expansion
- difficulty: Medium

You are given a string `s` representing a list of words. Each letter in the word has one or more options.

*   If there is one option, the letter is represented as is.
*   If there is more than one option, then curly braces delimit the options. For example, `"{a,b,c} "` represents options `[ "a ", "b ", "c "]`.

For example, if `s = "a{b,c} "`, the first character is always `'a'`, but the second character can be `'b'` or `'c'`. The original list is `[ "ab ", "ac "]`.

Return all words that can be formed in this manner, **sorted** in lexicographical order.

**Example 1:**

**Input:** s = "{a,b}c{d,e}f"
**Output:** \["acdf","acef","bcdf","bcef"\]

**Example 2:**

**Input:** s = "abcd"
**Output:** \["abcd"\]

**Constraints:**

*   `1 <= s.length <= 50`
*   `s` consists of curly brackets `'{}'`, commas `','`, and lowercase English letters.
*   `s` is guaranteed to be a valid input.
*   There are no nested curly brackets.
*   All characters inside a pair of consecutive opening and ending curly brackets are different.

## A solution in Java

```java
import java.util.HashMap;
import java.util.Map;

public int longestArithSeqLength(int[] nums) {
    int n = nums.length;
    int longest = 0;
    Map<Integer, Integer>[] dp = new HashMap[n];

    for (int i = 0; i < n; i++) {
        dp[i] = new HashMap<Integer, Integer>();
        for (int j = 0; j < i; j++) {
            int diff = nums[i] - nums[j];
            dp[i].put(diff, dp[j].containsKey(diff) ? dp[j].get(diff) + 1 : 2);
            longest = Math.max(longest, dp[i].get(diff));
        }
    }

    return longest;
}
```
The function uses dynamic programming to solve the problem. A `dp` array of hashmaps/dictionaries is created to store intermediate lengths of arithmetic subsequences at each index. For each pair of elements in the array, calculate their difference, and use that difference as a key in each corresponding `dp` hashmap/dictionary. This allows us to keep track of the length of the longest arithmetic subsequence ending at index `i` with that difference.

If we find a difference that already exists in the hashmap/dictionary at the previous index, it means that there is an arithmetic subsequence with that difference that has been seen before. In this case, the length of the arithmetic subsequence is incremented by 1. If not, a new arithmetic subsequence has been found with just two elements.

Finally, we keep updating the `longest` variable to store the maximum length seen so far, so that it holds the length of the longest arithmetic subsequence at the end of the loop.

## A solution in C++

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

int longestArithSeqLength(vector<int>& nums) {
    int n = nums.size();
    int longest = 0;
    vector<unordered_map<int, int>> dp(n);

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < i; ++j) {
            int diff = nums[i] - nums[j];
            dp[i][diff] = dp[j].count(diff) ? dp[j][diff] + 1 : 2;
            longest = max(longest, dp[i][diff]);
        }
    }

    return longest;
}
```
The function uses dynamic programming to solve the problem. A `dp` array of hashmaps/dictionaries is created to store intermediate lengths of arithmetic subsequences at each index. For each pair of elements in the array, calculate their difference, and use that difference as a key in each corresponding `dp` hashmap/dictionary. This allows us to keep track of the length of the longest arithmetic subsequence ending at index `i` with that difference.

If we find a difference that already exists in the hashmap/dictionary at the previous index, it means that there is an arithmetic subsequence with that difference that has been seen before. In this case, the length of the arithmetic subsequence is incremented by 1. If not, a new arithmetic subsequence has been found with just two elements.

Finally, we keep updating the `longest` variable to store the maximum length seen so far, so that it holds the length of the longest arithmetic subsequence at the end of the loop.

## A solution in Python

```python
def longestArithSeqLength(nums):
    n = len(nums)
    longest = 0
    dp = [{} for _ in range(n)]

    for i in range(n):
        for j in range(i):
            diff = nums[i] - nums[j]
            dp[i][diff] = dp[j].get(diff, 1) + 1
            longest = max(longest, dp[i][diff])

    return longest
```
The function uses dynamic programming to solve the problem. A `dp` array of hashmaps/dictionaries is created to store intermediate lengths of arithmetic subsequences at each index. For each pair of elements in the array, calculate their difference, and use that difference as a key in each corresponding `dp` hashmap/dictionary. This allows us to keep track of the length of the longest arithmetic subsequence ending at index `i` with that difference.

If we find a difference that already exists in the hashmap/dictionary at the previous index, it means that there is an arithmetic subsequence with that difference that has been seen before. In this case, the length of the arithmetic subsequence is incremented by 1. If not, a new arithmetic subsequence has been found with just two elements.

Finally, we keep updating the `longest` variable to store the maximum length seen so far, so that it holds the length of the longest arithmetic subsequence at the end of the loop.

## A solution in Javascript

```javascript
function longestArithSeqLength(nums) {
    const n = nums.length;
    let longest = 0;
    const dp = Array.from({ length: n }, () => ({}));

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < i; j++) {
            const diff = nums[i] - nums[j];
            dp[i][diff] = (dp[j][diff] || 1) + 1;
            longest = Math.max(longest, dp[i][diff]);
        }
    }

    return longest;
}
```
The function uses dynamic programming to solve the problem. A `dp` array of hashmaps/dictionaries is created to store intermediate lengths of arithmetic subsequences at each index. For each pair of elements in the array, calculate their difference, and use that difference as a key in each corresponding `dp` hashmap/dictionary. This allows us to keep track of the length of the longest arithmetic subsequence ending at index `i` with that difference.

If we find a difference that already exists in the hashmap/dictionary at the previous index, it means that there is an arithmetic subsequence with that difference that has been seen before. In this case, the length of the arithmetic subsequence is incremented by 1. If not, a new arithmetic subsequence has been found with just two elements.

Finally, we keep updating the `longest` variable to store the maximum length seen so far, so that it holds the length of the longest arithmetic subsequence at the end of the loop.


# Confusing Number II

- slug: confusing-number-ii
- difficulty: Hard

A **confusing number** is a number that when rotated `180` degrees becomes a different number with **each digit valid**.

We can rotate digits of a number by `180` degrees to form new digits.

*   When `0`, `1`, `6`, `8`, and `9` are rotated `180` degrees, they become `0`, `1`, `9`, `8`, and `6` respectively.
*   When `2`, `3`, `4`, `5`, and `7` are rotated `180` degrees, they become **invalid**.

Note that after rotating a number, we can ignore leading zeros.

*   For example, after rotating `8000`, we have `0008` which is considered as just `8`.

Given an integer `n`, return _the number of **confusing numbers** in the inclusive range_ `[1, n]`.

**Example 1:**

**Input:** n = 20
**Output:** 6
**Explanation:** The confusing numbers are \[6,9,10,16,18,19\].
6 converts to 9.
9 converts to 6.
10 converts to 01 which is just 1.
16 converts to 91.
18 converts to 81.
19 converts to 61.

**Example 2:**

**Input:** n = 100
**Output:** 19
**Explanation:** The confusing numbers are \[6,9,10,16,18,19,60,61,66,68,80,81,86,89,90,91,98,99,100\].

**Constraints:**

*   `1 <= n <= 109`

## A solution in Java

```java
public int confusingNumberII(int n) {
    return helper(n, 0, new int[]{0, 1, 6, 8, 9});
}

private int helper(int n, int current, int[] validNums) {
    int count = 0;
    for (int num : validNums) {
        long next = current * 10 + num;
        if (next > n) break;
        if (current == 0 && next == 0) continue;
        if (next != rotate(next)) count++;
        count += helper(n, (int) next, validNums);
    }
    return count;
}

private int rotate(int num) {
    int rotated = 0;
    while (num > 0) {
        int digit = num % 10;
        if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 7)
            return -1;
        if (digit == 6) digit = 9;
        else if (digit == 9) digit = 6;
        rotated = rotated * 10 + digit;
        num /= 10;
    }
    return rotated;
}
```
This problem can be solve using a recursive approach. We generate confusing numbers one digit at a time and validate if it's a valid and different number when rotated. In the helper function, we loop through the valid rotations, generate the next number by appending a valid rotation digit, and track count if the generated number is valid and not equal to its rotated version. For better efficiency, we input a memo that tracks the valid digits and their corresponding rotations.
The algorithm works as follows:

1. Initialize count to 0.
2. Generate the number one digit at a time using depth-first search (DFS).
3. Check if the next number (current * 10 + num) is within the boundaries.
4. If the next number is valid and different than its rotated version, increase count.
5. Recursively call the helper function on the next number.
6. Return the count.

To rotate a given number, we loop through its digits from right to left, and append their rotations. If the digit cannot be rotated, we return the original number to avoid increasing the count of confusing numbers.

## A solution in C++

```cpp
int findConfusingNumbers(int num, int& n, unordered_map<int, int>& mp) {
    if (num > n) return 0;
    int rotated = 0, src = num, newNum;
    while (src > 0) {
        rotated = rotated * 10 + mp[src % 10];
        src /= 10;
    }
    return (num != rotated) + findConfusingNumbers(num * 10 + 6, n, mp)
           + findConfusingNumbers(num * 10 + 9, n, mp)
           + findConfusingNumbers(num * 10 + 0, n, mp)
           + findConfusingNumbers(num * 10 + 1, n, mp)
           + findConfusingNumbers(num * 10 + 8, n, mp);
}

int confusingNumberII(int n) {
    unordered_map<int, int> mp = {{0,0},{1,1},{6,9},{8,8},{9,6}};
    return findConfusingNumbers(6, n, mp) + findConfusingNumbers(9, n, mp) +
           findConfusingNumbers(1, n, mp) + findConfusingNumbers(8, n, mp) + findConfusingNumbers(0, n, mp);
}
```
This problem can be solve using a recursive approach. We generate confusing numbers one digit at a time and validate if it's a valid and different number when rotated. In the helper function, we loop through the valid rotations, generate the next number by appending a valid rotation digit, and track count if the generated number is valid and not equal to its rotated version. For better efficiency, we input a memo that tracks the valid digits and their corresponding rotations.
The algorithm works as follows:

1. Initialize count to 0.
2. Generate the number one digit at a time using depth-first search (DFS).
3. Check if the next number (current * 10 + num) is within the boundaries.
4. If the next number is valid and different than its rotated version, increase count.
5. Recursively call the helper function on the next number.
6. Return the count.

To rotate a given number, we loop through its digits from right to left, and append their rotations. If the digit cannot be rotated, we return the original number to avoid increasing the count of confusing numbers.

## A solution in Python

```python
def confusingNumberII(n):
    def helper(current):
        nonlocal count, validNums
        for num in validNums:
            next_num = current * 10 + num
            if next_num > n:
                break
            if current != 0 or next_num != 0:
                if next_num != rotate(next_num):
                    count += 1
                count = helper(next_num)
        return count

    def rotate(num):
        rotated = 0
        original = num
        while num > 0:
            digit = num % 10
            if digit in (2, 3, 4, 5, 7):
                return original
            revd = {0: 0, 1: 1, 6: 9, 8: 8, 9: 6}
            rotated = rotated * 10 + revd[digit]
            num //= 10
        return rotated

    count = 0
    validNums = [0, 1, 6, 8, 9]
    return helper(0)
```
This problem can be solve using a recursive approach. We generate confusing numbers one digit at a time and validate if it's a valid and different number when rotated. In the helper function, we loop through the valid rotations, generate the next number by appending a valid rotation digit, and track count if the generated number is valid and not equal to its rotated version. For better efficiency, we input a memo that tracks the valid digits and their corresponding rotations.
The algorithm works as follows:

1. Initialize count to 0.
2. Generate the number one digit at a time using depth-first search (DFS).
3. Check if the next number (current * 10 + num) is within the boundaries.
4. If the next number is valid and different than its rotated version, increase count.
5. Recursively call the helper function on the next number.
6. Return the count.

To rotate a given number, we loop through its digits from right to left, and append their rotations. If the digit cannot be rotated, we return the original number to avoid increasing the count of confusing numbers.

## A solution in Javascript

```javascript
var confusingNumberII = function(n) {
    const validNums = [0, 1, 6, 8, 9];

    function helper(current) {
        let count = 0;
        for (const num of validNums) {
            const nextNum = current * 10 + num;
            if (nextNum > n) break;
            if (current !== 0 || nextNum !== 0) {
                if (nextNum !== rotate(nextNum)) count += 1;
                count += helper(nextNum);
            }
        }
        return count;
    }

    function rotate(num) {
        let rotated = 0;
        while (num > 0) {
            const digit = num % 10;
            if ([2, 3, 4, 5, 7].includes(digit)) return -1;
            rotated = rotated * 10 + (digit === 6 ? 9 : (digit === 9 ? 6 : digit));
            num = Math.floor(num / 10);
        }
        return rotated;
    }

    return helper(0);
};
```
This problem can be solve using a recursive approach. We generate confusing numbers one digit at a time and validate if it's a valid and different number when rotated. In the helper function, we loop through the valid rotations, generate the next number by appending a valid rotation digit, and track count if the generated number is valid and not equal to its rotated version. For better efficiency, we input a memo that tracks the valid digits and their corresponding rotations.
The algorithm works as follows:

1. Initialize count to 0.
2. Generate the number one digit at a time using depth-first search (DFS).
3. Check if the next number (current * 10 + num) is within the boundaries.
4. If the next number is valid and different than its rotated version, increase count.
5. Recursively call the helper function on the next number.
6. Return the count.

To rotate a given number, we loop through its digits from right to left, and append their rotations. If the digit cannot be rotated, we return the original number to avoid increasing the count of confusing numbers.


# Duplicate Zeros

- slug: duplicate-zeros
- difficulty: Easy

Given a fixed-length integer array `arr`, duplicate each occurrence of zero, shifting the remaining elements to the right.

**Note** that elements beyond the length of the original array are not written. Do the above modifications to the input array in place and do not return anything.

**Example 1:**

**Input:** arr = \[1,0,2,3,0,4,5,0\]
**Output:** \[1,0,0,2,3,0,0,4\]
**Explanation:** After calling your function, the input array is modified to: \[1,0,0,2,3,0,0,4\]

**Example 2:**

**Input:** arr = \[1,2,3\]
**Output:** \[1,2,3\]
**Explanation:** After calling your function, the input array is modified to: \[1,2,3\]

**Constraints:**

*   `1 <= arr.length <= 104`
*   `0 <= arr[i] <= 9`

## A solution in Java

```java
public void duplicateZeros(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n - 1; ++i) {
        if (arr[i] == 0) {
            for (int j = n - 1; j > i + 1; --j) {
                arr[j] = arr[j - 1];
            }
            arr[++i] = 0;
        }
    }
}
```
The algorithm iterates through the input array `arr`. When a zero is encountered at position `i`, a second for loop or equivalent control structure (`for`, `while`, or `range` depending on the language) is used to shift all elements at positions greater than `i` to the right by one. The element at position `i + 1` is then set to zero, and the iterator `i` is incremented to skip the newly added zero. This process is repeated until the end of the array is reached, ensuring that consecutive zeros are processed correctly.

## A solution in C++

```cpp
void duplicateZeros(vector<int>& arr) {
    int n = arr.size();
    for (int i = 0; i < n - 1; ++i) {
        if (arr[i] == 0) {
            for (int j = n - 1; j > i + 1; --j) {
                arr[j] = arr[j - 1];
            }
            arr[++i] = 0;
        }
    }
}
```
The algorithm iterates through the input array `arr`. When a zero is encountered at position `i`, a second for loop or equivalent control structure (`for`, `while`, or `range` depending on the language) is used to shift all elements at positions greater than `i` to the right by one. The element at position `i + 1` is then set to zero, and the iterator `i` is incremented to skip the newly added zero. This process is repeated until the end of the array is reached, ensuring that consecutive zeros are processed correctly.

## A solution in Python

```python
def duplicateZeros(arr):
    n = len(arr)
    i = 0
    while i < n - 1:
        if arr[i] == 0:
            for j in range(n - 1, i + 1, -1):
                arr[j] = arr[j - 1]
            arr[i + 1] = 0
            i += 1
        i += 1
```
The algorithm iterates through the input array `arr`. When a zero is encountered at position `i`, a second for loop or equivalent control structure (`for`, `while`, or `range` depending on the language) is used to shift all elements at positions greater than `i` to the right by one. The element at position `i + 1` is then set to zero, and the iterator `i` is incremented to skip the newly added zero. This process is repeated until the end of the array is reached, ensuring that consecutive zeros are processed correctly.

## A solution in Javascript

```javascript
function duplicateZeros(arr) {
    const n = arr.length;
    for (let i = 0; i < n - 1; ++i) {
        if (arr[i] === 0) {
            for (let j = n - 1; j > i + 1; --j) {
                arr[j] = arr[j - 1];
            }
            arr[++i] = 0;
        }
    }
}
```
The algorithm iterates through the input array `arr`. When a zero is encountered at position `i`, a second for loop or equivalent control structure (`for`, `while`, or `range` depending on the language) is used to shift all elements at positions greater than `i` to the right by one. The element at position `i + 1` is then set to zero, and the iterator `i` is incremented to skip the newly added zero. This process is repeated until the end of the array is reached, ensuring that consecutive zeros are processed correctly.


# Largest Values From Labels

- slug: largest-values-from-labels
- difficulty: Medium

There is a set of `n` items. You are given two integer arrays `values` and `labels` where the value and the label of the `ith` element are `values[i]` and `labels[i]` respectively. You are also given two integers `numWanted` and `useLimit`.

Choose a subset `s` of the `n` elements such that:

*   The size of the subset `s` is **less than or equal to** `numWanted`.
*   There are **at most** `useLimit` items with the same label in `s`.

The **score** of a subset is the sum of the values in the subset.

Return _the maximum **score** of a subset_ `s`.

**Example 1:**

**Input:** values = \[5,4,3,2,1\], labels = \[1,1,2,2,3\], numWanted = 3, useLimit = 1
**Output:** 9
**Explanation:** The subset chosen is the first, third, and fifth items.

**Example 2:**

**Input:** values = \[5,4,3,2,1\], labels = \[1,3,3,3,2\], numWanted = 3, useLimit = 2
**Output:** 12
**Explanation:** The subset chosen is the first, second, and third items.

**Example 3:**

**Input:** values = \[9,8,8,7,6\], labels = \[0,0,0,1,1\], numWanted = 3, useLimit = 1
**Output:** 16
**Explanation:** The subset chosen is the first and fourth items.

**Constraints:**

*   `n == values.length == labels.length`
*   `1 <= n <= 2 * 104`
*   `0 <= values[i], labels[i] <= 2 * 104`
*   `1 <= numWanted, useLimit <= n`

## A solution in Java

```java
import java.util.*;

public int largestValsFromLabels(int[] values, int[] labels, int numWanted, int useLimit) {
    int n = values.length;
    int[][] items = new int[n][2];
    for (int i = 0; i < n; ++i) {
        items[i][0] = values[i];
        items[i][1] = labels[i];
    }

    Arrays.sort(items, (a, b) -> Integer.compare(b[0], a[0]));

    Map<Integer, Integer> labelCount = new HashMap<>();
    int ans = 0;

    for (int[] item : items) {
        labelCount.putIfAbsent(item[1], 0);
        if (labelCount.get(item[1]) < useLimit) {
            ans += item[0];
            labelCount.put(item[1], labelCount.get(item[1]) + 1);
            if (--numWanted == 0) break;
        }
    }

    return ans;
}
```
1. Create a list of pairs containing value and label.
2. Sort the list of pairs based on the value in decreasing order.
3. Initialize an empty hash table called 'labelCount' to store the count of each label in the selected subset.
4. Initialize 'ans' to 0, which will store the result of maximum score.
5. Iterate through the sorted list of pairs:
   a. If the label is not in 'labelCount', set the label count as 0.
   b. If the count of the current label is less than the 'useLimit', add the value to 'ans', increment the count of the label, and decrement 'numWanted'.
   c. If 'numWanted' becomes 0, break the loop.
6. Return 'ans'.

## A solution in C++

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

int largestValsFromLabels(std::vector<int>& values, std::vector<int>& labels, int numWanted, int useLimit) {
    std::vector<std::pair<int, int>> items;
    for (int i = 0; i < values.size(); ++i) {
        items.push_back({values[i], labels[i]});
    }

    std::sort(items.begin(), items.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
        return a.first > b.first;
    });

    std::unordered_map<int, int> labelCount;
    int ans = 0;

    for (const auto& item : items) {
        if (labelCount[item.second] < useLimit) {
            ans += item.first;
            labelCount[item.second]++;
            if (--numWanted == 0) break;
        }
    }
    return ans;
}
```
1. Create a list of pairs containing value and label.
2. Sort the list of pairs based on the value in decreasing order.
3. Initialize an empty hash table called 'labelCount' to store the count of each label in the selected subset.
4. Initialize 'ans' to 0, which will store the result of maximum score.
5. Iterate through the sorted list of pairs:
   a. If the label is not in 'labelCount', set the label count as 0.
   b. If the count of the current label is less than the 'useLimit', add the value to 'ans', increment the count of the label, and decrement 'numWanted'.
   c. If 'numWanted' becomes 0, break the loop.
6. Return 'ans'.

## A solution in Python

```python
from typing import List

def largestValsFromLabels(values: List[int], labels: List[int], numWanted: int, useLimit: int) -> int:
    items = list(zip(values, labels))
    items.sort(key=lambda x: x[0], reverse=True)

    label_count = {}
    ans = 0

    for value, label in items:
        if label not in label_count:
            label_count[label] = 0
        if label_count[label] < useLimit:
            ans += value
            label_count[label] += 1
            numWanted -= 1
            if numWanted == 0:
                break

    return ans
```
1. Create a list of pairs containing value and label.
2. Sort the list of pairs based on the value in decreasing order.
3. Initialize an empty hash table called 'labelCount' to store the count of each label in the selected subset.
4. Initialize 'ans' to 0, which will store the result of maximum score.
5. Iterate through the sorted list of pairs:
   a. If the label is not in 'labelCount', set the label count as 0.
   b. If the count of the current label is less than the 'useLimit', add the value to 'ans', increment the count of the label, and decrement 'numWanted'.
   c. If 'numWanted' becomes 0, break the loop.
6. Return 'ans'.

## A solution in Javascript

```javascript
function largestValsFromLabels(values, labels, numWanted, useLimit) {
    const items = values.map((value, i) => [value, labels[i]]);
    items.sort((a, b) => b[0] - a[0]);

    const labelCount = {};
    let ans = 0;

    for (const [value, label] of items) {
        if (!labelCount.hasOwnProperty(label)) {
            labelCount[label] = 0;
        }
        if (labelCount[label] < useLimit) {
            ans += value;
            labelCount[label]++;
            numWanted--;
            if (numWanted === 0) break;
        }
    }

    return ans;
}
```
1. Create a list of pairs containing value and label.
2. Sort the list of pairs based on the value in decreasing order.
3. Initialize an empty hash table called 'labelCount' to store the count of each label in the selected subset.
4. Initialize 'ans' to 0, which will store the result of maximum score.
5. Iterate through the sorted list of pairs:
   a. If the label is not in 'labelCount', set the label count as 0.
   b. If the count of the current label is less than the 'useLimit', add the value to 'ans', increment the count of the label, and decrement 'numWanted'.
   c. If 'numWanted' becomes 0, break the loop.
6. Return 'ans'.


# Shortest Path in Binary Matrix

- slug: shortest-path-in-binary-matrix
- difficulty: Medium

Given an `n x n` binary matrix `grid`, return _the length of the shortest **clear path** in the matrix_. If there is no clear path, return `-1`.

A **clear path** in a binary matrix is a path from the **top-left** cell (i.e., `(0, 0)`) to the **bottom-right** cell (i.e., `(n - 1, n - 1)`) such that:

*   All the visited cells of the path are `0`.
*   All the adjacent cells of the path are **8-directionally** connected (i.e., they are different and they share an edge or a corner).

The **length of a clear path** is the number of visited cells of this path.

**Example 1:**

**Input:** grid = \[\[0,1\],\[1,0\]\]
**Output:** 2

**Example 2:**

**Input:** grid = \[\[0,0,0\],\[1,1,0\],\[1,1,0\]\]
**Output:** 4

**Example 3:**

**Input:** grid = \[\[1,0,0\],\[1,1,0\],\[1,1,0\]\]
**Output:** -1

**Constraints:**

*   `n == grid.length`
*   `n == grid[i].length`
*   `1 <= n <= 100`
*   `grid[i][j] is 0 or 1`

## A solution in Java

```java
import java.util.*;

class Solution {
    public int shortestPathBinaryMatrix(int[][] grid) {
        int n = grid.length;
        if (grid[0][0] == 1 || grid[n - 1][n - 1] == 1) return -1;

        int[][] dir = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[]{0, 0});
        grid[0][0] = 1;

        int pathLength = 1;

        while (!q.isEmpty()) {
            int qlen = q.size();
            for (int i = 0; i < qlen; i++) {
                int[] cur = q.poll();
                int x = cur[0], y = cur[1];

                if (x == n - 1 && y == n - 1) return pathLength;

                for (int[] d : dir) {
                    int newX = x + d[0];
                    int newY = y + d[1];

                    if (newX >= 0 && newX < n && newY >= 0 && newY < n && grid[newX][newY] == 0) {
                        q.offer(new int[]{newX, newY});
                        grid[newX][newY] = 1;
                    }
                }
            }
            pathLength++;
        }

        return -1;
    }
}
```
The idea is to use BFS (Breadth First Search) algorithm to start from the top left (0, 0), explore reachable cells, and reach the bottom right (n-1, n-1). During the search, mark any visited cell as 1 to prevent revisiting the same cell.

1. Check if the top-left cell or the bottom-right cell is 1. If either of them is 1, return -1 because there is no valid path.
2. Define the 8 directions that can be taken from each cell.
3. Create a queue for BFS and initially push the top-left cell into the queue.
4. Initialize the path length as 1.
5. While the queue has elements in it:
   a. Store the length of the queue.
   b. For each element in the queue at that level of BFS, check if the current cell is the bottom-right cell. If yes, return path length.
   c. Otherwise, explore all possible 8 directions from the current cell. If the new cell is unvisited (0) and within the grid boundaries, push it to the queue and mark it visited.
   d. Increment the path length and repeat the process.
6. If the bottom-right cell is not reached, return -1.

## A solution in C++

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

using namespace std;

int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
    int n = grid.size();
    if (grid[0][0] == 1 || grid[n - 1][n - 1] == 1) return -1;

    vector<vector<int>> dir = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
    queue<pair<int, int>> q;
    q.push({0, 0});
    grid[0][0] = 1;

    int pathLength = 1;

    while (!q.empty()) {
        int qlen = q.size();
        for (int i = 0; i < qlen; i++) {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();

            if (x == n - 1 && y == n - 1) return pathLength;

            for (vector<int>& d : dir) {
                int newX = x + d[0];
                int newY = y + d[1];

                if (newX >= 0 && newX < n && newY >= 0 && newY < n && grid[newX][newY] == 0) {
                    q.push({newX, newY});
                    grid[newX][newY] = 1;
                }
            }
        }
        pathLength++;
    }

    return -1;
}
```
The idea is to use BFS (Breadth First Search) algorithm to start from the top left (0, 0), explore reachable cells, and reach the bottom right (n-1, n-1). During the search, mark any visited cell as 1 to prevent revisiting the same cell.

1. Check if the top-left cell or the bottom-right cell is 1. If either of them is 1, return -1 because there is no valid path.
2. Define the 8 directions that can be taken from each cell.
3. Create a queue for BFS and initially push the top-left cell into the queue.
4. Initialize the path length as 1.
5. While the queue has elements in it:
   a. Store the length of the queue.
   b. For each element in the queue at that level of BFS, check if the current cell is the bottom-right cell. If yes, return path length.
   c. Otherwise, explore all possible 8 directions from the current cell. If the new cell is unvisited (0) and within the grid boundaries, push it to the queue and mark it visited.
   d. Increment the path length and repeat the process.
6. If the bottom-right cell is not reached, return -1.

## A solution in Python

```python
from collections import deque

def shortestPathBinaryMatrix(grid):
    n = len(grid)
    if grid[0][0] or grid[n - 1][n - 1]: return -1

    dir = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
    q = deque([(0, 0)])
    grid[0][0] = 1

    pathLength = 1

    while q:
        qlen = len(q)
        for _ in range(qlen):
            x, y = q.popleft()

            if x == n - 1 and y == n - 1: return pathLength

            for d in dir:
                newX, newY = x + d[0], y + d[1]

                if 0 <= newX < n and 0 <= newY < n and grid[newX][newY] == 0:
                    q.append((newX, newY))
                    grid[newX][newY] = 1
        pathLength += 1

    return -1
```
The idea is to use BFS (Breadth First Search) algorithm to start from the top left (0, 0), explore reachable cells, and reach the bottom right (n-1, n-1). During the search, mark any visited cell as 1 to prevent revisiting the same cell.

1. Check if the top-left cell or the bottom-right cell is 1. If either of them is 1, return -1 because there is no valid path.
2. Define the 8 directions that can be taken from each cell.
3. Create a queue for BFS and initially push the top-left cell into the queue.
4. Initialize the path length as 1.
5. While the queue has elements in it:
   a. Store the length of the queue.
   b. For each element in the queue at that level of BFS, check if the current cell is the bottom-right cell. If yes, return path length.
   c. Otherwise, explore all possible 8 directions from the current cell. If the new cell is unvisited (0) and within the grid boundaries, push it to the queue and mark it visited.
   d. Increment the path length and repeat the process.
6. If the bottom-right cell is not reached, return -1.

## A solution in Javascript

```javascript
function shortestPathBinaryMatrix(grid) {
    const n = grid.length;
    if (grid[0][0] === 1 || grid[n - 1][n - 1] === 1) return -1;

    const dir = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
    const q = [[0, 0]];
    grid[0][0] = 1;

    let pathLength = 1;

    while (q.length > 0) {
        const qlen = q.length;
        for (let i = 0; i < qlen; i++) {
            const [x, y] = q.shift();

            if (x === n - 1 && y === n - 1) return pathLength;

            for (const d of dir) {
                const newX = x + d[0];
                const newY = y + d[1];

                if (newX >= 0 && newX < n && newY >= 0 && newY < n && grid[newX][newY] === 0) {
                    q.push([newX, newY]);
                    grid[newX][newY] = 1;
                }
            }
        }
        pathLength++;
    }

    return -1;
}
```
The idea is to use BFS (Breadth First Search) algorithm to start from the top left (0, 0), explore reachable cells, and reach the bottom right (n-1, n-1). During the search, mark any visited cell as 1 to prevent revisiting the same cell.

1. Check if the top-left cell or the bottom-right cell is 1. If either of them is 1, return -1 because there is no valid path.
2. Define the 8 directions that can be taken from each cell.
3. Create a queue for BFS and initially push the top-left cell into the queue.
4. Initialize the path length as 1.
5. While the queue has elements in it:
   a. Store the length of the queue.
   b. For each element in the queue at that level of BFS, check if the current cell is the bottom-right cell. If yes, return path length.
   c. Otherwise, explore all possible 8 directions from the current cell. If the new cell is unvisited (0) and within the grid boundaries, push it to the queue and mark it visited.
   d. Increment the path length and repeat the process.
6. If the bottom-right cell is not reached, return -1.


# Shortest Common Supersequence

- slug: shortest-common-supersequence
- difficulty: Hard

Given two strings `str1` and `str2`, return _the shortest string that has both_ `str1` _and_ `str2` _as **subsequences**_. If there are multiple valid strings, return **any** of them.

A string `s` is a **subsequence** of string `t` if deleting some number of characters from `t` (possibly `0`) results in the string `s`.

**Example 1:**

**Input:** str1 =  "abac ", str2 =  "cab "
**Output:**  "cabac "
**Explanation:**
str1 =  "abac " is a subsequence of  "cabac " because we can delete the first  "c ".
str2 =  "cab " is a subsequence of  "cabac " because we can delete the last  "ac ".
The answer provided is the shortest such string that satisfies these properties.

**Example 2:**

**Input:** str1 =  "aaaaaaaa ", str2 =  "aaaaaaaa "
**Output:**  "aaaaaaaa "

**Constraints:**

*   `1 <= str1.length, str2.length <= 1000`
*   `str1` and `str2` consist of lowercase English letters.

## A solution in Java

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

class Result {
    int min;
    int max;
}

int dfs(TreeNode node, Result result) {
    if (node == null) return 0;
    Result leftResult = new Result();
    Result rightResult = new Result();
    int leftDiff = dfs(node.left, leftResult);
    int rightDiff = dfs(node.right, rightResult);
    result.min = Math.min(node.val, Math.min(leftResult.min, rightResult.min));
    result.max = Math.max(node.val, Math.max(leftResult.max, rightResult.max));
    return Math.max(Math.max(leftDiff, rightDiff), Math.max(Math.abs(node.val - leftResult.min), Math.abs(node.val - rightResult.max)));
}

int maxAncestorDiff(TreeNode root) {
    Result result = new Result();
    return dfs(root, result);
}
```
The algorithm uses a depth-first search (DFS) to traverse the input binary tree. The base case is reached when the root node is `null`, in which case the maximum value and minimum value are set to positive and negative infinity, respectively. While traversing the nodes, the algorithm maintains the maximum and minimum values of each subtree, as well as the maximum absolute difference.

At each node of the tree, the algorithm compares the difference in the node's value to the minimum and maximum values of both the left and right subtrees. This way, the potential new maximum difference is computed by comparing the current maximum difference to the absolute differences $(node.val - leftMin)$ and $(node.val - rightMax)$. The final maximum absolute difference is returned after the entire tree has been traversed.

## A solution in C++

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

int dfs(TreeNode* node, int& mn, int& mx) {
    if (!node) return 0;
    int left_min = node->val, right_min = node->val;
    int left_max = node->val, right_max = node->val;
    int left_diff = dfs(node->left, left_min, left_max);
    int right_diff = dfs(node->right, right_min, right_max);
    mn = min(node->val, min(left_min, right_min));
    mx = max(node->val, max(left_max, right_max));
    return max(max(left_diff, right_diff), max(abs(node->val - left_min), abs(node->val - right_max)));
}
int maxAncestorDiff(TreeNode* root) {
    int mn = root->val, mx = root->val;
    return dfs(root, mn, mx);
}
```
The algorithm uses a depth-first search (DFS) to traverse the input binary tree. The base case is reached when the root node is `null`, in which case the maximum value and minimum value are set to positive and negative infinity, respectively. While traversing the nodes, the algorithm maintains the maximum and minimum values of each subtree, as well as the maximum absolute difference.

At each node of the tree, the algorithm compares the difference in the node's value to the minimum and maximum values of both the left and right subtrees. This way, the potential new maximum difference is computed by comparing the current maximum difference to the absolute differences $(node.val - leftMin)$ and $(node.val - rightMax)$. The final maximum absolute difference is returned after the entire tree has been traversed.

## 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 dfs(node):
    if not node:
        return 0, float('inf'), float('-inf')
    left_diff, left_min, left_max = dfs(node.left)
    right_diff, right_min, right_max = dfs(node.right)
    mn = min(node.val, left_min, right_min)
    mx = max(node.val, left_max, right_max)
    return max(max(left_diff, right_diff), max(abs(node.val - left_min), abs(node.val - right_max))), mn, mx

def maxAncestorDiff(root):
    diff, _, _ = dfs(root)
    return diff
```
The algorithm uses a depth-first search (DFS) to traverse the input binary tree. The base case is reached when the root node is `null`, in which case the maximum value and minimum value are set to positive and negative infinity, respectively. While traversing the nodes, the algorithm maintains the maximum and minimum values of each subtree, as well as the maximum absolute difference.

At each node of the tree, the algorithm compares the difference in the node's value to the minimum and maximum values of both the left and right subtrees. This way, the potential new maximum difference is computed by comparing the current maximum difference to the absolute differences $(node.val - leftMin)$ and $(node.val - rightMax)$. The final maximum absolute difference is returned after the entire tree has been traversed.

## A solution in Javascript

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

function dfs(node) {
    if (!node) return [0, Infinity, -Infinity];
    const [leftDiff, leftMin, leftMax] = dfs(node.left);
    const [rightDiff, rightMin, rightMax] = dfs(node.right);
    const mn = Math.min(node.val, leftMin, rightMin);
    const mx = Math.max(node.val, leftMax, rightMax);
    return [Math.max(Math.max(leftDiff, rightDiff), Math.max(Math.abs(node.val - leftMin), Math.abs(node.val - rightMax))), mn, mx];
}

function maxAncestorDiff(root) {
    const [diff, _, _] = dfs(root);
    return diff;
}
```
The algorithm uses a depth-first search (DFS) to traverse the input binary tree. The base case is reached when the root node is `null`, in which case the maximum value and minimum value are set to positive and negative infinity, respectively. While traversing the nodes, the algorithm maintains the maximum and minimum values of each subtree, as well as the maximum absolute difference.

At each node of the tree, the algorithm compares the difference in the node's value to the minimum and maximum values of both the left and right subtrees. This way, the potential new maximum difference is computed by comparing the current maximum difference to the absolute differences $(node.val - leftMin)$ and $(node.val - rightMax)$. The final maximum absolute difference is returned after the entire tree has been traversed.


# Statistics from a Large Sample

- slug: statistics-from-a-large-sample
- difficulty: Medium

You are given a large sample of integers in the range `[0, 255]`. Since the sample is so large, it is represented by an array `count` where `count[k]` is the **number of times** that `k` appears in the sample.

Calculate the following statistics:

*   `minimum`: The minimum element in the sample.
*   `maximum`: The maximum element in the sample.
*   `mean`: The average of the sample, calculated as the total sum of all elements divided by the total number of elements.
*   `median`:
    *   If the sample has an odd number of elements, then the `median` is the middle element once the sample is sorted.
    *   If the sample has an even number of elements, then the `median` is the average of the two middle elements once the sample is sorted.
*   `mode`: The number that appears the most in the sample. It is guaranteed to be **unique**.

Return _the statistics of the sample as an array of floating-point numbers_ `[minimum, maximum, mean, median, mode]`_. Answers within_ `10-5` _of the actual answer will be accepted._

**Example 1:**

**Input:** count = \[0,1,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\]
**Output:** \[1.00000,3.00000,2.37500,2.50000,3.00000\]
**Explanation:** The sample represented by count is \[1,2,2,2,3,3,3,3\].
The minimum and maximum are 1 and 3 respectively.
The mean is (1+2+2+2+3+3+3+3) / 8 = 19 / 8 = 2.375.
Since the size of the sample is even, the median is the average of the two middle elements 2 and 3, which is 2.5.
The mode is 3 as it appears the most in the sample.

**Example 2:**

**Input:** count = \[0,4,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\]
**Output:** \[1.00000,4.00000,2.18182,2.00000,1.00000\]
**Explanation:** The sample represented by count is \[1,1,1,1,2,2,2,3,3,4,4\].
The minimum and maximum are 1 and 4 respectively.
The mean is (1+1+1+1+2+2+2+3+3+4+4) / 11 = 24 / 11 = 2.18181818... (for display purposes, the output shows the rounded number 2.18182).
Since the size of the sample is odd, the median is the middle element 2.
The mode is 1 as it appears the most in the sample.

**Constraints:**

*   `count.length == 256`
*   `0 <= count[i] <= 109`
*   `1 <= sum(count) <= 109`
*   The mode of the sample that `count` represents is **unique**.

## A solution in Java

```java
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public TreeNode recoverFromPreorder(String S) {
    return helper(new java.util.Scanner(S), 0);
}

public TreeNode helper(java.util.Scanner scanner, int depth) {
    int numDashes = 0;
    while (scanner.hasNext("-")) {
        numDashes++;
        scanner.next("-");
    }

    if (numDashes != depth) {
        while (numDashes-- > 0) {
            scanner.next("-");
        }
        return null;
    }

    int val = scanner.nextInt();
    TreeNode node = new TreeNode(val);
    node.left = helper(scanner, depth + 1);
    node.right = helper(scanner, depth + 1);
    return node;
}
```
The algorithm starts by creating a helper function that operates on the given input string S and current depth (initially 0 for root).

The number of dashes at the current position is counted. If the number of dashes do not equal the depth, it means the current value is not meant for the current node, so we return null. Otherwise, we extract the value and create a new node with that value.

We then call the helper function recursively on the left and right children of the current node with incremented depth. These calls repeat the same process for each subtree.

After consuming the traversal string, the helper function returns the root of the recovered binary tree.

## A solution in C++

```cpp
#include <sstream>
#include <string>

using namespace std;

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

void helper(istringstream &iss, TreeNode* &node, int depth) {
    int d = 0;
    while (iss.peek() == '-') {
        iss.get();
        d++;
    }
    if (d != depth) {
        iss.putback('-');
        return;
    }
    int val;
    iss >> val;
    node = new TreeNode(val);
    helper(iss, node->left, depth + 1);
    helper(iss, node->right, depth + 1);
}

TreeNode* recoverFromPreorder(string S) {
    istringstream iss(S);
    TreeNode* root = nullptr;
    helper(iss, root, 0);
    return root;
}
```
The algorithm starts by creating a helper function that operates on the given input string S and current depth (initially 0 for root).

The number of dashes at the current position is counted. If the number of dashes do not equal the depth, it means the current value is not meant for the current node, so we return null. Otherwise, we extract the value and create a new node with that value.

We then call the helper function recursively on the left and right children of the current node with incremented depth. These calls repeat the same process for each subtree.

After consuming the traversal string, the helper function returns the root of the recovered binary tree.

## A solution in Python

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

def recoverFromPreorder(S: str) -> TreeNode:
    def helper() -> TreeNode:
        nonlocal depth, index
        num_dashes = 0
        while index < len(S) and S[index] == '-':
            num_dashes += 1
            index += 1
        if num_dashes != depth:
            index -= num_dashes
            return None
        val = 0
        while index < len(S) and S[index].isdigit():
            val = val * 10 + int(S[index])
            index += 1
        node = TreeNode(val)
        depth += 1
        node.left = helper()
        node.right = helper()
        depth -= 1
        return node

    depth, index = 0, 0
    return helper()
```
The algorithm starts by creating a helper function that operates on the given input string S and current depth (initially 0 for root).

The number of dashes at the current position is counted. If the number of dashes do not equal the depth, it means the current value is not meant for the current node, so we return null. Otherwise, we extract the value and create a new node with that value.

We then call the helper function recursively on the left and right children of the current node with incremented depth. These calls repeat the same process for each subtree.

After consuming the traversal string, the helper function returns the root of the recovered binary tree.

## A solution in Javascript

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

function recoverFromPreorder(S) {
    return helper(S, 0);
}

function helper(S, depth) {
    if (!S.length) return null;

    let numDashes = 0;
    let start = 0;
    while (S.charAt(start) === '-') {
        numDashes++;
        start++;
    }

    if (numDashes < depth) return null;

    S = S.substring(start - depth);
    let end = 0;
    while (S.charAt(end) !== '-' && end < S.length) end++;
    const val = parseInt(S.substring(0, end));

    const node = new TreeNode(val);
    S = S.substring(end);

    node.left = helper(S, depth + 1);
    node.right = helper(S, depth + 1);

    return node;
}
```
The algorithm starts by creating a helper function that operates on the given input string S and current depth (initially 0 for root).

The number of dashes at the current position is counted. If the number of dashes do not equal the depth, it means the current value is not meant for the current node, so we return null. Otherwise, we extract the value and create a new node with that value.

We then call the helper function recursively on the left and right children of the current node with incremented depth. These calls repeat the same process for each subtree.

After consuming the traversal string, the helper function returns the root of the recovered binary tree.


# Car Pooling

- slug: car-pooling
- difficulty: Medium

There is a car with `capacity` empty seats. The vehicle only drives east (i.e., it cannot turn around and drive west).

You are given the integer `capacity` and an array `trips` where `trips[i] = [numPassengersi, fromi, toi]` indicates that the `ith` trip has `numPassengersi` passengers and the locations to pick them up and drop them off are `fromi` and `toi` respectively. The locations are given as the number of kilometers due east from the car's initial location.

Return `true` _if it is possible to pick up and drop off all passengers for all the given trips, or_ `false` _otherwise_.

**Example 1:**

**Input:** trips = \[\[2,1,5\],\[3,3,7\]\], capacity = 4
**Output:** false

**Example 2:**

**Input:** trips = \[\[2,1,5\],\[3,3,7\]\], capacity = 5
**Output:** true

**Constraints:**

*   `1 <= trips.length <= 1000`
*   `trips[i].length == 3`
*   `1 <= numPassengersi <= 100`
*   `0 <= fromi < toi <= 1000`
*   `1 <= capacity <= 105`

## A solution in Java

```java
import java.util.Arrays;

public int[][] allCellsDistOrder(int rows, int cols, int rCenter, int cCenter) {
    int[][] coordinates = new int[rows * cols][2];

    int index = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            coordinates[index++] = new int[]{i, j};
        }
    }

    Arrays.sort(coordinates, (a, b) ->
        Math.abs(a[0] - rCenter) + Math.abs(a[1] - cCenter) - Math.abs(b[0] - rCenter) - Math.abs(b[1] - cCenter)
    );

    return coordinates;
}
```
1. First, we generate all the coordinate pairs (i, j) in the given rows x cols matrix and store them in a list named 'coordinates'.
2. Next, we sort the 'coordinates' list based on the distance from the (rCenter, cCenter). We calculate the distance between two points (r1, c1) and (r2, c2) using the formula: |r1 - r2| + |c1 - c2|.
3. Finally, we return the sorted coordinates list.

## A solution in C++

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

std::vector<std::vector<int>> allCellsDistOrder(int rows, int cols, int rCenter, int cCenter) {
    std::vector<std::vector<int>> coordinates;

    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            coordinates.push_back({i, j});
        }
    }

    std::sort(coordinates.begin(), coordinates.end(), [&](const std::vector<int>& a, const std::vector<int>& b) {
        return abs(a[0] - rCenter) + abs(a[1] - cCenter) < abs(b[0] - rCenter) + abs(b[1] - cCenter);
    });

    return coordinates;
}
```
1. First, we generate all the coordinate pairs (i, j) in the given rows x cols matrix and store them in a list named 'coordinates'.
2. Next, we sort the 'coordinates' list based on the distance from the (rCenter, cCenter). We calculate the distance between two points (r1, c1) and (r2, c2) using the formula: |r1 - r2| + |c1 - c2|.
3. Finally, we return the sorted coordinates list.

## A solution in Python

```python
def allCellsDistOrder(rows, cols, rCenter, cCenter):
    coordinates = [[i, j] for i in range(rows) for j in range(cols)]

    coordinates.sort(key=lambda x: abs(x[0] - rCenter) + abs(x[1] - cCenter))

    return coordinates
```
1. First, we generate all the coordinate pairs (i, j) in the given rows x cols matrix and store them in a list named 'coordinates'.
2. Next, we sort the 'coordinates' list based on the distance from the (rCenter, cCenter). We calculate the distance between two points (r1, c1) and (r2, c2) using the formula: |r1 - r2| + |c1 - c2|.
3. Finally, we return the sorted coordinates list.

## A solution in Javascript

```javascript
function allCellsDistOrder(rows, cols, rCenter, cCenter) {
    const coordinates = [];

    for (let i = 0; i < rows; ++i) {
        for (let j = 0; j < cols; ++j) {
            coordinates.push([i, j]);
        }
    }

    coordinates.sort((a, b) =>
        Math.abs(a[0] - rCenter) + Math.abs(a[1] - cCenter) - Math.abs(b[0] - rCenter) - Math.abs(b[1] - cCenter)
    );

    return coordinates;
}
```
1. First, we generate all the coordinate pairs (i, j) in the given rows x cols matrix and store them in a list named 'coordinates'.
2. Next, we sort the 'coordinates' list based on the distance from the (rCenter, cCenter). We calculate the distance between two points (r1, c1) and (r2, c2) using the formula: |r1 - r2| + |c1 - c2|.
3. Finally, we return the sorted coordinates list.


# Find in Mountain Array

- slug: find-in-mountain-array
- difficulty: Hard

_(This problem is an **interactive problem**.)_

You may recall that an array `arr` is a **mountain array** if and only if:

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

Given a mountain array `mountainArr`, return the **minimum** `index` such that `mountainArr.get(index) == target`. If such an `index` does not exist, return `-1`.

**You cannot access the mountain array directly.** You may only access the array using a `MountainArray` interface:

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

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

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `3 <= mountain_arr.length() <= 104`
*   `0 <= target <= 109`
*   `0 <= mountain_arr.get(index) <= 109`

## A solution in Java

```java
import java.util.Arrays;

public int twoCitySchedCost(int[][] costs) {
    Arrays.sort(costs, (a, b) -> (a[0] - a[1]) - (b[0] - b[1]));

    int totalCost = 0;
    int n = costs.length / 2;

    for (int i = 0; i < n; i++) {
        totalCost += costs[i][0] + costs[i + n][1];
    }

    return totalCost;
}
```
1. Sort the costs by the difference between the cost of flying to city A and city B. This will effectively prioritize the people who may benefit most from flying to a particular city.
2. Calculate the total cost by adding the costs for the first half of the sorted list flying to city A, and the latter half flying to city B.
3. Return the total cost as the result.

This greedy algorithm minimizes the total cost by selecting the closest suitable matchings for each city, ensuring that we get the lowest possible cost across all possibilities.

## A solution in C++

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

int twoCitySchedCost(std::vector<std::vector<int>>& costs) {
    std::sort(costs.begin(), costs.end(), [](const std::vector<int>& a, const std::vector<int>& b){
        return (a[0] - a[1]) < (b[0] - b[1]);
    });

    int totalCost = 0;
    int n = costs.size() / 2;

    for (int i = 0; i < n; i++) {
        totalCost += costs[i][0] + costs[i+n][1];
    }

    return totalCost;
}
```
1. Sort the costs by the difference between the cost of flying to city A and city B. This will effectively prioritize the people who may benefit most from flying to a particular city.
2. Calculate the total cost by adding the costs for the first half of the sorted list flying to city A, and the latter half flying to city B.
3. Return the total cost as the result.

This greedy algorithm minimizes the total cost by selecting the closest suitable matchings for each city, ensuring that we get the lowest possible cost across all possibilities.

## A solution in Python

```python
def twoCitySchedCost(costs):
    costs.sort(key=lambda x: x[0] - x[1])

    totalCost = 0
    n = len(costs) // 2

    for i in range(n):
        totalCost += costs[i][0] + costs[i + n][1]

    return totalCost
```
1. Sort the costs by the difference between the cost of flying to city A and city B. This will effectively prioritize the people who may benefit most from flying to a particular city.
2. Calculate the total cost by adding the costs for the first half of the sorted list flying to city A, and the latter half flying to city B.
3. Return the total cost as the result.

This greedy algorithm minimizes the total cost by selecting the closest suitable matchings for each city, ensuring that we get the lowest possible cost across all possibilities.

## A solution in Javascript

```javascript
function twoCitySchedCost(costs) {
    costs.sort((a, b) => (a[0] - a[1]) - (b[0] - b[1]));

    let totalCost = 0;
    const n = costs.length / 2;

    for (let i = 0; i < n; i++) {
        totalCost += costs[i][0] + costs[i + n][1];
    }

    return totalCost;
}
```
1. Sort the costs by the difference between the cost of flying to city A and city B. This will effectively prioritize the people who may benefit most from flying to a particular city.
2. Calculate the total cost by adding the costs for the first half of the sorted list flying to city A, and the latter half flying to city B.
3. Return the total cost as the result.

This greedy algorithm minimizes the total cost by selecting the closest suitable matchings for each city, ensuring that we get the lowest possible cost across all possibilities.


# Brace Expansion II

- slug: brace-expansion-ii
- difficulty: Hard

Under the grammar given below, strings can represent a set of lowercase words. Let `R(expr)` denote the set of words the expression represents.

The grammar can best be understood through simple examples:

*   Single letters represent a singleton set containing that word.
    *   `R( "a ") = { "a "}`
    *   `R( "w ") = { "w "}`
*   When we take a comma-delimited list of two or more expressions, we take the union of possibilities.
    *   `R( "{a,b,c} ") = { "a ", "b ", "c "}`
    *   `R( "{{a,b},{b,c}} ") = { "a ", "b ", "c "}` (notice the final set only contains each word at most once)
*   When we concatenate two expressions, we take the set of possible concatenations between two words where the first word comes from the first expression and the second word comes from the second expression.
    *   `R( "{a,b}{c,d} ") = { "ac ", "ad ", "bc ", "bd "}`
    *   `R( "a{b,c}{d,e}f{g,h} ") = { "abdfg ", "abdfh ", "abefg ", "abefh ", "acdfg ", "acdfh ", "acefg ", "acefh "}`

Formally, the three rules for our grammar:

*   For every lowercase letter `x`, we have `R(x) = {x}`.
*   For expressions `e1, e2, ... , ek` with `k >= 2`, we have `R({e1, e2, ...}) = R(e1) ∪ R(e2) ∪ ...`
*   For expressions `e1` and `e2`, we have `R(e1 + e2) = {a + b for (a, b) in R(e1) * R(e2)}`, where `+` denotes concatenation, and `*` denotes the cartesian product.

Given an expression representing a set of words under the given grammar, return _the sorted list of words that the expression represents_.

**Example 1:**

**Input:** expression =  "{a,b}{c,{d,e}} "
**Output:** \[ "ac ", "ad ", "ae ", "bc ", "bd ", "be "\]

**Example 2:**

**Input:** expression =  "{{a,z},a{b,c},{ab,z}} "
**Output:** \[ "a ", "ab ", "ac ", "z "\]
**Explanation:** Each distinct word is written only once in the final answer.

**Constraints:**

*   `1 <= expression.length <= 60`
*   `expression[i]` consists of `'{'`, `'}'`, `','`or lowercase English letters.
*   The given `expression` represents a set of words based on the grammar given in the description.

## A solution in Java

```java
import java.util.*;

class Solution {
    public List<String> braceExpansionII(String expression) {
        int[] i = new int[]{0};
        Set<String> parsedSet = parse(expression, i);
        List<String> result = new ArrayList<>(parsedSet);
        Collections.sort(result);
        return result;
    }

    private Set<String> parse(String expression, int[] i) {
        HashSet<String> current = new HashSet<>();
        current.add("");
        HashSet<String> result = new HashSet<>();

        while (i[0] < expression.length()) {
            char c = expression.charAt(i[0]++);
            if (c == '{') {
                HashSet<String> temp = new HashSet<>();
                for (String postfix : parse(expression, i)) {
                    for (String prefix : current) {
                        temp.add(prefix + postfix);
                    }
                }
                current = temp;
            } else if (c == '}') {
                break;
            } else if (c == ',') {
                result.addAll(current);
                current.clear();
                current.add("");
            } else {
                HashSet<String> temp = new HashSet<>();
                for (String s : current) {
                    temp.add(s + c);
                }
                current = temp;
            }
        }
        result.addAll(current);
        return result;
    }
}
```
The core of the algorithm is a parse function that takes an expression and current index. The parse function returns a set of possible strings based on the grammar. Initially, we call parse with the input expression and index 0. The parse function uses a loop that iterates through the expression characters. During each iteration:

1. If the current character is "{", we create a temporary set and generate all possible combinations of prefixes from the current set and postfixes from the inner parse call's result. We update the current set with this temporary set and update the index to the matching "}".

2. If the current character is "}", we break the loop as we reached the end of the recursion level.

3. If the current character is ",", we merge the current set into the result set and reset the current set to just contain an empty string.

4. Else, the character is a lowercase letter, so we create a new set by appending the character to each element of the current set and update the current set with this new set.

When the loop ends, we merge the current set into the result set one more time and return it. In the main function, we convert the final result set into a sorted list or array.

Notice that this algorithm respects the constraints given in the problem, and as such, it's guaranteed to work with the input expressions provided. The time complexity is O(N * M), where N is the expression length, and M is the maximum number of possible combinations that can be generated.

## A solution in C++

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

class Solution {
public:
    vector<string> braceExpansionII(string expression) {
        int i = 0;
        return vector<string>(parse(expression, i).begin(), parse(expression, i).end());
    }

    set<string> parse(string& expresion, int& i) {
        set<string> current;
        current.insert("");
        set<string> result;

        for (; i < expresion.size(); ++i) {
            char c = expresion[i];
            if (c == '{') {
                set<string> update;
                for (string postfix : parse(expresion, ++i)) {
                    for (string prefix : current) {
                        update.insert(prefix + postfix);
                    }
                }
                current = update;
            } else if (c == ',') {
                result.insert(current.begin(), current.end());
                current.clear();
                current.insert("");
            } else if (c == '}') {
                break;
            } else {
                set<string> update;
                for (string element : current) {
                    update.insert(element + c);
                }
                current = update;
            }
        }

        result.insert(current.begin(), current.end());
        return result;
    }
};
```
The core of the algorithm is a parse function that takes an expression and current index. The parse function returns a set of possible strings based on the grammar. Initially, we call parse with the input expression and index 0. The parse function uses a loop that iterates through the expression characters. During each iteration:

1. If the current character is "{", we create a temporary set and generate all possible combinations of prefixes from the current set and postfixes from the inner parse call's result. We update the current set with this temporary set and update the index to the matching "}".

2. If the current character is "}", we break the loop as we reached the end of the recursion level.

3. If the current character is ",", we merge the current set into the result set and reset the current set to just contain an empty string.

4. Else, the character is a lowercase letter, so we create a new set by appending the character to each element of the current set and update the current set with this new set.

When the loop ends, we merge the current set into the result set one more time and return it. In the main function, we convert the final result set into a sorted list or array.

Notice that this algorithm respects the constraints given in the problem, and as such, it's guaranteed to work with the input expressions provided. The time complexity is O(N * M), where N is the expression length, and M is the maximum number of possible combinations that can be generated.

## A solution in Python

```python
class Solution:
    def braceExpansionII(self, expression: str) -> List[str]:
        def parse(expr: str, i: int) -> Set[str]:
            result, current = set(), {""}
            while i < len(expr):
                if expr[i] == '{':
                    update = set()
                    for postfix in parse(expr, i + 1):
                        for prefix in current:
                            update.add(prefix + postfix)
                    current = update
                    i = expr.index('}', i)
                elif expr[i] == '}':
                    break
                elif expr[i] == ',':
                    result |= current
                    current = {""}
                else:
                    current = {s + expr[i] for s in current}
                i += 1
            return result | current

        return sorted(parse(expression, 0))
```
The core of the algorithm is a parse function that takes an expression and current index. The parse function returns a set of possible strings based on the grammar. Initially, we call parse with the input expression and index 0. The parse function uses a loop that iterates through the expression characters. During each iteration:

1. If the current character is "{", we create a temporary set and generate all possible combinations of prefixes from the current set and postfixes from the inner parse call's result. We update the current set with this temporary set and update the index to the matching "}".

2. If the current character is "}", we break the loop as we reached the end of the recursion level.

3. If the current character is ",", we merge the current set into the result set and reset the current set to just contain an empty string.

4. Else, the character is a lowercase letter, so we create a new set by appending the character to each element of the current set and update the current set with this new set.

When the loop ends, we merge the current set into the result set one more time and return it. In the main function, we convert the final result set into a sorted list or array.

Notice that this algorithm respects the constraints given in the problem, and as such, it's guaranteed to work with the input expressions provided. The time complexity is O(N * M), where N is the expression length, and M is the maximum number of possible combinations that can be generated.

## A solution in Javascript

```javascript
/**
 * @param {string} expression
 * @return {string[]}
 */
var braceExpansionII = function(expression) {
    function parse(expresion, i) {
        let current = new Set();
        current.add("");
        let result = new Set();

        while (i[0] < expresion.length) {
            let c = expresion[i[0]++];
            if (c === '{') {
                let update = new Set();
                for(let postfix of parse(expresion, i)) {
                    for(let prefix of current) {
                        update.add(prefix + postfix);
                    }
                }
                current = update;
            } else if (c === '}') {
                break;
            } else if (c === ',') {
                for(let cur of current) {
                    result.add(cur);
                }
                current.clear();
                current.add("");
            } else {
                let update = new Set();
                for(let element of current) {
                    update.add(element + c);
                }
                current = update;
            }
        }

        for(let cur of current) {
            result.add(cur);
        }
        return result;
    }

    const i = [0];
    return Array.from(parse(expression, i)).sort();
};
```
The core of the algorithm is a parse function that takes an expression and current index. The parse function returns a set of possible strings based on the grammar. Initially, we call parse with the input expression and index 0. The parse function uses a loop that iterates through the expression characters. During each iteration:

1. If the current character is "{", we create a temporary set and generate all possible combinations of prefixes from the current set and postfixes from the inner parse call's result. We update the current set with this temporary set and update the index to the matching "}".

2. If the current character is "}", we break the loop as we reached the end of the recursion level.

3. If the current character is ",", we merge the current set into the result set and reset the current set to just contain an empty string.

4. Else, the character is a lowercase letter, so we create a new set by appending the character to each element of the current set and update the current set with this new set.

When the loop ends, we merge the current set into the result set one more time and return it. In the main function, we convert the final result set into a sorted list or array.

Notice that this algorithm respects the constraints given in the problem, and as such, it's guaranteed to work with the input expressions provided. The time complexity is O(N * M), where N is the expression length, and M is the maximum number of possible combinations that can be generated.


# Two Sum Less Than K

- slug: two-sum-less-than-k
- difficulty: Easy

Given an array `nums` of integers and integer `k`, return the maximum `sum` such that there exists `i < j` with `nums[i] + nums[j] = sum` and `sum < k`. If no `i`, `j` exist satisfying this equation, return `-1`.

**Example 1:**

**Input:** nums = \[34,23,1,24,75,33,54,8\], k = 60
**Output:** 58
**Explanation:** We can use 34 and 24 to sum 58 which is less than 60.

**Example 2:**

**Input:** nums = \[10,20,30\], k = 15
**Output:** -1
**Explanation:** In this case it is not possible to get a pair sum less that 15.

**Constraints:**

*   `1 <= nums.length <= 100`
*   `1 <= nums[i] <= 1000`
*   `1 <= k <= 2000`

## A solution in Java

```java
public int maxSumUnderK(int[] nums, int k) {
    int maxSum = -1;
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            int sum = nums[i] + nums[j];
            if (sum < k && sum > maxSum) {
                maxSum = sum;
            }
        }
    }
    return maxSum;
}
```
The algorithm contains two nested loops, iterating through all possible combinations of indices `i` and `j` (with `j > i`). For each combination of `i` and `j`, the function calculates the sum of `nums[i]` and `nums[j]`. If the sum is less than `k` and greater than the current `maxSum`, the function updates `maxSum` with the new sum. Finally, the function returns the maximum sum found during the iterations. If no suitable sum was found, the function returns `-1`.

## A solution in C++

```cpp
int maxSumUnderK(vector<int>& nums, int k) {
    int maxSum = -1;
    for (int i = 0; i < nums.size(); i++) {
        for (int j = i + 1; j < nums.size(); j++) {
            int sum = nums[i] + nums[j];
            if (sum < k && sum > maxSum) {
                maxSum = sum;
            }
        }
    }
    return maxSum;
}
```
The algorithm contains two nested loops, iterating through all possible combinations of indices `i` and `j` (with `j > i`). For each combination of `i` and `j`, the function calculates the sum of `nums[i]` and `nums[j]`. If the sum is less than `k` and greater than the current `maxSum`, the function updates `maxSum` with the new sum. Finally, the function returns the maximum sum found during the iterations. If no suitable sum was found, the function returns `-1`.

## A solution in Python

```python
def max_sum_under_k(nums, k):
    max_sum = -1
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            _sum = nums[i] + nums[j]
            if _sum < k and _sum > max_sum:
                max_sum = _sum
    return max_sum
```
The algorithm contains two nested loops, iterating through all possible combinations of indices `i` and `j` (with `j > i`). For each combination of `i` and `j`, the function calculates the sum of `nums[i]` and `nums[j]`. If the sum is less than `k` and greater than the current `maxSum`, the function updates `maxSum` with the new sum. Finally, the function returns the maximum sum found during the iterations. If no suitable sum was found, the function returns `-1`.

## A solution in Javascript

```javascript
function maxSumUnderK(nums, k) {
    let maxSum = -1;
    for (let i = 0; i < nums.length; i++) {
        for (let j = i + 1; j < nums.length; j++) {
            let sum = nums[i] + nums[j];
            if (sum < k && sum > maxSum) {
                maxSum = sum;
            }
        }
    }
    return maxSum;
}
```
The algorithm contains two nested loops, iterating through all possible combinations of indices `i` and `j` (with `j > i`). For each combination of `i` and `j`, the function calculates the sum of `nums[i]` and `nums[j]`. If the sum is less than `k` and greater than the current `maxSum`, the function updates `maxSum` with the new sum. Finally, the function returns the maximum sum found during the iterations. If no suitable sum was found, the function returns `-1`.


# Find K-Length Substrings With No Repeated Characters

- slug: find-k-length-substrings-with-no-repeated-characters
- difficulty: Medium

Given a string `s` and an integer `k`, return _the number of substrings in_ `s` _of length_ `k` _with no repeated characters_.

**Example 1:**

**Input:** s =  "havefunonleetcode ", k = 5
**Output:** 6
**Explanation:** There are 6 substrings they are: 'havef','avefu','vefun','efuno','etcod','tcode'.

**Example 2:**

**Input:** s =  "home ", k = 5
**Output:** 0
**Explanation:** Notice k can be larger than the length of s. In this case, it is not possible to find any substring.

**Constraints:**

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

## A solution in Java

```java
public int numKLenSubstrNoRepeats(String s, int k) {
    int n = s.length();
    if (k > n) return 0;

    int result = 0;
    HashSet<Character> window = new HashSet<>();

    for (int i = 0, j = 0; j < n; ++j) {
        while (window.contains(s.charAt(j))) {
            window.remove(s.charAt(i++));
        }
        window.add(s.charAt(j));
        if (j - i + 1 == k) {
            ++result;
            window.remove(s.charAt(i++));
        }
    }
    return result;
}
```
The algorithm uses a sliding window approach. Initialize an empty set `window` to store unique characters in a substring. We use two pointers `i` and `j` for each end of the window. The outer loop iterates `j` through the string. If the current character `s[j]` is in `window`, remove the first element of the window by deleting `s[i++]`. Then, insert `s[j]` into the `window`.
If the current window size is equal to k (i.e., `j - i + 1 == k`), increment the count of unique substrings `result` by 1, and remove the first element of the window by deleting `s[i++]`.

Once the outer loop finishes, return the result variable, which contains the count of unique length-k substrings.

## A solution in C++

```cpp
int numKLenSubstrNoRepeats(string s, int k) {
    int n = s.length();
    if (k > n) return 0;

    int result = 0;
    unordered_set<char> window;

    for (int i = 0, j = 0; j < n; ++j) {
        while (window.find(s[j]) != window.end()) {
            window.erase(s[i++]);
        }
        window.insert(s[j]);
        if (j - i + 1 == k) {
            ++result;
            window.erase(s[i++]);
        }
    }
    return result;
}
```
The algorithm uses a sliding window approach. Initialize an empty set `window` to store unique characters in a substring. We use two pointers `i` and `j` for each end of the window. The outer loop iterates `j` through the string. If the current character `s[j]` is in `window`, remove the first element of the window by deleting `s[i++]`. Then, insert `s[j]` into the `window`.
If the current window size is equal to k (i.e., `j - i + 1 == k`), increment the count of unique substrings `result` by 1, and remove the first element of the window by deleting `s[i++]`.

Once the outer loop finishes, return the result variable, which contains the count of unique length-k substrings.

## A solution in Python

```python
def num_k_len_substr_no_repeats(s: str, k: int) -> int:
    n = len(s)
    if k > n:
        return 0

    result = 0
    window = set()

    i = 0
    for j in range(n):
        while s[j] in window:
            window.remove(s[i])
            i += 1
        window.add(s[j])
        if j - i + 1 == k:
            result += 1
            window.remove(s[i])
            i += 1

    return result
```
The algorithm uses a sliding window approach. Initialize an empty set `window` to store unique characters in a substring. We use two pointers `i` and `j` for each end of the window. The outer loop iterates `j` through the string. If the current character `s[j]` is in `window`, remove the first element of the window by deleting `s[i++]`. Then, insert `s[j]` into the `window`.
If the current window size is equal to k (i.e., `j - i + 1 == k`), increment the count of unique substrings `result` by 1, and remove the first element of the window by deleting `s[i++]`.

Once the outer loop finishes, return the result variable, which contains the count of unique length-k substrings.

## A solution in Javascript

```javascript
function numKLenSubstrNoRepeats(s, k) {
    const n = s.length;
    if (k > n) return 0;

    let result = 0;
    const window = new Set();

    for (let i = 0, j = 0; j < n; ++j) {
        while (window.has(s[j])) {
            window.delete(s[i++]);
        }
        window.add(s[j]);
        if (j - i + 1 === k) {
            ++result;
            window.delete(s[i++]);
        }
    }
    return result;
}
```
The algorithm uses a sliding window approach. Initialize an empty set `window` to store unique characters in a substring. We use two pointers `i` and `j` for each end of the window. The outer loop iterates `j` through the string. If the current character `s[j]` is in `window`, remove the first element of the window by deleting `s[i++]`. Then, insert `s[j]` into the `window`.
If the current window size is equal to k (i.e., `j - i + 1 == k`), increment the count of unique substrings `result` by 1, and remove the first element of the window by deleting `s[i++]`.

Once the outer loop finishes, return the result variable, which contains the count of unique length-k substrings.


# The Earliest Moment When Everyone Become Friends

- slug: the-earliest-moment-when-everyone-become-friends
- difficulty: Medium

There are n people in a social group labeled from `0` to `n - 1`. You are given an array `logs` where `logs[i] = [timestampi, xi, yi]` indicates that `xi` and `yi` will be friends at the time `timestampi`.

Friendship is **symmetric**. That means if `a` is friends with `b`, then `b` is friends with `a`. Also, person `a` is acquainted with a person `b` if `a` is friends with `b`, or `a` is a friend of someone acquainted with `b`.

Return _the earliest time for which every person became acquainted with every other person_. If there is no such earliest time, return `-1`.

**Example 1:**

**Input:** logs = \[\[20190101,0,1\],\[20190104,3,4\],\[20190107,2,3\],\[20190211,1,5\],\[20190224,2,4\],\[20190301,0,3\],\[20190312,1,2\],\[20190322,4,5\]\], n = 6
**Output:** 20190301
**Explanation:**
The first event occurs at timestamp = 20190101, and after 0 and 1 become friends, we have the following friendship groups \[0,1\], \[2\], \[3\], \[4\], \[5\].
The second event occurs at timestamp = 20190104, and after 3 and 4 become friends, we have the following friendship groups \[0,1\], \[2\], \[3,4\], \[5\].
The third event occurs at timestamp = 20190107, and after 2 and 3 become friends, we have the following friendship groups \[0,1\], \[2,3,4\], \[5\].
The fourth event occurs at timestamp = 20190211, and after 1 and 5 become friends, we have the following friendship groups \[0,1,5\], \[2,3,4\].
The fifth event occurs at timestamp = 20190224, and as 2 and 4 are already friends, nothing happens.
The sixth event occurs at timestamp = 20190301, and after 0 and 3 become friends, we all become friends.

**Example 2:**

**Input:** logs = \[\[0,2,0\],\[1,0,1\],\[3,0,3\],\[4,1,2\],\[7,3,1\]\], n = 4
**Output:** 3
**Explanation:** At timestamp = 3, all the persons (i.e., 0, 1, 2, and 3) become friends.

**Constraints:**

*   `2 <= n <= 100`
*   `1 <= logs.length <= 104`
*   `logs[i].length == 3`
*   `0 <= timestampi <= 109`
*   `0 <= xi, yi <= n - 1`
*   `xi != yi`
*   All the values `timestampi` are **unique**.
*   All the pairs `(xi, yi)` occur at most one time in the input.

## A solution in Java

```java
import java.util.Arrays;
import java.util.List;

public int earliestAcq(int[][] logs, int n) {
    int[] parents = new int[n];
    for (int i = 0; i < n; i++) {
        parents[i] = i;
    }

    Arrays.sort(logs, (log1, log2) -> log1[0] - log2[0]);

    int groupCount = n;
    for (int[] log : logs) {
        int rootX = find(log[1], parents);
        int rootY = find(log[2], parents);
        if (rootX != rootY) {
            parents[rootX] = rootY;
            groupCount--;
        }
        if (groupCount == 1) {
            return log[0];
        }
    }
    return -1;
}

private int find(int x, int[] parents) {
    return x == parents[x] ? x : (parents[x] = find(parents[x], parents));
}
```
All the implemented algorithms are based on the Union-Find data structure.

We initialize a parents array to keep track of the parent of each node. We sort the logs based on timestamps. We iterate through each log and for each pair of friends, x and y, we find their root using the `find` function. If the roots are not equal, we merge their roots and decrement the group count. This means they are now part of the same group, and there is one less separate group. We return the current timestamp when we reach to only one group left.

## A solution in C++

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

int parent(int x, std::vector<int>& parents) {
    return x == parents[x] ? x : parents[x] = parent(parents[x], parents);
}

int earliestAcq(std::vector<std::vector<int>>& logs, int n) {
    std::vector<int> parents(n);
    for (int i = 0; i < n; ++i) parents[i] = i;

    std::sort(logs.begin(), logs.end());

    int groupCount = n;
    for (const auto& log : logs) {
        int rootX = parent(log[1], parents);
        int rootY = parent(log[2], parents);
        if (rootX != rootY) {
            parents[rootX] = rootY;
            groupCount--;
        }
        if (groupCount == 1) {
            return log[0];
        }
    }
    return -1;
}
```
All the implemented algorithms are based on the Union-Find data structure.

We initialize a parents array to keep track of the parent of each node. We sort the logs based on timestamps. We iterate through each log and for each pair of friends, x and y, we find their root using the `find` function. If the roots are not equal, we merge their roots and decrement the group count. This means they are now part of the same group, and there is one less separate group. We return the current timestamp when we reach to only one group left.

## A solution in Python

```python
def earliestAcq(logs, n):
    def find(x):
        if x != parents[x]:
            parents[x] = find(parents[x])
        return parents[x]

    parents = list(range(n))
    logs.sort()

    group_count = n
    for timestamp, x, y in logs:
        root_x, root_y = find(x), find(y)
        if root_x != root_y:
            parents[root_x] = root_y
            group_count -= 1
        if group_count == 1:
            return timestamp
    return -1
```
All the implemented algorithms are based on the Union-Find data structure.

We initialize a parents array to keep track of the parent of each node. We sort the logs based on timestamps. We iterate through each log and for each pair of friends, x and y, we find their root using the `find` function. If the roots are not equal, we merge their roots and decrement the group count. This means they are now part of the same group, and there is one less separate group. We return the current timestamp when we reach to only one group left.

## A solution in Javascript

```javascript
function earliestAcq(logs, n) {
    const parents = new Array(n).fill(0).map((_, idx) => idx);

    logs.sort((a, b) => a[0] - b[0]);

    const find = (x) => {
        if (x !== parents[x]) {
            parents[x] = find(parents[x]);
        }
        return parents[x];
    }

    let group_count = n;
    for (const [timestamp, x, y] of logs) {
        const root_x = find(x);
        const root_y = find(y);
        if (root_x !== root_y) {
            parents[root_x] = root_y;
            group_count--;
        }
        if (group_count === 1) {
            return timestamp;
        }
    }

    return -1;
}
```
All the implemented algorithms are based on the Union-Find data structure.

We initialize a parents array to keep track of the parent of each node. We sort the logs based on timestamps. We iterate through each log and for each pair of friends, x and y, we find their root using the `find` function. If the roots are not equal, we merge their roots and decrement the group count. This means they are now part of the same group, and there is one less separate group. We return the current timestamp when we reach to only one group left.


# Path With Maximum Minimum Value

- slug: path-with-maximum-minimum-value
- difficulty: Medium

Given an `m x n` integer matrix `grid`, return _the maximum **score** of a path starting at_ `(0, 0)` _and ending at_ `(m - 1, n - 1)` moving in the 4 cardinal directions.

The **score** of a path is the minimum value in that path.

*   For example, the score of the path `8 -> 4 -> 5 -> 9` is `4`.

**Example 1:**

**Input:** grid = \[\[5,4,5\],\[1,2,6\],\[7,4,6\]\]
**Output:** 4
**Explanation:** The path with the maximum score is highlighted in yellow.

**Example 2:**

**Input:** grid = \[\[2,2,1,2,2,2\],\[1,2,2,2,1,2\]\]
**Output:** 2

**Example 3:**

**Input:** grid = \[\[3,4,6,3,4\],\[0,2,1,1,7\],\[8,8,3,2,7\],\[3,2,4,9,8\],\[4,1,2,0,0\],\[4,6,5,4,3\]\]
**Output:** 3

**Constraints:**

*   `m == grid.length`
*   `n == grid[i].length`
*   `1 <= m, n <= 100`
*   `0 <= grid[i][j] <= 109`

## A solution in Java

```java
public int maxScore(int[][] grid) {
    int m = grid.length, n = grid[0].length;

    for (int i = 1; i < n; ++i) {
        grid[0][i] = Math.min(grid[0][i], grid[0][i - 1]);
    }

    for (int i = 1; i < m; ++i) {
        grid[i][0] = Math.min(grid[i][0], grid[i - 1][0]);

        for (int j = 1; j < n; ++j) {
            grid[i][j] = Math.max(Math.min(grid[i - 1][j], grid[i][j]),
                                  Math.min(grid[i][j - 1], grid[i][j]));
        }
    }

    return grid[m - 1][n - 1];
}
```
The basic idea is to maintain the maximum score at each cell in the grid. In this case, we start with the first row, and then for every next cell, we store the minimum of that cell and its previous cell in it.

Then, starting from the second row, we perform the same operation for the first column, storing the minimum across rows.

At this point, for each interior cell in the grid, we have two options: either move from the top cell, or move from the left cell. We apply the same minimum operation between the current cell, and the top cell, and the left cell. We choose the maximum between these two results.

Finally, we return the value at the last cell of the grid, which holds the maximum score.

## A solution in C++

```cpp
int maxScore(vector<vector<int>>& grid) {
    int m = grid.size(), n = grid[0].size();

    for (int i = 1; i < n; i++) {
        grid[0][i] = min(grid[0][i], grid[0][i - 1]);
    }

    for (int i = 1; i < m; i++) {
        grid[i][0] = min(grid[i][0], grid[i - 1][0]);

        for (int j = 1; j < n; j++) {
            grid[i][j] = max(min(grid[i - 1][j], grid[i][j]), min(grid[i][j - 1], grid[i][j]));
        }
    }

    return grid[m - 1][n - 1];
}
```
The basic idea is to maintain the maximum score at each cell in the grid. In this case, we start with the first row, and then for every next cell, we store the minimum of that cell and its previous cell in it.

Then, starting from the second row, we perform the same operation for the first column, storing the minimum across rows.

At this point, for each interior cell in the grid, we have two options: either move from the top cell, or move from the left cell. We apply the same minimum operation between the current cell, and the top cell, and the left cell. We choose the maximum between these two results.

Finally, we return the value at the last cell of the grid, which holds the maximum score.

## A solution in Python

```python
def maxScore(grid):
    m, n = len(grid), len(grid[0])

    for i in range(1, n):
        grid[0][i] = min(grid[0][i], grid[0][i - 1])

    for i in range(1, m):
        grid[i][0] = min(grid[i][0], grid[i - 1][0])

        for j in range(1, n):
            grid[i][j] = max(min(grid[i - 1][j], grid[i][j]), min(grid[i][j - 1], grid[i][j]))

    return grid[m - 1][n - 1]
```
The basic idea is to maintain the maximum score at each cell in the grid. In this case, we start with the first row, and then for every next cell, we store the minimum of that cell and its previous cell in it.

Then, starting from the second row, we perform the same operation for the first column, storing the minimum across rows.

At this point, for each interior cell in the grid, we have two options: either move from the top cell, or move from the left cell. We apply the same minimum operation between the current cell, and the top cell, and the left cell. We choose the maximum between these two results.

Finally, we return the value at the last cell of the grid, which holds the maximum score.

## A solution in Javascript

```javascript
function maxScore(grid) {
    const m = grid.length, n = grid[0].length;

    for (let i = 1; i < n; ++i) {
        grid[0][i] = Math.min(grid[0][i], grid[0][i - 1]);
    }

    for (let i = 1; i < m; ++i) {
        grid[i][0] = Math.min(grid[i][0], grid[i - 1][0]);

        for (let j = 1; j < n; ++j) {
            grid[i][j] = Math.max(Math.min(grid[i - 1][j], grid[i][j]),
                                  Math.min(grid[i][j - 1], grid[i][j]));
        }
    }

    return grid[m - 1][n - 1];
}
```
The basic idea is to maintain the maximum score at each cell in the grid. In this case, we start with the first row, and then for every next cell, we store the minimum of that cell and its previous cell in it.

Then, starting from the second row, we perform the same operation for the first column, storing the minimum across rows.

At this point, for each interior cell in the grid, we have two options: either move from the top cell, or move from the left cell. We apply the same minimum operation between the current cell, and the top cell, and the left cell. We choose the maximum between these two results.

Finally, we return the value at the last cell of the grid, which holds the maximum score.