# All Elements in Two Binary Search Trees

- slug: all-elements-in-two-binary-search-trees
- difficulty: Medium

Given two binary search trees `root1` and `root2`, return _a list containing all the integers from both trees sorted in **ascending** order_.

**Example 1:**

**Input:** root1 = \[2,1,4\], root2 = \[1,0,3\]
**Output:** \[0,1,1,2,3,4\]

**Example 2:**

**Input:** root1 = \[1,null,8\], root2 = \[8,1\]
**Output:** \[1,1,8,8\]

**Constraints:**

*   The number of nodes in each tree is in the range `[0, 5000]`.
*   `-105 <= Node.val <= 105`

## A solution in Java

```java
import java.util.Stack;

public int[] peopleCanSee(int[] heights) {
    int n = heights.length;
    int[] ans = new int[n];
    Stack<Integer> st = new Stack<>();

    for (int i = n - 1; i >= 0; --i) {
        while (!st.isEmpty() && heights[st.peek()] < heights[i]) {
            int idx = st.pop();
            ans[i]++;
            ans[i] += ans[idx];
        }
        st.push(i);
    }

    return ans;
}
```
The algorithm uses a stack to keep track of people whose visible right neighbors are not yet determined.

We iterate through the people from right to left, comparing the height of the current person with the height of the person on top of the stack. If the person on top of the stack is shorter than the current person, we pop that person from the stack since their neighbor has been found, incrementing the visible count for the current person (ans[i]) and adding the previous count of the top person from the stack.

We then push the current person onto the stack to check for their visible neighbors on their right. The time complexity is O(n) as each person is pushed and popped only once.

## A solution in C++

```cpp
#include <vector>
#include <stack>

std::vector<int> peopleCanSee(std::vector<int>& heights) {
    int n = heights.size();
    std::vector<int> ans(n, 0);
    std::stack<int> st;

    for (int i = n - 1; i >= 0; --i) {
        while (!st.empty() && heights[st.top()] < heights[i]) {
            int idx = st.top();
            st.pop();
            ans[i]++;
            ans[i] += ans[idx];
        }
        st.push(i);
    }

    return ans;
}
```
The algorithm uses a stack to keep track of people whose visible right neighbors are not yet determined.

We iterate through the people from right to left, comparing the height of the current person with the height of the person on top of the stack. If the person on top of the stack is shorter than the current person, we pop that person from the stack since their neighbor has been found, incrementing the visible count for the current person (ans[i]) and adding the previous count of the top person from the stack.

We then push the current person onto the stack to check for their visible neighbors on their right. The time complexity is O(n) as each person is pushed and popped only once.

## A solution in Python

```python
def people_can_see(heights):
    n = len(heights)
    ans = [0] * n
    st = []

    for i in range(n - 1, -1, -1):
        while st and heights[st[-1]] < heights[i]:
            idx = st.pop()
            ans[i] += 1
            ans[i] += ans[idx]
        st.append(i)

    return ans
```
The algorithm uses a stack to keep track of people whose visible right neighbors are not yet determined.

We iterate through the people from right to left, comparing the height of the current person with the height of the person on top of the stack. If the person on top of the stack is shorter than the current person, we pop that person from the stack since their neighbor has been found, incrementing the visible count for the current person (ans[i]) and adding the previous count of the top person from the stack.

We then push the current person onto the stack to check for their visible neighbors on their right. The time complexity is O(n) as each person is pushed and popped only once.

## A solution in Javascript

```javascript
function peopleCanSee(heights) {
    const n = heights.length;
    const ans = new Array(n).fill(0);
    const st = [];

    for (let i = n - 1; i >= 0; --i) {
        while (st.length > 0 && heights[st[st.length - 1]] < heights[i]) {
            const idx = st.pop();
            ans[i]++;
            ans[i] += ans[idx];
        }
        st.push(i);
    }

    return ans;
}
```
The algorithm uses a stack to keep track of people whose visible right neighbors are not yet determined.

We iterate through the people from right to left, comparing the height of the current person with the height of the person on top of the stack. If the person on top of the stack is shorter than the current person, we pop that person from the stack since their neighbor has been found, incrementing the visible count for the current person (ans[i]) and adding the previous count of the top person from the stack.

We then push the current person onto the stack to check for their visible neighbors on their right. The time complexity is O(n) as each person is pushed and popped only once.


# Jump Game III

- slug: jump-game-iii
- difficulty: Medium

Given an array of non-negative integers `arr`, you are initially positioned at `start` index of the array. When you are at index `i`, you can jump to `i + arr[i]` or `i - arr[i]`, check if you can reach to **any** index with value 0.

Notice that you can not jump outside of the array at any time.

**Example 1:**

**Input:** arr = \[4,2,3,0,3,1,2\], start = 5
**Output:** true
**Explanation:**
All possible ways to reach at index 3 with value 0 are:
index 5 -> index 4 -> index 1 -> index 3
index 5 -> index 6 -> index 4 -> index 1 -> index 3

**Example 2:**

**Input:** arr = \[4,2,3,0,3,1,2\], start = 0
**Output:** true
**Explanation:**
One possible way to reach at index 3 with value 0 is:
index 0 -> index 4 -> index 1 -> index 3

**Example 3:**

**Input:** arr = \[3,0,2,1,2\], start = 2
**Output:** false
**Explanation:** There is no way to reach at index 1 with value 0.

**Constraints:**

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

a, b are from arr a < b b - a equals to the minimum absolute difference of any two elements in arr

## A solution in Java

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

public List<List<Integer>> minimumAbsDifference(int[] arr) {
    Arrays.sort(arr);
    int min_difference = Integer.MAX_VALUE;
    List<List<Integer>> result = new ArrayList<>();

    for (int i = 1; i < arr.length; ++i) {
        int difference = arr[i] - arr[i - 1];
        if (difference < min_difference) {
            min_difference = difference;
            result.clear();
            result.add(Arrays.asList(arr[i - 1], arr[i]));
        } else if (difference == min_difference) {
            result.add(Arrays.asList(arr[i - 1], arr[i]));
        }
    }

    return result;
}
```
1. Sort the array in ascending order.
2. Initialize the minimum absolute difference variable `min_difference` and an empty result list.
3. Iterate through the sorted array from the second element to the last element, calculate the difference between the current element and the previous element.
4. If the difference is less than the current `min_difference`, update the `min_difference` variable and reset the result list with this new pair of elements.
5. If the difference is equal to the current `min_difference`, append this pair of elements to the result list.
6. Return the result list after processing all elements in the sorted array.

## A solution in C++

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

vector<vector<int>> minimumAbsDifference(vector<int>& arr) {
    sort(arr.begin(), arr.end());
    int min_difference = INT_MAX;
    vector<vector<int>> result;

    for (int i = 1; i < arr.size(); ++i) {
        int difference = arr[i] - arr[i - 1];
        if (difference < min_difference) {
            min_difference = difference;
            result.clear();
            result.push_back({arr[i - 1], arr[i]});
        } else if (difference == min_difference) {
            result.push_back({arr[i - 1], arr[i]});
        }
    }

    return result;
}
```
1. Sort the array in ascending order.
2. Initialize the minimum absolute difference variable `min_difference` and an empty result list.
3. Iterate through the sorted array from the second element to the last element, calculate the difference between the current element and the previous element.
4. If the difference is less than the current `min_difference`, update the `min_difference` variable and reset the result list with this new pair of elements.
5. If the difference is equal to the current `min_difference`, append this pair of elements to the result list.
6. Return the result list after processing all elements in the sorted array.

## A solution in Python

```python
def minimumAbsDifference(arr):
    arr.sort()
    min_difference = float('inf')
    result = []

    for i in range(1, len(arr)):
        difference = arr[i] - arr[i - 1]
        if difference < min_difference:
            min_difference = difference
            result = [[arr[i - 1], arr[i]]]
        elif difference == min_difference:
            result.append([arr[i - 1], arr[i]])

    return result
```
1. Sort the array in ascending order.
2. Initialize the minimum absolute difference variable `min_difference` and an empty result list.
3. Iterate through the sorted array from the second element to the last element, calculate the difference between the current element and the previous element.
4. If the difference is less than the current `min_difference`, update the `min_difference` variable and reset the result list with this new pair of elements.
5. If the difference is equal to the current `min_difference`, append this pair of elements to the result list.
6. Return the result list after processing all elements in the sorted array.

## A solution in Javascript

```javascript
function minimumAbsDifference(arr) {
    arr.sort((a, b) => a - b);
    let min_difference = Infinity;
    let result = [];

    for (let i = 1; i < arr.length; ++i) {
        let difference = arr[i] - arr[i - 1];
        if (difference < min_difference) {
            min_difference = difference;
            result = [[arr[i - 1], arr[i]]];
        } else if (difference === min_difference) {
            result.push([arr[i - 1], arr[i]]);
        }
    }

    return result;
}
```
1. Sort the array in ascending order.
2. Initialize the minimum absolute difference variable `min_difference` and an empty result list.
3. Iterate through the sorted array from the second element to the last element, calculate the difference between the current element and the previous element.
4. If the difference is less than the current `min_difference`, update the `min_difference` variable and reset the result list with this new pair of elements.
5. If the difference is equal to the current `min_difference`, append this pair of elements to the result list.
6. Return the result list after processing all elements in the sorted array.


# Verbal Arithmetic Puzzle

- slug: verbal-arithmetic-puzzle
- difficulty: Hard

Given an equation, represented by `words` on the left side and the `result` on the right side.

You need to check if the equation is solvable under the following rules:

*   Each character is decoded as one digit (0 - 9).
*   No two characters can map to the same digit.
*   Each `words[i]` and `result` are decoded as one number **without** leading zeros.
*   Sum of numbers on the left side (`words`) will equal to the number on the right side (`result`).

Return `true` _if the equation is solvable, otherwise return_ `false`.

**Example 1:**

**Input:** words = \[ "SEND ", "MORE "\], result =  "MONEY "
**Output:** true
**Explanation:** Map 'S'-> 9, 'E'->5, 'N'->6, 'D'->7, 'M'->1, 'O'->0, 'R'->8, 'Y'->'2'
Such that:  "SEND " +  "MORE " =  "MONEY " ,  9567 + 1085 = 10652

**Example 2:**

**Input:** words = \[ "SIX ", "SEVEN ", "SEVEN "\], result =  "TWENTY "
**Output:** true
**Explanation:** Map 'S'-> 6, 'I'->5, 'X'->0, 'E'->8, 'V'->7, 'N'->2, 'T'->1, 'W'->'3', 'Y'->4
Such that:  "SIX " +  "SEVEN " +  "SEVEN " =  "TWENTY " ,  650 + 68782 + 68782 = 138214

**Example 3:**

**Input:** words = \[ "LEET ", "CODE "\], result =  "POINT "
**Output:** false
**Explanation:** There is no possible mapping to satisfy the equation, so we return false.
Note that two different characters cannot map to the same digit.

**Constraints:**

*   `2 <= words.length <= 5`
*   `1 <= words[i].length, result.length <= 7`
*   `words[i], result` contain only uppercase English letters.
*   The number of different characters used in the expression is at most `10`.

## A solution in Java

```java
public int nthUglyNumber(int n, int a, int b, int c) {
    long ab = a * b / gcd(a, b);
    long ac = a * c / gcd(a, c);
    long bc = b * c / gcd(b, c);
    long abc = a * (b * c / gcd(b, c)) / gcd(a, (b * c / gcd(b, c)));

    long left = 0, right = 2000000000;
    while (left < right) {
        long mid = left + (right - left) / 2;
        long cnt = mid / a + mid / b + mid / c - mid / ab - mid / ac - mid / bc + mid / abc;
        if (cnt < n) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return (int)left;
}

private long gcd(long a, long b) {
    return b == 0 ? a : gcd(b, a % b);
}
```
We can solve this problem using binary search. First, we find the least common multiple of each pair of numbers (a, b), (a, c), and (b, c) as well as the least common multiple of all three numbers (a, b, c). Then, we use binary search to find the ugly number. In each iteration, we check the count of numbers divisible by a, b, or c in the range [0, mid] and compare it with our target index n. If the count is less than n, we search in the larger half of the search space, otherwise, we search in the smaller half. When our search range becomes [0,1] or left becomes equal to right, we have found the nth ugly number.

## A solution in C++

```cpp
#include <algorithm>

int nthUglyNumber(int n, int a1, int a2, int a3) {
    long long a = a1, b = a2, c = a3;
    long long ab = a * b / std::__gcd(a, b);
    long long ac = a * c / std::__gcd(a, c);
    long long bc = b * c / std::__gcd(b, c);
    long long abc = a * bc / std::__gcd(a, bc);

    long long left = 0, right = 2e9;
    while (left < right) {
        long long mid = left + (right - left) / 2;
        long long cnt = mid / a + mid / b + mid / c - mid / ab - mid / ac - mid / bc + mid / abc;
        if (cnt < n) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return left;
}
```
We can solve this problem using binary search. First, we find the least common multiple of each pair of numbers (a, b), (a, c), and (b, c) as well as the least common multiple of all three numbers (a, b, c). Then, we use binary search to find the ugly number. In each iteration, we check the count of numbers divisible by a, b, or c in the range [0, mid] and compare it with our target index n. If the count is less than n, we search in the larger half of the search space, otherwise, we search in the smaller half. When our search range becomes [0,1] or left becomes equal to right, we have found the nth ugly number.

## A solution in Python

```python
def nthUglyNumber(n, a, b, c):
    from math import gcd

    ab = a * b // gcd(a, b)
    ac = a * c // gcd(a, c)
    bc = b * c // gcd(b, c)
    abc = a * bc // gcd(a, bc)

    left, right = 0, 2 * 10**9
    while left < right:
        mid = left + (right - left) // 2
        cnt = mid // a + mid // b + mid // c - mid // ab - mid // ac - mid // bc + mid // abc
        if cnt < n:
            left = mid + 1
        else:
            right = mid

    return left
```
We can solve this problem using binary search. First, we find the least common multiple of each pair of numbers (a, b), (a, c), and (b, c) as well as the least common multiple of all three numbers (a, b, c). Then, we use binary search to find the ugly number. In each iteration, we check the count of numbers divisible by a, b, or c in the range [0, mid] and compare it with our target index n. If the count is less than n, we search in the larger half of the search space, otherwise, we search in the smaller half. When our search range becomes [0,1] or left becomes equal to right, we have found the nth ugly number.

## A solution in Javascript

```javascript
function nthUglyNumber(n, a, b, c) {
    const gcd = (x, y) => y === 0 ? x : gcd(y, x % y);

    let ab = a * b / gcd(a, b);
    let ac = a * c / gcd(a, c);
    let bc = b * c / gcd(b, c);
    let abc = a * (b * c / gcd(b, c)) / gcd(a, (b * c / gcd(b, c)));

    let left = 0, right = 2e9;
    while (left < right) {
        let mid = left + Math.floor((right - left) / 2);
        let cnt = Math.floor(mid / a) + Math.floor(mid / b) + Math.floor(mid / c) - Math.floor(mid / ab) -
                  Math.floor(mid / ac) - Math.floor(mid / bc) + Math.floor(mid / abc);
        if (cnt < n) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return left;
}
```
We can solve this problem using binary search. First, we find the least common multiple of each pair of numbers (a, b), (a, c), and (b, c) as well as the least common multiple of all three numbers (a, b, c). Then, we use binary search to find the ugly number. In each iteration, we check the count of numbers divisible by a, b, or c in the range [0, mid] and compare it with our target index n. If the count is less than n, we search in the larger half of the search space, otherwise, we search in the smaller half. When our search range becomes [0,1] or left becomes equal to right, we have found the nth ugly number.


# Decrypt String from Alphabet to Integer Mapping

- slug: decrypt-string-from-alphabet-to-integer-mapping
- difficulty: Easy

You are given a string `s` formed by digits and `'#'`. We want to map `s` to English lowercase characters as follows:

*   Characters (`'a'` to `'i'`) are represented by (`'1'` to `'9'`) respectively.
*   Characters (`'j'` to `'z'`) are represented by (`'10#'` to `'26#'`) respectively.

Return _the string formed after mapping_.

The test cases are generated so that a unique mapping will always exist.

**Example 1:**

**Input:** s =  "10#11#12 "
**Output:**  "jkab "
**Explanation:**  "j " ->  "10# " ,  "k " ->  "11# " ,  "a " ->  "1 " ,  "b " ->  "2 ".

**Example 2:**

**Input:** s =  "1326# "
**Output:**  "acz "

**Constraints:**

*   `1 <= s.length <= 1000`
*   `s` consists of digits and the `'#'` letter.
*   `s` will be a valid string such that mapping is always possible.

## A solution in Java

```java
import java.util.*;

public List<Integer> sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
    // Calculate outdegrees and dependencies for groups and items
    int[] groupOutdegree = new int[m];
    List<List<Integer>> groupEdges = new ArrayList<>(m);
    for (int i = 0; i < m; i++) {
        groupEdges.add(new ArrayList<>());
    }

    int[] itemOutdegree = new int[n];
    List<List<Integer>> itemEdges = new ArrayList<>(n);
    for (int i = 0; i < n; i++) {
        itemEdges.add(new ArrayList<>());
    }

    for (int i = 0; i < group.length; i++) {
        for (int dep : beforeItems.get(i)) {
            int a = group[i], b = group[dep];
            if (a != -1 && a != b && !(groupEdges.get(b).size() > 0 && groupEdges.get(b).get(groupEdges.get(b).size() - 1) == a)) {
                groupEdges.get(b).add(a);
                groupOutdegree[a]++;
            }
            if (a != b) {
                itemEdges.get(dep).add(i);
                itemOutdegree[i]++;
            }
        }
    }

    // Topological sort
    List<Integer> groupOrder = topologicalSort(groupOutdegree, groupEdges);
    if (groupOrder.size() < m) {
        return new ArrayList<>();
    }

    List<Integer> itemOrder = topologicalSort(itemOutdegree, itemEdges);
    if (itemOrder.size() < n) {
        return new ArrayList<>();
    }

    // Combine orders
    List<Integer> res = new ArrayList<>();
    for (int gi : groupOrder) {
        for (int idx : itemOrder) {
            if (group[idx] == gi) {
                res.add(idx);
            }
        }
    }

    return res;
}

private List<Integer>	topologicalSort(int[] outdegree, List<List<Integer>> edges) {
    List<Integer> res = new ArrayList<>();
    Deque<Integer> queue = new LinkedList<>();
    for (int i = 0; i < outdegree.length; i++) {
        if (outdegree[i] == 0) {
            queue.offerLast(i);
        }
    }

    while (!queue.isEmpty()) {
        int u = queue.pollLast();
        res.add(u);

        for (int v : edges.get(u)) {
            if (--outdegree[v] == 0) {
                queue.offerLast(v);
            }
        }
    }

    return res;
}
```
The algorithm consists of the following steps:
1. Calculate the outdegrees and edges for both the groups and the items based on their dependencies.
2. Perform a topological sort on group dependencies and item dependencies separately. If the topological order of groups or items is not complete, return an empty list because we cannot find a valid solution.
3. Combine the orders based on grouping. For each group in the order of groups, find the items belonging to that group from itemOrder and add it to the final result.
4. Return the combined order as the final result.

## A solution in C++

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

std::vector<int> sortItems(int n, int m, std::vector<int>& group, std::vector<std::vector<int>>& beforeItems) {
    // Calculate outdegrees and dependencies for groups and items
    std::vector<int> groupOutdegree(m, 0);
    std::vector<std::vector<int>> groupEdges(m);
    std::vector<int> itemOutdegree(n, 0);
    std::vector<std::vector<int>> itemEdges(n);

    for (int i = 0; i < group.size(); ++i) {
        for (const int dep : beforeItems[i]) {
            int a = group[i], b = group[dep];
            if (a != -1 && a != b && !groupEdges[b].empty() && groupEdges[b].back() == a) {
                groupEdges[b].push_back(a);
                ++groupOutdegree[a];
            }
            if (a != b) {
                itemEdges[dep].push_back(i);
                ++itemOutdegree[i];
            }
        }
    }

    // Topological sort
    auto topologicalSort = [](const std::vector<int>& outdegree, const std::vector<std::vector<int>>& edges) {
        std::vector<int> res, q;
        for (int i = 0; i < outdegree.size(); ++i)
            if (outdegree[i] == 0)
                q.push_back(i);

        while (!q.empty()) {
            int u = q.back();
            q.pop_back();
            res.push_back(u);

            for (const int v : edges[u])
                if (--const_cast<int&>(outdegree[v]) == 0)
                    q.push_back(v);
        }
        return res;
    };

    std::vector<int> groupOrder = topologicalSort(groupOutdegree, groupEdges);
    if (groupOrder.size() < m)
        return {};

    std::vector<int> itemOrder = topologicalSort(itemOutdegree, itemEdges);
    if (itemOrder.size() < n)
        return {};

    // Combine orders
    std::vector<int> res;
    for (const int gi : groupOrder)
        for (const int idx : itemOrder)
            if (group[idx] == gi)
                res.push_back(idx);

    return res;
}
```
The algorithm consists of the following steps:
1. Calculate the outdegrees and edges for both the groups and the items based on their dependencies.
2. Perform a topological sort on group dependencies and item dependencies separately. If the topological order of groups or items is not complete, return an empty list because we cannot find a valid solution.
3. Combine the orders based on grouping. For each group in the order of groups, find the items belonging to that group from itemOrder and add it to the final result.
4. Return the combined order as the final result.

## A solution in Python

```python
from collections import defaultdict, deque

def sortItems(n, m, group, beforeItems):
    def topological_sort(outdegree, edges):
        res = []
        q = deque([i for i in range(len(outdegree)) if outdegree[i] == 0])
        while q:
            u = q.pop()
            res.append(u)
            for v in edges[u]:
                outdegree[v] -= 1
                if outdegree[v] == 0:
                    q.append(v)
        return res

    # Calculate outdegrees and dependencies for groups and items
    group_outdegree = [0] * m
    group_edges = defaultdict(list)

    item_outdegree = [0] * n
    item_edges = defaultdict(list)

    for i in range(n):
        for dep in beforeItems[i]:
            a, b = group[i], group[dep]
            if a != -1 and a != b and not (group_edges[b] and group_edges[b][-1] == a):
                group_edges[b].append(a)
                group_outdegree[a] += 1
            if a != b:
                item_edges[dep].append(i)
                item_outdegree[i] += 1

    group_order = topological_sort(group_outdegree, group_edges)
    if len(group_order) < m:
        return []

    item_order = topological_sort(item_outdegree, item_edges)
    if len(item_order) < n:
        return []

    # Combine orders
    res = [0] * n
    idx = 0
    for gi in group_order:
        for item_idx in item_order:
            if group[item_idx] == gi:
                res[idx] = item_idx
                idx += 1

    return res
```
The algorithm consists of the following steps:
1. Calculate the outdegrees and edges for both the groups and the items based on their dependencies.
2. Perform a topological sort on group dependencies and item dependencies separately. If the topological order of groups or items is not complete, return an empty list because we cannot find a valid solution.
3. Combine the orders based on grouping. For each group in the order of groups, find the items belonging to that group from itemOrder and add it to the final result.
4. Return the combined order as the final result.

## A solution in Javascript

```javascript
function sortItems(n, m, group, beforeItems) {
  function topologicalSort(outdegree, edges) {
    const res = [];
    const q = [];
    for (let i = 0; i < outdegree.length; i++) {
      if (outdegree[i] === 0) q.push(i);
    }
    while (q.length) {
      const u = q.pop();
      res.push(u);
      for (const v of edges.get(u)) {
        outdegree[v]--;
        if (outdegree[v] === 0) {
          q.push(v);
        }
      }
    }
    return res;
  }

  // Calculate outdegrees and dependencies for groups and items
  const groupOutdegree = new Array(m).fill(0);
  const groupEdges = new Map(Array.from({length: m}, () => []));

  const itemOutdegree = new Array(n).fill(0);
  const itemEdges = new Map(Array.from({length: n}, () => []));

  for (let i = 0; i < group.length; i++) {
    for (const dep of beforeItems[i]) {
      const a = group[i], b = group[dep];
      if (a !== -1 && a !== b && !(groupEdges.get(b).length > 0 && groupEdges.get(b)[groupEdges.get(b).length - 1] === a)) {
        groupEdges.get(b).push(a);
        groupOutdegree[a]++;
      }
      if (a !== b) {
        itemEdges.get(dep).push(i);
        itemOutdegree[i]++;
      }
    }
  }

  const groupOrder = topologicalSort(groupOutdegree, groupEdges);
  if (groupOrder.length < m) {
    return [];
  }

  const itemOrder = topologicalSort(itemOutdegree, itemEdges);
  if (itemOrder.length < n) {
    return [];
  }

  // Combine orders
  const res = [];
  for (const gi of groupOrder) {
    for (const idx of itemOrder) {
      if (group[idx] === gi) {
        res.push(idx);
      }
    }
  }

  return res;
}
```
The algorithm consists of the following steps:
1. Calculate the outdegrees and edges for both the groups and the items based on their dependencies.
2. Perform a topological sort on group dependencies and item dependencies separately. If the topological order of groups or items is not complete, return an empty list because we cannot find a valid solution.
3. Combine the orders based on grouping. For each group in the order of groups, find the items belonging to that group from itemOrder and add it to the final result.
4. Return the combined order as the final result.


# XOR Queries of a Subarray

- slug: xor-queries-of-a-subarray
- difficulty: Medium

You are given an array `arr` of positive integers. You are also given the array `queries` where `queries[i] = [lefti, righti]`.

For each query `i` compute the **XOR** of elements from `lefti` to `righti` (that is, `arr[lefti] XOR arr[lefti + 1] XOR ... XOR arr[righti]` ).

Return an array `answer` where `answer[i]` is the answer to the `ith` query.

**Example 1:**

**Input:** arr = \[1,3,4,8\], queries = \[\[0,1\],\[1,2\],\[0,3\],\[3,3\]\]
**Output:** \[2,7,14,8\]
**Explanation:**
The binary representation of the elements in the array are:
1 = 0001
3 = 0011
4 = 0100
8 = 1000
The XOR values for queries are:
\[0,1\] = 1 xor 3 = 2
\[1,2\] = 3 xor 4 = 7
\[0,3\] = 1 xor 3 xor 4 xor 8 = 14
\[3,3\] = 8

**Example 2:**

**Input:** arr = \[4,8,2,10\], queries = \[\[2,3\],\[1,3\],\[0,0\],\[0,3\]\]
**Output:** \[8,0,4,4\]

**Constraints:**

*   `1 <= arr.length, queries.length <= 3 * 104`
*   `1 <= arr[i] <= 109`
*   `queries[i].length == 2`
*   `0 <= lefti <= righti < arr.length`

## A solution in Java

```java
public int waterPlants(int[] plants, int capacity) {
    int steps = 0;
    int waterLeft = 0;

    for (int i = 0; i < plants.length; ++i) {
        if (waterLeft < plants[i]) {
            steps += 2 * i + 1; // Refill the watering can
            waterLeft = capacity;
        }
        waterLeft -= plants[i];
        steps++; // Move to the next plant
    }

    return steps;
}
```
The algorithm starts by initializing two variables: steps to keep track of the steps needed to water all the plants, and water_left to keep track of how much water is left in the watering can. Then, we loop through each plant in the array. At each step, we check if the amount of water left in the can is less than the water needed by the current plant. If it is, we refill the watering can by adding 2 * i + 1 to steps (i being the index of the current plant). This addition is performed because we must go to the river, located at x = -1, and then go back to the current plant at x = i. Once the can is refilled, we update the water_left to capacity.

Next, we decrease the water_left by the amount needed by the current plant, and increment steps by 1 to move to the next plant. This process is repeated for every plant in the array. Finally, the algorithm returns the total number of steps.

## A solution in C++

```cpp
int waterPlants(vector<int> &plants, int capacity) {
    int steps = 0;
    int water_left = 0;
    for (int i = 0; i < plants.size(); ++i) {
        if (water_left < plants[i]) {
            steps += 2 * i + 1; // Refill the watering can
            water_left = capacity;
        }
        water_left -= plants[i];
        steps++; // Move to the next plant
    }
    return steps;
}
```
The algorithm starts by initializing two variables: steps to keep track of the steps needed to water all the plants, and water_left to keep track of how much water is left in the watering can. Then, we loop through each plant in the array. At each step, we check if the amount of water left in the can is less than the water needed by the current plant. If it is, we refill the watering can by adding 2 * i + 1 to steps (i being the index of the current plant). This addition is performed because we must go to the river, located at x = -1, and then go back to the current plant at x = i. Once the can is refilled, we update the water_left to capacity.

Next, we decrease the water_left by the amount needed by the current plant, and increment steps by 1 to move to the next plant. This process is repeated for every plant in the array. Finally, the algorithm returns the total number of steps.

## A solution in Python

```python
def water_plants(plants, capacity):
    steps = 0
    water_left = 0

    for i, plant in enumerate(plants):
        if water_left < plant:
            steps += 2 * i + 1  # Refill the watering can
            water_left = capacity
        water_left -= plant
        steps += 1  # Move to the next plant

    return steps
```
The algorithm starts by initializing two variables: steps to keep track of the steps needed to water all the plants, and water_left to keep track of how much water is left in the watering can. Then, we loop through each plant in the array. At each step, we check if the amount of water left in the can is less than the water needed by the current plant. If it is, we refill the watering can by adding 2 * i + 1 to steps (i being the index of the current plant). This addition is performed because we must go to the river, located at x = -1, and then go back to the current plant at x = i. Once the can is refilled, we update the water_left to capacity.

Next, we decrease the water_left by the amount needed by the current plant, and increment steps by 1 to move to the next plant. This process is repeated for every plant in the array. Finally, the algorithm returns the total number of steps.

## A solution in Javascript

```javascript
function waterPlants(plants, capacity) {
    let steps = 0;
    let waterLeft = 0;

    for (let i = 0; i < plants.length; ++i) {
        if (waterLeft < plants[i]) {
            steps += 2 * i + 1; // Refill the watering can
            waterLeft = capacity;
        }
        waterLeft -= plants[i];
        steps++; // Move to the next plant
    }

    return steps;
}
```
The algorithm starts by initializing two variables: steps to keep track of the steps needed to water all the plants, and water_left to keep track of how much water is left in the watering can. Then, we loop through each plant in the array. At each step, we check if the amount of water left in the can is less than the water needed by the current plant. If it is, we refill the watering can by adding 2 * i + 1 to steps (i being the index of the current plant). This addition is performed because we must go to the river, located at x = -1, and then go back to the current plant at x = i. Once the can is refilled, we update the water_left to capacity.

Next, we decrease the water_left by the amount needed by the current plant, and increment steps by 1 to move to the next plant. This process is repeated for every plant in the array. Finally, the algorithm returns the total number of steps.


# Get Watched Videos by Your Friends

- slug: get-watched-videos-by-your-friends
- difficulty: Medium

There are `n` people, each person has a unique _id_ between `0` and `n-1`. Given the arrays `watchedVideos` and `friends`, where `watchedVideos[i]` and `friends[i]` contain the list of watched videos and the list of friends respectively for the person with `id = i`.

Level **1** of videos are all watched videos by your friends, level **2** of videos are all watched videos by the friends of your friends and so on. In general, the level `k` of videos are all watched videos by people with the shortest path **exactly** equal to `k` with you. Given your `id` and the `level` of videos, return the list of videos ordered by their frequencies (increasing). For videos with the same frequency order them alphabetically from least to greatest.

**Example 1:**

**Input:** watchedVideos = \[\[ "A ", "B "\],\[ "C "\],\[ "B ", "C "\],\[ "D "\]\], friends = \[\[1,2\],\[0,3\],\[0,3\],\[1,2\]\], id = 0, level = 1
**Output:** \[ "B ", "C "\]
**Explanation:**
You have id = 0 (green color in the figure) and your friends are (yellow color in the figure):
Person with id = 1 -> watchedVideos = \[ "C "\]
Person with id = 2 -> watchedVideos = \[ "B ", "C "\]
The frequencies of watchedVideos by your friends are:
B -> 1
C -> 2

**Example 2:**

**Input:** watchedVideos = \[\[ "A ", "B "\],\[ "C "\],\[ "B ", "C "\],\[ "D "\]\], friends = \[\[1,2\],\[0,3\],\[0,3\],\[1,2\]\], id = 0, level = 2
**Output:** \[ "D "\]
**Explanation:**
You have id = 0 (green color in the figure) and the only friend of your friends is the person with id = 3 (yellow color in the figure).

**Constraints:**

*   `n == watchedVideos.length == friends.length`
*   `2 <= n <= 100`
*   `1 <= watchedVideos[i].length <= 100`
*   `1 <= watchedVideos[i][j].length <= 8`
*   `0 <= friends[i].length < n`
*   `0 <= friends[i][j] < n`
*   `0 <= id < n`
*   `1 <= level < n`
*   if `friends[i]` contains `j`, then `friends[j]` contains `i`

## A solution in Java

```java
public int largestMagicSquare(int[][] grid) {
    int m = grid.length, n = grid[0].length;
    int[][] row = new int[m][n + 1];
    int[][] col = new int[m + 1][n];

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            row[i][j + 1] = row[i][j] + grid[i][j];
            col[i + 1][j] = col[i][j] + grid[i][j];
        }
    }

    for (int k = Math.min(m, n); k > 1; --k) {
        for (int i = 0; i + k - 1 < m; ++i) {
            for (int j = 0; j + k - 1 < n; ++j) {
                int sum = row[i][j + k] - row[i][j];
                boolean ok = true;
                for (int t = 1; t < k; ++t) {
                    if (row[i + t][j + k] - row[i + t][j] != sum) {
                        ok = false;
                        break;
                    }
                    if (col[i + k][j + t] - col[i][j + t] != sum) {
                        ok = false;
                        break;
                    }
                }
                if (!ok) continue;

                int diag1 = 0, diag2 = 0;
                for (int t = 0; t < k; ++t) {
                    diag1 += grid[i + t][j + t];
                    diag2 += grid[i + t][j + k - 1 - t];
                }
                if (diag1 == sum && diag2 == sum) return k;
            }
        }
    }

    return 1;
}
```
1. First, compute the row and column cumulative sums in `row` and `col` matrices.
2. Iterate `k` from the minimum of `m` and `n` down to 2, which represents the size of the potential magic square.
3. For each `k`, iterate through all possible top-left corners `(i, j)` of the magic square.
4. Check if all row and column sums match. If any do not, skip this position.
5. Calculate both diagonal sums of the magic square. If both diagonal sums match the row and column sums, return `k` as the largest magic square size.
6. If no magic square with size > 1 is found, return 1.

## A solution in C++

```cpp
int largestMagicSquare(vector<vector<int>>& grid) {
    int m = grid.size(), n = grid[0].size();
    vector<vector<int>> row(m, vector<int>(n + 1, 0));
    vector<vector<int>> col(m + 1, vector<int>(n, 0));

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            row[i][j + 1] = row[i][j] + grid[i][j];
            col[i + 1][j] = col[i][j] + grid[i][j];
        }
    }

    for (int k = min(m, n); k > 1; --k) {
        for (int i = 0; i + k - 1 < m; ++i) {
            for (int j = 0; j + k - 1 < n; ++j) {
                int sum = row[i][j + k] - row[i][j];
                bool ok = true;
                for (int t = 1; t < k; ++t) {
                    if (row[i + t][j + k] - row[i + t][j] != sum) {
                        ok = false;
                        break;
                    }
                    if (col[i + k][j + t] - col[i][j + t] != sum) {
                        ok = false;
                        break;
                    }
                }
                if (!ok) continue;

                int diag1 = 0, diag2 = 0;
                for (int t = 0; t < k; ++t) {
                    diag1 += grid[i + t][j + t];
                    diag2 += grid[i + t][j + k - 1 - t];
                }
                if (diag1 == sum && diag2 == sum) return k;
            }
        }
    }

    return 1;
}
```
1. First, compute the row and column cumulative sums in `row` and `col` matrices.
2. Iterate `k` from the minimum of `m` and `n` down to 2, which represents the size of the potential magic square.
3. For each `k`, iterate through all possible top-left corners `(i, j)` of the magic square.
4. Check if all row and column sums match. If any do not, skip this position.
5. Calculate both diagonal sums of the magic square. If both diagonal sums match the row and column sums, return `k` as the largest magic square size.
6. If no magic square with size > 1 is found, return 1.

## A solution in Python

```python
def largestMagicSquare(grid):
    m, n = len(grid), len(grid[0])
    row = [[0] * (n + 1) for _ in range(m)]
    col = [[0] * n for _ in range(m + 1)]

    for i in range(m):
        for j in range(n):
            row[i][j + 1] = row[i][j] + grid[i][j]
            col[i + 1][j] = col[i][j] + grid[i][j]

    for k in reversed(range(2, min(m, n) + 1)):
        for i in range(m - k + 1):
            for j in range(n - k + 1):
                _sum = row[i][j + k] - row[i][j]
                ok = all(row[i + t][j + k] - row[i + t][j] == _sum for t in range(1, k)) and all(
                    col[i + k][j + t] - col[i][j + t] == _sum for t in range(1, k))

                if not ok: continue

                diag1 = sum(grid[i + t][j + t] for t in range(k))
                diag2 = sum(grid[i + t][j + k - 1 - t] for t in range(k))

                if diag1 == _sum and diag2 == _sum: return k

    return 1
```
1. First, compute the row and column cumulative sums in `row` and `col` matrices.
2. Iterate `k` from the minimum of `m` and `n` down to 2, which represents the size of the potential magic square.
3. For each `k`, iterate through all possible top-left corners `(i, j)` of the magic square.
4. Check if all row and column sums match. If any do not, skip this position.
5. Calculate both diagonal sums of the magic square. If both diagonal sums match the row and column sums, return `k` as the largest magic square size.
6. If no magic square with size > 1 is found, return 1.

## A solution in Javascript

```javascript
function largestMagicSquare(grid) {
    const m = grid.length, n = grid[0].length;
    const row = Array.from({length: m}, () => Array(n + 1).fill(0));
    const col = Array.from({length: m + 1}, () => Array(n).fill(0));

    for (let i = 0; i < m; ++i) {
        for (let j = 0; j < n; ++j) {
            row[i][j + 1] = row[i][j] + grid[i][j];
            col[i + 1][j] = col[i][j] + grid[i][j];
        }
    }

    for (let k = Math.min(m, n); k > 1; --k) {
        for (let i = 0; i + k - 1 < m; ++i) {
            for (let j = 0; j + k - 1 < n; ++j) {
                const sum = row[i][j + k] - row[i][j];
                let ok = true;
                for (let t = 1; t < k; ++t) {
                    if (row[i + t][j + k] - row[i + t][j] !== sum || col[i + k][j + t] - col[i][j + t] !== sum) {
                        ok = false;
                        break;
                    }
                }
                if (!ok) continue;

                let diag1 = 0, diag2 = 0;
                for (let t = 0; t < k; ++t) {
                    diag1 += grid[i + t][j + t];
                    diag2 += grid[i + t][j + k - 1 - t];
                }
                if (diag1 === sum && diag2 === sum) return k;
            }
        }
    }

    return 1;
}
```
1. First, compute the row and column cumulative sums in `row` and `col` matrices.
2. Iterate `k` from the minimum of `m` and `n` down to 2, which represents the size of the potential magic square.
3. For each `k`, iterate through all possible top-left corners `(i, j)` of the magic square.
4. Check if all row and column sums match. If any do not, skip this position.
5. Calculate both diagonal sums of the magic square. If both diagonal sums match the row and column sums, return `k` as the largest magic square size.
6. If no magic square with size > 1 is found, return 1.


# Minimum Insertion Steps to Make a String Palindrome

- slug: minimum-insertion-steps-to-make-a-string-palindrome
- difficulty: Hard

Given a string `s`. In one step you can insert any character at any index of the string.

Return _the minimum number of steps_ to make `s` palindrome.

A **Palindrome String** is one that reads the same backward as well as forward.

**Example 1:**

**Input:** s =  "zzazz "
**Output:** 0
**Explanation:** The string  "zzazz " is already palindrome we do not need any insertions.

**Example 2:**

**Input:** s =  "mbadm "
**Output:** 2
**Explanation:** String can be  "mbdadbm " or  "mdbabdm ".

**Example 3:**

**Input:** s =  "leetcode "
**Output:** 5
**Explanation:** Inserting 5 characters the string becomes  "leetcodocteel ".

**Constraints:**

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

## A solution in Java

```java
public int extractArtifacts(int n, int[][] artifacts, int[][] dig) {
    Map<Integer, Set<Integer>> artifactCells = new HashMap<>();
    Map<Integer, Integer> artifactCount = new HashMap<>();
    for (int i = 0; i < artifacts.length; i++) {
        for (int r = artifacts[i][0]; r <= artifacts[i][2]; r++) {
            for (int c = artifacts[i][1]; c <= artifacts[i][3]; c++) {
                int cell = r * n + c;
                artifactCells.computeIfAbsent(cell, k -> new HashSet<>()).add(i);
                artifactCount.put(i, artifactCount.getOrDefault(i, 0) + 1);
            }
        }
    }

    int ans = 0;
    for (int[] d : dig) {
        int cell = d[0] * n + d[1];
        Set<Integer> artifactsInCell = artifactCells.remove(cell);
        if (artifactsInCell != null) {
            for (int artifactId : artifactsInCell) {
                int remaining = artifactCount.get(artifactId) - 1;
                artifactCount.put(artifactId, remaining);
                if (remaining == 0) ans++;
            }
        }
    }
    return ans;
}
```
1. For each artifact, iterate through its grid positions and store the positions in an unordered_map or HashMap (artifact_cells) with the key being the cell value (row * n + column) and the value being a set containing the artifact ID. Also, maintain a count of the number of cells for each artifact in another unordered_map or HashMap (artifact_count).

2. Iterate through the dig array and for each cell, check if it contains any artifacts using the artifact_cells. If so, decrement the count of the corresponding artifacts in the artifact_count, and remove the cell from the artifact_cells.

3. If the count of an artifact reaches 0, increment the result (ans) by 1, as the whole artifact has been uncovered and can be extracted now.

4. Return the final count (ans) after iterating through all the dig cells. This represents the number of artifacts that can be extracted.

## A solution in C++

```cpp
int extractArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
    unordered_map<int, set<pair<int, int>>> artifact_cells;
    unordered_map<int, int> artifact_count;
    for (int i = 0; i < artifacts.size(); i++) {
        for (int r = artifacts[i][0]; r <= artifacts[i][2]; r++) {
            for (int c = artifacts[i][1]; c <= artifacts[i][3]; c++) {
                artifact_cells[r * n + c].insert({i, r * n + c});
                artifact_count[i]++;
            }
        }
    }

    int ans = 0;
    for (const auto& d : dig) {
        int cell = d[0] * n + d[1];
        for (const auto& p : artifact_cells[cell]) {
            artifact_count[p.first]--;
            if (artifact_count[p.first] == 0) ans++;
        }
        artifact_cells.erase(cell);
    }
    return ans;
}
```
1. For each artifact, iterate through its grid positions and store the positions in an unordered_map or HashMap (artifact_cells) with the key being the cell value (row * n + column) and the value being a set containing the artifact ID. Also, maintain a count of the number of cells for each artifact in another unordered_map or HashMap (artifact_count).

2. Iterate through the dig array and for each cell, check if it contains any artifacts using the artifact_cells. If so, decrement the count of the corresponding artifacts in the artifact_count, and remove the cell from the artifact_cells.

3. If the count of an artifact reaches 0, increment the result (ans) by 1, as the whole artifact has been uncovered and can be extracted now.

4. Return the final count (ans) after iterating through all the dig cells. This represents the number of artifacts that can be extracted.

## A solution in Python

```python
def extract_artifacts(n, artifacts, dig):
    artifact_cells = {}
    artifact_count = {}

    for i, (r1, c1, r2, c2) in enumerate(artifacts):
        for r in range(r1, r2 + 1):
            for c in range(c1, c2 + 1):
                cell = r * n + c
                if cell not in artifact_cells:
                    artifact_cells[cell] = set()
                artifact_cells[cell].add(i)
                artifact_count[i] = artifact_count.get(i, 0) + 1

    ans = 0
    for r, c in dig:
        cell = r * n + c
        if cell in artifact_cells:
            for artifact_id in artifact_cells[cell]:
                artifact_count[artifact_id] -= 1
                if artifact_count[artifact_id] == 0:
                    ans += 1
            del artifact_cells[cell]

    return ans
```
1. For each artifact, iterate through its grid positions and store the positions in an unordered_map or HashMap (artifact_cells) with the key being the cell value (row * n + column) and the value being a set containing the artifact ID. Also, maintain a count of the number of cells for each artifact in another unordered_map or HashMap (artifact_count).

2. Iterate through the dig array and for each cell, check if it contains any artifacts using the artifact_cells. If so, decrement the count of the corresponding artifacts in the artifact_count, and remove the cell from the artifact_cells.

3. If the count of an artifact reaches 0, increment the result (ans) by 1, as the whole artifact has been uncovered and can be extracted now.

4. Return the final count (ans) after iterating through all the dig cells. This represents the number of artifacts that can be extracted.

## A solution in Javascript

```javascript
function extractArtifacts(n, artifacts, dig) {
    const artifactCells = new Map();
    const artifactCount = new Map();

    for (let i = 0; i < artifacts.length; i++) {
        for (let r = artifacts[i][0]; r <= artifacts[i][2]; r++) {
            for (let c = artifacts[i][1]; c <= artifacts[i][3]; c++) {
                const cell = r * n + c;
                if (!artifactCells.has(cell)) {
                    artifactCells.set(cell, new Set());
                }
                artifactCells.get(cell).add(i);
                artifactCount.set(i, (artifactCount.get(i) || 0) + 1);
            }
        }
    }

    let ans = 0;
    for (const [r, c] of dig) {
        const cell = r * n + c;
        if (artifactCells.has(cell)) {
            for (const artifactId of artifactCells.get(cell)) {
                const remaining = artifactCount.get(artifactId) - 1;
                artifactCount.set(artifactId, remaining);
                if (remaining === 0) ans++;
            }
            artifactCells.delete(cell);
        }
    }
    return ans;
}
```
1. For each artifact, iterate through its grid positions and store the positions in an unordered_map or HashMap (artifact_cells) with the key being the cell value (row * n + column) and the value being a set containing the artifact ID. Also, maintain a count of the number of cells for each artifact in another unordered_map or HashMap (artifact_count).

2. Iterate through the dig array and for each cell, check if it contains any artifacts using the artifact_cells. If so, decrement the count of the corresponding artifacts in the artifact_count, and remove the cell from the artifact_cells.

3. If the count of an artifact reaches 0, increment the result (ans) by 1, as the whole artifact has been uncovered and can be extracted now.

4. Return the final count (ans) after iterating through all the dig cells. This represents the number of artifacts that can be extracted.


# Decompress Run-Length Encoded List

- slug: decompress-run-length-encoded-list
- difficulty: Easy

We are given a list `nums` of integers representing a list compressed with run-length encoding.

Consider each adjacent pair of elements `[freq, val] = [nums[2*i], nums[2*i+1]]` (with `i >= 0`). For each such pair, there are `freq` elements with value `val` concatenated in a sublist. Concatenate all the sublists from left to right to generate the decompressed list.

Return the decompressed list.

**Example 1:**

**Input:** nums = \[1,2,3,4\]
**Output:** \[2,4,4,4\]
**Explanation:** The first pair \[1,2\] means we have freq = 1 and val = 2 so we generate the array \[2\].
The second pair \[3,4\] means we have freq = 3 and val = 4 so we generate \[4,4,4\].
At the end the concatenation \[2\] + \[4,4,4\] is \[2,4,4,4\].

**Example 2:**

**Input:** nums = \[1,1,2,3\]
**Output:** \[1,3,3\]

**Constraints:**

*   `2 <= nums.length <= 100`
*   `nums.length % 2 == 0`
*   `1 <= nums[i] <= 100`

## A solution in Java

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

public class Solution {
    static final int MOD = (int) 1e9 + 7;

    int addRooms(int idx, List<List<Integer>> children, int[] memo) {
        if (children.get(idx).isEmpty()) return 1;

        if (memo[idx] != -1) return memo[idx];

        long res = 1;
        int cnt = 0;
        for (int child : children.get(idx)) {
            cnt++;
            res = (res * addRooms(child, children, memo)) % MOD;
        }

        for (int i = 2; i <= cnt; i++) {
            res = (res * i) % MOD;
        }

        return memo[idx] = (int) res;
    }

    public int numOfWays(int[] prevRoom) {
        int n = prevRoom.length;
        List<List<Integer>> children = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            children.add(new ArrayList<>());
        }
        for (int i = 1; i < n; i++) {
            children.get(prevRoom[i]).add(i);
        }

        int[] memo = new int[n];
        Arrays.fill(memo, -1);
        return addRooms(0, children, memo);
    }
}
```
1. Create a function addRooms that takes the room index, the array that stores the room dependencies (children), and the memoization array as inputs.
2. If there are no dependencies for the current room, return 1.
3. If the memoization array already has the result for the current room, return it.
4. Calculate the number of ways to create the directly connected rooms with the current room. Multiplying the results is possible because each new room is created after the current room is completed. Apply the modulo operator at each step.
5. Factorial of the number of directly connected rooms need to be multiplied since they can be constructed in any order. Apply the modulo operator at each step.
6. Store the result in the memoization array.
7. Call the addRooms function with room 0 and return the result.

## A solution in C++

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

const int MOD = 1e9 + 7;

int addRooms(int idx, const vector<vector<int>>& children, vector<int>& memo) {
    if (children[idx].empty()) return 1;

    if (memo[idx] != -1) return memo[idx];

    long long res = 1;
    int cnt = 0;
    for (int child : children[idx]) {
        cnt++;
        res = (res * addRooms(child, children, memo)) % MOD;
    }

    for (int i = 2; i <= cnt; i++) {
        res = (res * i) % MOD;
    }

    return memo[idx] = res;
}

int numOfWays(vector<int>& prevRoom) {
    int n = prevRoom.size();
    vector<vector<int>> children(n);
    for (int i = 1; i < n; i++) {
        children[prevRoom[i]].push_back(i);
    }

    vector<int> memo(n, -1);
    return addRooms(0, children, memo);
}
```
1. Create a function addRooms that takes the room index, the array that stores the room dependencies (children), and the memoization array as inputs.
2. If there are no dependencies for the current room, return 1.
3. If the memoization array already has the result for the current room, return it.
4. Calculate the number of ways to create the directly connected rooms with the current room. Multiplying the results is possible because each new room is created after the current room is completed. Apply the modulo operator at each step.
5. Factorial of the number of directly connected rooms need to be multiplied since they can be constructed in any order. Apply the modulo operator at each step.
6. Store the result in the memoization array.
7. Call the addRooms function with room 0 and return the result.

## A solution in Python

```python
MOD = 10**9 + 7

def add_rooms(idx, children, memo):
    if not children[idx]:
        return 1
    if memo[idx] != -1:
        return memo[idx]

    res = 1
    cnt = 0
    for child in children[idx]:
        cnt += 1
        res = (res * add_rooms(child, children, memo)) % MOD

    for i in range(2, cnt + 1):
        res = (res * i) % MOD

    memo[idx] = res
    return res

def num_of_ways(prev_room):
    n = len(prev_room)
    children = [[] for _ in range(n)]
    for i in range(1, n):
        children[prev_room[i]].append(i)

    memo = [-1] * n
    return add_rooms(0, children, memo)
```
1. Create a function addRooms that takes the room index, the array that stores the room dependencies (children), and the memoization array as inputs.
2. If there are no dependencies for the current room, return 1.
3. If the memoization array already has the result for the current room, return it.
4. Calculate the number of ways to create the directly connected rooms with the current room. Multiplying the results is possible because each new room is created after the current room is completed. Apply the modulo operator at each step.
5. Factorial of the number of directly connected rooms need to be multiplied since they can be constructed in any order. Apply the modulo operator at each step.
6. Store the result in the memoization array.
7. Call the addRooms function with room 0 and return the result.

## A solution in Javascript

```javascript
const MOD = 1e9 + 7;

function addRooms(idx, children, memo) {
    if (children[idx].length === 0) return 1;
    if (memo[idx] !== -1) return memo[idx];

    let res = 1;
    let cnt = 0;
    for (const child of children[idx]) {
        cnt++;
        res = (res * addRooms(child, children, memo)) % MOD;
    }

    for (let i = 2; i <= cnt; i++) {
        res = (res * i) % MOD;
    }

    memo[idx] = res;
    return res;
}

function numOfWays(prevRoom) {
    const n = prevRoom.length;
    const children = new Array(n).fill(0).map(() => []);
    for (let i = 1; i < n; i++) {
        children[prevRoom[i]].push(i);
    }

    const memo = new Array(n).fill(-1);
    return addRooms(0, children, memo);
}
```
1. Create a function addRooms that takes the room index, the array that stores the room dependencies (children), and the memoization array as inputs.
2. If there are no dependencies for the current room, return 1.
3. If the memoization array already has the result for the current room, return it.
4. Calculate the number of ways to create the directly connected rooms with the current room. Multiplying the results is possible because each new room is created after the current room is completed. Apply the modulo operator at each step.
5. Factorial of the number of directly connected rooms need to be multiplied since they can be constructed in any order. Apply the modulo operator at each step.
6. Store the result in the memoization array.
7. Call the addRooms function with room 0 and return the result.


# Matrix Block Sum

- slug: matrix-block-sum
- difficulty: Medium

Given a `m x n` matrix `mat` and an integer `k`, return _a matrix_ `answer` _where each_ `answer[i][j]` _is the sum of all elements_ `mat[r][c]` _for_:

*   `i - k <= r <= i + k,`
*   `j - k <= c <= j + k`, and
*   `(r, c)` is a valid position in the matrix.

**Example 1:**

**Input:** mat = \[\[1,2,3\],\[4,5,6\],\[7,8,9\]\], k = 1
**Output:** \[\[12,21,16\],\[27,45,33\],\[24,39,28\]\]

**Example 2:**

**Input:** mat = \[\[1,2,3\],\[4,5,6\],\[7,8,9\]\], k = 2
**Output:** \[\[45,45,45\],\[45,45,45\],\[45,45,45\]\]

**Constraints:**

*   `m == mat.length`
*   `n == mat[i].length`
*   `1 <= m, n, k <= 100`
*   `1 <= mat[i][j] <= 100`

## A solution in Java

```java
public int[][] matrixBlockSum(int[][] mat, int k) {
    int m = mat.length;
    int n = mat[0].length;
    int[][] answer = new int[m][n];

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            for (int r = Math.max(0, i - k); r <= Math.min(m - 1, i + k); r++) {
                for (int c = Math.max(0, j - k); c <= Math.min(n - 1, j + k); c++) {
                    answer[i][j] += mat[r][c];
                }
            }
        }
    }

    return answer;
}
```
This algorithm iterates through each cell of the input matrix `mat`. For each cell, it calculates the sum of all elements in the given sub-matrix range. The sub-matrix `mat[r][c]` is represented by the conditions `i - k <= r <= i + k` and `j - k <= c <= j + k`. It checks if `(r, c)` is a valid position. If it's valid, the sum will be stored in the `answer` matrix at the same index (i, j). The complexity of this algorithm is O(m * n * k^2), where m is the number of rows, n is the number of columns, and k is the range.

## A solution in C++

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

vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
    int m = mat.size();
    int n = mat[0].size();
    vector<vector<int>> answer(m, vector<int>(n, 0));

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int r = max(0, i - k); r <= min(m - 1, i + k); ++r) {
                for (int c = max(0, j - k); c <= min(n - 1, j + k); ++c) {
                    answer[i][j] += mat[r][c];
                }
            }
        }
    }

    return answer;
}
```
This algorithm iterates through each cell of the input matrix `mat`. For each cell, it calculates the sum of all elements in the given sub-matrix range. The sub-matrix `mat[r][c]` is represented by the conditions `i - k <= r <= i + k` and `j - k <= c <= j + k`. It checks if `(r, c)` is a valid position. If it's valid, the sum will be stored in the `answer` matrix at the same index (i, j). The complexity of this algorithm is O(m * n * k^2), where m is the number of rows, n is the number of columns, and k is the range.

## A solution in Python

```python
def matrix_block_sum(mat, k):
    m, n = len(mat), len(mat[0])
    answer = [[0 for _ in range(n)] for _ in range(m)]

    for i in range(m):
        for j in range(n):
            for r in range(max(0, i - k), min(m, i + k + 1)):
                for c in range(max(0, j - k), min(n, j + k + 1)):
                    answer[i][j] += mat[r][c]

    return answer
```
This algorithm iterates through each cell of the input matrix `mat`. For each cell, it calculates the sum of all elements in the given sub-matrix range. The sub-matrix `mat[r][c]` is represented by the conditions `i - k <= r <= i + k` and `j - k <= c <= j + k`. It checks if `(r, c)` is a valid position. If it's valid, the sum will be stored in the `answer` matrix at the same index (i, j). The complexity of this algorithm is O(m * n * k^2), where m is the number of rows, n is the number of columns, and k is the range.

## A solution in Javascript

```javascript
function matrixBlockSum(mat, k) {
    const m = mat.length;
    const n = mat[0].length;
    const answer = new Array(m).fill(null).map(() => new Array(n).fill(0));

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            for (let r = Math.max(0, i - k); r <= Math.min(m - 1, i + k); r++) {
                for (let c = Math.max(0, j - k); c <= Math.min(n - 1, j + k); c++) {
                    answer[i][j] += mat[r][c];
                }
            }
        }
    }

    return answer;
}
```
This algorithm iterates through each cell of the input matrix `mat`. For each cell, it calculates the sum of all elements in the given sub-matrix range. The sub-matrix `mat[r][c]` is represented by the conditions `i - k <= r <= i + k` and `j - k <= c <= j + k`. It checks if `(r, c)` is a valid position. If it's valid, the sum will be stored in the `answer` matrix at the same index (i, j). The complexity of this algorithm is O(m * n * k^2), where m is the number of rows, n is the number of columns, and k is the range.


# Sum of Nodes with Even-Valued Grandparent

- slug: sum-of-nodes-with-even-valued-grandparent
- difficulty: Medium

Given the `root` of a binary tree, return _the sum of values of nodes with an **even-valued grandparent**_. If there are no nodes with an **even-valued grandparent**, return `0`.

A **grandparent** of a node is the parent of its parent if it exists.

**Example 1:**

**Input:** root = \[6,7,8,2,7,1,3,9,null,1,4,null,null,null,5\]
**Output:** 18
**Explanation:** The red nodes are the nodes with even-value grandparent while the blue nodes are the even-value grandparents.

**Example 2:**

**Input:** root = \[1\]
**Output:** 0

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 104]`.
*   `1 <= Node.val <= 100`

## A solution in Java

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

public int sumEvenGrandparent(TreeNode root, TreeNode parent, TreeNode grandparent) {
    if (root == null) return 0;
    int sum = (grandparent != null && grandparent.val % 2 == 0) ? root.val : 0;
    return sum + sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent);
}
```
We use a recursive tree traversal with an additional two parameters, one to keep track of the parent node and another to keep track of the grandparent node. During the traversal, we check if the current node's grandparent has an even value.

In each function, we start by checking if the root is null (or if there is no node), and if so, we return 0. Then we calculate the sum of the current node. If the grandparent exists and has an even-valued integer, we add the current node's value to the sum. Otherwise, the sum remains 0.

Next, we update the sum by recursively calling the function for the left and right children of the current node, updating the parent and grandparent with the current node as the new parent and the old parent as the new grandparent. This is conducted in a depth-first search manner.

Finally, we return the total sum. All four-function implementations follow the same logic.

## A solution in C++

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

int sumEvenGrandparent(TreeNode* root, TreeNode* parent = nullptr, TreeNode* grandparent = nullptr) {
    if (root == nullptr) return 0;
    int sum = ((grandparent != nullptr) && (grandparent->val % 2 == 0)) ? root->val : 0;
    return sum + sumEvenGrandparent(root->left, root, parent) + sumEvenGrandparent(root->right, root, parent);
}
```
We use a recursive tree traversal with an additional two parameters, one to keep track of the parent node and another to keep track of the grandparent node. During the traversal, we check if the current node's grandparent has an even value.

In each function, we start by checking if the root is null (or if there is no node), and if so, we return 0. Then we calculate the sum of the current node. If the grandparent exists and has an even-valued integer, we add the current node's value to the sum. Otherwise, the sum remains 0.

Next, we update the sum by recursively calling the function for the left and right children of the current node, updating the parent and grandparent with the current node as the new parent and the old parent as the new grandparent. This is conducted in a depth-first search manner.

Finally, we return the total sum. All four-function implementations follow the same logic.

## A solution in Python

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

def sumEvenGrandparent(root, parent=None, grandparent=None):
    if root is None:
        return 0
    sum = root.val if grandparent and grandparent.val % 2 == 0 else 0
    return sum + sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent)
```
We use a recursive tree traversal with an additional two parameters, one to keep track of the parent node and another to keep track of the grandparent node. During the traversal, we check if the current node's grandparent has an even value.

In each function, we start by checking if the root is null (or if there is no node), and if so, we return 0. Then we calculate the sum of the current node. If the grandparent exists and has an even-valued integer, we add the current node's value to the sum. Otherwise, the sum remains 0.

Next, we update the sum by recursively calling the function for the left and right children of the current node, updating the parent and grandparent with the current node as the new parent and the old parent as the new grandparent. This is conducted in a depth-first search manner.

Finally, we return the total sum. All four-function implementations follow the same logic.

## A solution in Javascript

```javascript
class TreeNode {
  constructor(val, left, right) {
    this.val = (val === undefined ? 0 : val)
    this.left = (left === undefined ? null : left)
    this.right = (right === undefined ? null : right)
  }
}

function sumEvenGrandparent(root, parent = null, grandparent = null) {
  if (root === null) return 0;
  let sum = (grandparent !== null && grandparent.val % 2 === 0) ? root.val : 0;
  return sum + sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent);
}
```
We use a recursive tree traversal with an additional two parameters, one to keep track of the parent node and another to keep track of the grandparent node. During the traversal, we check if the current node's grandparent has an even value.

In each function, we start by checking if the root is null (or if there is no node), and if so, we return 0. Then we calculate the sum of the current node. If the grandparent exists and has an even-valued integer, we add the current node's value to the sum. Otherwise, the sum remains 0.

Next, we update the sum by recursively calling the function for the left and right children of the current node, updating the parent and grandparent with the current node as the new parent and the old parent as the new grandparent. This is conducted in a depth-first search manner.

Finally, we return the total sum. All four-function implementations follow the same logic.


# Convert Integer to the Sum of Two No-Zero Integers

- slug: convert-integer-to-the-sum-of-two-no-zero-integers
- difficulty: Easy

**No-Zero integer** is a positive integer that **does not contain any `0`** in its decimal representation.

Given an integer `n`, return _a list of two integers_ `[a, b]` _where_:

*   `a` and `b` are **No-Zero integers**.
*   `a + b = n`

The test cases are generated so that there is at least one valid solution. If there are many valid solutions, you can return any of them.

**Example 1:**

**Input:** n = 2
**Output:** \[1,1\]
**Explanation:** Let a = 1 and b = 1.
Both a and b are no-zero integers, and a + b = 2 = n.

**Example 2:**

**Input:** n = 11
**Output:** \[2,9\]
**Explanation:** Let a = 2 and b = 9.
Both a and b are no-zero integers, and a + b = 9 = n.
Note that there are other valid answers as \[8, 3\] that can be accepted.

**Constraints:**

*   `2 <= n <= 104`

## A solution in Java

```java
public int[] noZeroIntegers(int n) {
    for (int a = 1; a < n; ++a) {
        if (Integer.toString(a).indexOf('0') == -1 &&
            Integer.toString(n - a).indexOf('0') == -1) {
            return new int[]{a, n - a};
        }
    }
    return new int[]{0, 0}; // never gets here
}
```
We will write a function that receives an integer `n` as the input. The algorithm then iterates over all integers from `1` to `n-1` as a candidate for value `a` in the result `[a, b]`. For each candidate `a`, we check if both `a` and `n-a` (which would be `b`) are No-Zero integers by ensuring that neither of the strings representation have a '0'. If both strings don't have a '0', we found a valid answer and return a list containing `[a, n-a]`. The loop should always find a valid answer for the given constraints.

## A solution in C++

```cpp
std::vector<int> noZeroIntegers(int n) {
    for (int a = 1; a < n; ++a) {
        if (std::to_string(a).find('0') == std::string::npos &&
            std::to_string(n - a).find('0') == std::string::npos) {
            return {a, n - a};
        }
    }
    return {0, 0}; // never gets here
}
```
We will write a function that receives an integer `n` as the input. The algorithm then iterates over all integers from `1` to `n-1` as a candidate for value `a` in the result `[a, b]`. For each candidate `a`, we check if both `a` and `n-a` (which would be `b`) are No-Zero integers by ensuring that neither of the strings representation have a '0'. If both strings don't have a '0', we found a valid answer and return a list containing `[a, n-a]`. The loop should always find a valid answer for the given constraints.

## A solution in Python

```python
def no_zero_integers(n: int):
    for a in range(1, n):
        if '0' not in str(a) and '0' not in str(n - a):
            return [a, n - a]
    return [0, 0]  # never gets here
```
We will write a function that receives an integer `n` as the input. The algorithm then iterates over all integers from `1` to `n-1` as a candidate for value `a` in the result `[a, b]`. For each candidate `a`, we check if both `a` and `n-a` (which would be `b`) are No-Zero integers by ensuring that neither of the strings representation have a '0'. If both strings don't have a '0', we found a valid answer and return a list containing `[a, n-a]`. The loop should always find a valid answer for the given constraints.

## A solution in Javascript

```javascript
function noZeroIntegers(n) {
    for (let a = 1; a < n; ++a) {
        if (!String(a).includes('0') && !String(n - a).includes('0')) {
            return [a, n - a];
        }
    }
    return [0, 0]; // never gets here
}
```
We will write a function that receives an integer `n` as the input. The algorithm then iterates over all integers from `1` to `n-1` as a candidate for value `a` in the result `[a, b]`. For each candidate `a`, we check if both `a` and `n-a` (which would be `b`) are No-Zero integers by ensuring that neither of the strings representation have a '0'. If both strings don't have a '0', we found a valid answer and return a list containing `[a, n-a]`. The loop should always find a valid answer for the given constraints.


# Minimum Flips to Make a OR b Equal to c

- slug: minimum-flips-to-make-a-or-b-equal-to-c
- difficulty: Medium

Given 3 positives numbers `a`, `b` and `c`. Return the minimum flips required in some bits of `a` and `b` to make ( `a` OR `b` == `c` ). (bitwise OR operation).
Flip operation consists of change **any** single bit 1 to 0 or change the bit 0 to 1 in their binary representation.

**Example 1:**

**Input:** a = 2, b = 6, c = 5
**Output:** 3
**Explanation:** After flips a = 1 , b = 4 , c = 5 such that (`a` OR `b` == `c`)

**Example 2:**

**Input:** a = 4, b = 2, c = 7
**Output:** 1

**Example 3:**

**Input:** a = 1, b = 2, c = 3
**Output:** 0

**Constraints:**

*   `1 <= a <= 10^9`
*   `1 <= b <= 10^9`
*   `1 <= c <= 10^9`

## A solution in Java

```java
public int minFlips(int a, int b, int c) {
    int count = 0;
    for (int i = 0; i < 32; ++i) {
        int bitA = (a >> i) & 1;
        int bitB = (b >> i) & 1;
        int bitC = (c >> i) & 1;
        if (bitC == 0) {
            count += bitA + bitB;
        } else {
            count += 1 - (bitA | bitB);
        }
    }
    return count;
}
```
We iterate through all 32 bits since the maximum number is 10^9, which requires 30 bits to represent in binary. For each bit, we determine the bits for `a`, `b`, and `c`, at the current position. If the bit in `c` is 0, we increment the counter by the sum of the bits of `a` and `b` at that position. This is because we need to flip any 1s in `a` and `b` to make the OR result 0. If the bit in `c` is 1, we increment the counter by 1 minus the OR result of `a` and `b`. This is because either `a` or `b` (or both) need to have a 1 at this position, so 1 minus the OR result gives us the necessary flips.

## A solution in C++

```cpp
int minFlips(int a, int b, int c) {
    int count = 0;
    for (int i = 0; i < 32; ++i) {
        int bitA = (a >> i) & 1;
        int bitB = (b >> i) & 1;
        int bitC = (c >> i) & 1;
        if (bitC == 0) {
            count += bitA + bitB;
        } else {
            count += 1 - (bitA | bitB);
        }
    }
    return count;
}
```
We iterate through all 32 bits since the maximum number is 10^9, which requires 30 bits to represent in binary. For each bit, we determine the bits for `a`, `b`, and `c`, at the current position. If the bit in `c` is 0, we increment the counter by the sum of the bits of `a` and `b` at that position. This is because we need to flip any 1s in `a` and `b` to make the OR result 0. If the bit in `c` is 1, we increment the counter by 1 minus the OR result of `a` and `b`. This is because either `a` or `b` (or both) need to have a 1 at this position, so 1 minus the OR result gives us the necessary flips.

## A solution in Python

```python
def minFlips(a: int, b: int, c: int) -> int:
    count = 0
    for i in range(32):
        bitA = (a >> i) & 1
        bitB = (b >> i) & 1
        bitC = (c >> i) & 1
        if bitC == 0:
            count += bitA + bitB
        else:
            count += 1 - (bitA | bitB)
    return count
```
We iterate through all 32 bits since the maximum number is 10^9, which requires 30 bits to represent in binary. For each bit, we determine the bits for `a`, `b`, and `c`, at the current position. If the bit in `c` is 0, we increment the counter by the sum of the bits of `a` and `b` at that position. This is because we need to flip any 1s in `a` and `b` to make the OR result 0. If the bit in `c` is 1, we increment the counter by 1 minus the OR result of `a` and `b`. This is because either `a` or `b` (or both) need to have a 1 at this position, so 1 minus the OR result gives us the necessary flips.

## A solution in Javascript

```javascript
function minFlips(a, b, c) {
    let count = 0;
    for (let i = 0; i < 32; ++i) {
        let bitA = (a >> i) & 1;
        let bitB = (b >> i) & 1;
        let bitC = (c >> i) & 1;
        if (bitC === 0) {
            count += bitA + bitB;
        } else {
            count += 1 - (bitA | bitB);
        }
    }
    return count;
}
```
We iterate through all 32 bits since the maximum number is 10^9, which requires 30 bits to represent in binary. For each bit, we determine the bits for `a`, `b`, and `c`, at the current position. If the bit in `c` is 0, we increment the counter by the sum of the bits of `a` and `b` at that position. This is because we need to flip any 1s in `a` and `b` to make the OR result 0. If the bit in `c` is 1, we increment the counter by 1 minus the OR result of `a` and `b`. This is because either `a` or `b` (or both) need to have a 1 at this position, so 1 minus the OR result gives us the necessary flips.


# Number of Operations to Make Network Connected

- slug: number-of-operations-to-make-network-connected
- difficulty: Medium

There are `n` computers numbered from `0` to `n - 1` connected by ethernet cables `connections` forming a network where `connections[i] = [ai, bi]` represents a connection between computers `ai` and `bi`. Any computer can reach any other computer directly or indirectly through the network.

You are given an initial computer network `connections`. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected.

Return _the minimum number of times you need to do this in order to make all the computers connected_. If it is not possible, return `-1`.

**Example 1:**

**Input:** n = 4, connections = \[\[0,1\],\[0,2\],\[1,2\]\]
**Output:** 1
**Explanation:** Remove cable between computer 1 and 2 and place between computers 1 and 3.

**Example 2:**

**Input:** n = 6, connections = \[\[0,1\],\[0,2\],\[0,3\],\[1,2\],\[1,3\]\]
**Output:** 2

**Example 3:**

**Input:** n = 6, connections = \[\[0,1\],\[0,2\],\[0,3\],\[1,2\]\]
**Output:** -1
**Explanation:** There are not enough cables.

**Constraints:**

*   `1 <= n <= 105`
*   `1 <= connections.length <= min(n * (n - 1) / 2, 105)`
*   `connections[i].length == 2`
*   `0 <= ai, bi < n`
*   `ai != bi`
*   There are no repeated connections.
*   No two computers are connected by more than one cable.

## A solution in Java

```java
import java.util.HashMap;
import java.util.HashSet;

public boolean uniqueOccurrences(int[] arr) {
    HashMap<Integer, Integer> counts = new HashMap<>();
    for (int num : arr) {
        counts.put(num, counts.getOrDefault(num, 0) + 1);
    }

    HashSet<Integer> uniqueCounts = new HashSet<>();
    for (int count : counts.values()) {
        if (uniqueCounts.contains(count)) {
            return false;
        }
        uniqueCounts.add(count);
    }

    return true;
}
```
The algorithm first computes a hashmap where the keys are the integers in the input array 'arr' and the values are their counts/occurrences. Then, it iterates through the hashmap's values (counts) and checks if the count already exists in a set (unique_counts). If the count exists, it returns false, as it means there is a duplicate number of occurrences. If the for-loop completes, return true, as there are no duplicate occurrences. This algorithm has a time complexity of O(n), where n is the length of the input array 'arr'.

## A solution in C++

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

bool uniqueOccurrences(vector<int>& arr) {
    map<int, int> counts;
    for (int num : arr) {
        counts[num]++;
    }

    unordered_set<int> unique_counts;
    for (auto& count : counts) {
        if (unique_counts.count(count.second) > 0) {
            return false;
        }
        unique_counts.insert(count.second);
    }

    return true;
}
```
The algorithm first computes a hashmap where the keys are the integers in the input array 'arr' and the values are their counts/occurrences. Then, it iterates through the hashmap's values (counts) and checks if the count already exists in a set (unique_counts). If the count exists, it returns false, as it means there is a duplicate number of occurrences. If the for-loop completes, return true, as there are no duplicate occurrences. This algorithm has a time complexity of O(n), where n is the length of the input array 'arr'.

## A solution in Python

```python
def unique_occurrences(arr):
    counts = {}
    for num in arr:
        counts[num] = counts.get(num, 0) + 1

    unique_counts = set()
    for count in counts.values():
        if count in unique_counts:
            return False
        unique_counts.add(count)

    return True
```
The algorithm first computes a hashmap where the keys are the integers in the input array 'arr' and the values are their counts/occurrences. Then, it iterates through the hashmap's values (counts) and checks if the count already exists in a set (unique_counts). If the count exists, it returns false, as it means there is a duplicate number of occurrences. If the for-loop completes, return true, as there are no duplicate occurrences. This algorithm has a time complexity of O(n), where n is the length of the input array 'arr'.

## A solution in Javascript

```javascript
function uniqueOccurrences(arr) {
    const counts = {};
    for (let num of arr) {
        counts[num] = (counts[num] || 0) + 1;
    }

    const uniqueCounts = new Set();
    for (let count in counts) {
        if (uniqueCounts.has(counts[count])) {
            return false;
        }
        uniqueCounts.add(counts[count]);
    }

    return true;
}
```
The algorithm first computes a hashmap where the keys are the integers in the input array 'arr' and the values are their counts/occurrences. Then, it iterates through the hashmap's values (counts) and checks if the count already exists in a set (unique_counts). If the count exists, it returns false, as it means there is a duplicate number of occurrences. If the for-loop completes, return true, as there are no duplicate occurrences. This algorithm has a time complexity of O(n), where n is the length of the input array 'arr'.


# Minimum Distance to Type a Word Using Two Fingers

- slug: minimum-distance-to-type-a-word-using-two-fingers
- difficulty: Hard

You have a keyboard layout as shown above in the **X-Y** plane, where each English uppercase letter is located at some coordinate.

*   For example, the letter `'A'` is located at coordinate `(0, 0)`, the letter `'B'` is located at coordinate `(0, 1)`, the letter `'P'` is located at coordinate `(2, 3)` and the letter `'Z'` is located at coordinate `(4, 1)`.

Given the string `word`, return _the minimum total **distance** to type such string using only two fingers_.

The **distance** between coordinates `(x1, y1)` and `(x2, y2)` is `|x1 - x2| + |y1 - y2|`.

**Note** that the initial positions of your two fingers are considered free so do not count towards your total distance, also your two fingers do not have to start at the first letter or the first two letters.

**Example 1:**

**Input:** word =  "CAKE "
**Output:** 3
**Explanation:** Using two fingers, one optimal way to type  "CAKE " is:
Finger 1 on letter 'C' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'C' to letter 'A' = 2
Finger 2 on letter 'K' -> cost = 0
Finger 2 on letter 'E' -> cost = Distance from letter 'K' to letter 'E' = 1
Total distance = 3

**Example 2:**

**Input:** word =  "HAPPY "
**Output:** 6
**Explanation:** Using two fingers, one optimal way to type  "HAPPY " is:
Finger 1 on letter 'H' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'H' to letter 'A' = 2
Finger 2 on letter 'P' -> cost = 0
Finger 2 on letter 'P' -> cost = Distance from letter 'P' to letter 'P' = 0
Finger 1 on letter 'Y' -> cost = Distance from letter 'A' to letter 'Y' = 4
Total distance = 6

**Constraints:**

*   `2 <= word.length <= 300`
*   `word` consists of uppercase English letters.

## A solution in Java

```java
import java.util.Stack;

public String removeDuplicates(String s, int k) {
    Stack<Pair<Character, Integer>> st = new Stack<>();
    for (char c : s.toCharArray()) {
        if (!st.isEmpty() && st.peek().getKey() == c) {
            st.peek().setValue(st.peek().getValue() + 1);
            if (st.peek().getValue() == k) st.pop();
        } else {
            st.push(new Pair<>(c, 1));
        }
    }
    StringBuilder result = new StringBuilder();
    while (!st.isEmpty()) {
        Pair<Character, Integer> top = st.pop();
        for (int i = 0; i < top.getValue(); i++) {
            result.insert(0, top.getKey());
        }
    }
    return result.toString();
}
```
The algorithm initializes an empty stack for storing input string characters and their counts. It iterates through the input string, checking each character. If the top of the stack contains the same character, its count is incremented by 1. If the count becomes equal to k, remove that character from the stack, as we've found k adjacent and equal letters to remove. If the top of the stack does not contain the same character, push the character and the count 1 to the stack.

Once the input string has been processed, build the resulting string by concatenating characters from the stack with their respective counts.

The time complexity of this algorithm is O(n), as it iterates over each character in the input string once, and the space complexity is O(n), as it uses a stack to store elements.

## A solution in C++

```cpp
#include <string>
#include <stack>

std::string removeDuplicates(std::string s, int k) {
    std::stack<std::pair<char, int>> st;
    for (char c : s) {
        if (!st.empty() && st.top().first == c) {
            st.top().second++;
            if (st.top().second == k) st.pop();
        } else {
            st.push({c, 1});
        }
    }
    std::string result = "";
    while (!st.empty()) {
        result = std::string(st.top().second, st.top().first) + result;
        st.pop();
    }
    return result;
}
```
The algorithm initializes an empty stack for storing input string characters and their counts. It iterates through the input string, checking each character. If the top of the stack contains the same character, its count is incremented by 1. If the count becomes equal to k, remove that character from the stack, as we've found k adjacent and equal letters to remove. If the top of the stack does not contain the same character, push the character and the count 1 to the stack.

Once the input string has been processed, build the resulting string by concatenating characters from the stack with their respective counts.

The time complexity of this algorithm is O(n), as it iterates over each character in the input string once, and the space complexity is O(n), as it uses a stack to store elements.

## A solution in Python

```python
def removeDuplicates(s: str, k: int) -> str:
    stack = []
    for c in s:
        if stack and stack[-1][0] == c:
            stack[-1][1] += 1
            if stack[-1][1] == k:
                stack.pop()
        else:
            stack.append([c, 1])
    return ''.join(c * n for c, n in stack)
```
The algorithm initializes an empty stack for storing input string characters and their counts. It iterates through the input string, checking each character. If the top of the stack contains the same character, its count is incremented by 1. If the count becomes equal to k, remove that character from the stack, as we've found k adjacent and equal letters to remove. If the top of the stack does not contain the same character, push the character and the count 1 to the stack.

Once the input string has been processed, build the resulting string by concatenating characters from the stack with their respective counts.

The time complexity of this algorithm is O(n), as it iterates over each character in the input string once, and the space complexity is O(n), as it uses a stack to store elements.

## A solution in Javascript

```javascript
function removeDuplicates(s, k) {
    let stack = [];
    for (let c of s) {
        if (stack.length > 0 && stack[stack.length - 1][0] === c) {
            stack[stack.length - 1][1]++;
            if (stack[stack.length - 1][1] === k) stack.pop();
        } else {
            stack.push([c, 1]);
        }
    }
    return stack.map(([c, n]) => c.repeat(n)).join('');
}
```
The algorithm initializes an empty stack for storing input string characters and their counts. It iterates through the input string, checking each character. If the top of the stack contains the same character, its count is incremented by 1. If the count becomes equal to k, remove that character from the stack, as we've found k adjacent and equal letters to remove. If the top of the stack does not contain the same character, push the character and the count 1 to the stack.

Once the input string has been processed, build the resulting string by concatenating characters from the stack with their respective counts.

The time complexity of this algorithm is O(n), as it iterates over each character in the input string once, and the space complexity is O(n), as it uses a stack to store elements.


# Maximum 69 Number

- slug: maximum-69-number
- difficulty: Easy

You are given a positive integer `num` consisting only of digits `6` and `9`.

Return _the maximum number you can get by changing **at most** one digit (_`6` _becomes_ `9`_, and_ `9` _becomes_ `6`_)_.

**Example 1:**

**Input:** num = 9669
**Output:** 9969
**Explanation:**
Changing the first digit results in 6669.
Changing the second digit results in 9969.
Changing the third digit results in 9699.
Changing the fourth digit results in 9666.
The maximum number is 9969.

**Example 2:**

**Input:** num = 9996
**Output:** 9999
**Explanation:** Changing the last digit 6 to 9 results in the maximum number.

**Example 3:**

**Input:** num = 9999
**Output:** 9999
**Explanation:** It is better not to apply any change.

**Constraints:**

*   `1 <= num <= 104`
*   `num` consists of only `6` and `9` digits.

## A solution in Java

```java
public int maximum69Number (int num) {
    String numStr = Integer.toString(num);
    char[] numArr = numStr.toCharArray();
    for (int i = 0; i < numArr.length; i++) {
        if (numArr[i] == '6') {
            numArr[i] = '9';
            break;
        }
    }
    return Integer.parseInt(new String(numArr));
}
```
The algorithm to solve this problem is simple:

1. Convert the integer `num` to a string, so that we can easily manipulate individual digits.
2. Iterate through the string, looking for the first occurrence of the digit '6'.
3. When the digit '6' is found, change it to '9' and exit the loop.
4. Convert the modified string back to an integer and return it.

This algorithm guarantees that only one digit will be modified at most, and the result will be the maximum value possible under the given constraints.

## A solution in C++

```cpp
int maximum69Number (int num) {
    string numStr = to_string(num);
    for (char &c : numStr) {
        if (c == '6') {
            c = '9';
            break;
        }
    }
    return stoi(numStr);
}
```
The algorithm to solve this problem is simple:

1. Convert the integer `num` to a string, so that we can easily manipulate individual digits.
2. Iterate through the string, looking for the first occurrence of the digit '6'.
3. When the digit '6' is found, change it to '9' and exit the loop.
4. Convert the modified string back to an integer and return it.

This algorithm guarantees that only one digit will be modified at most, and the result will be the maximum value possible under the given constraints.

## A solution in Python

```python
def maximum69Number(num: int) -> int:
    num_str = list(str(num))
    for i in range(len(num_str)):
        if num_str[i] == '6':
            num_str[i] = '9'
            break
    return int(''.join(num_str))
```
The algorithm to solve this problem is simple:

1. Convert the integer `num` to a string, so that we can easily manipulate individual digits.
2. Iterate through the string, looking for the first occurrence of the digit '6'.
3. When the digit '6' is found, change it to '9' and exit the loop.
4. Convert the modified string back to an integer and return it.

This algorithm guarantees that only one digit will be modified at most, and the result will be the maximum value possible under the given constraints.

## A solution in Javascript

```javascript
function maximum69Number(num) {
    let numStr = num.toString();
    let numArr = Array.from(numStr);
    for (let i = 0; i < numArr.length; i++) {
        if (numArr[i] == '6') {
            numArr[i] = '9';
            break;
        }
    }
    return parseInt(numArr.join(''));
}
```
The algorithm to solve this problem is simple:

1. Convert the integer `num` to a string, so that we can easily manipulate individual digits.
2. Iterate through the string, looking for the first occurrence of the digit '6'.
3. When the digit '6' is found, change it to '9' and exit the loop.
4. Convert the modified string back to an integer and return it.

This algorithm guarantees that only one digit will be modified at most, and the result will be the maximum value possible under the given constraints.