# Design Bitset

- slug: design-bitset
- difficulty: Medium

A **Bitset** is a data structure that compactly stores bits.

Implement the `Bitset` class:

*   `Bitset(int size)` Initializes the Bitset with `size` bits, all of which are `0`.
*   `void fix(int idx)` Updates the value of the bit at the index `idx` to `1`. If the value was already `1`, no change occurs.
*   `void unfix(int idx)` Updates the value of the bit at the index `idx` to `0`. If the value was already `0`, no change occurs.
*   `void flip()` Flips the values of each bit in the Bitset. In other words, all bits with value `0` will now have value `1` and vice versa.
*   `boolean all()` Checks if the value of **each** bit in the Bitset is `1`. Returns `true` if it satisfies the condition, `false` otherwise.
*   `boolean one()` Checks if there is **at least one** bit in the Bitset with value `1`. Returns `true` if it satisfies the condition, `false` otherwise.
*   `int count()` Returns the **total number** of bits in the Bitset which have value `1`.
*   `String toString()` Returns the current composition of the Bitset. Note that in the resultant string, the character at the `ith` index should coincide with the value at the `ith` bit of the Bitset.

**Example 1:**

**Input**
\[ "Bitset ",  "fix ",  "fix ",  "flip ",  "all ",  "unfix ",  "flip ",  "one ",  "unfix ",  "count ",  "toString "\]
\[\[5\], \[3\], \[1\], \[\], \[\], \[0\], \[\], \[\], \[0\], \[\], \[\]\]
**Output**
\[null, null, null, null, false, null, null, true, null, 2,  "01010 "\]

**Explanation**
Bitset bs = new Bitset(5); // bitset =  "00000 ".
bs.fix(3);     // the value at idx = 3 is updated to 1, so bitset =  "00010 ".
bs.fix(1);     // the value at idx = 1 is updated to 1, so bitset =  "01010 ".
bs.flip();     // the value of each bit is flipped, so bitset =  "10101 ".
bs.all();      // return False, as not all values of the bitset are 1.
bs.unfix(0);   // the value at idx = 0 is updated to 0, so bitset =  "00101 ".
bs.flip();     // the value of each bit is flipped, so bitset =  "11010 ".
bs.one();      // return True, as there is at least 1 index with value 1.
bs.unfix(0);   // the value at idx = 0 is updated to 0, so bitset =  "01010 ".
bs.count();    // return 2, as there are 2 bits with value 1.
bs.toString(); // return  "01010 ", which is the composition of bitset.

**Constraints:**

*   `1 <= size <= 105`
*   `0 <= idx <= size - 1`
*   At most `105` calls will be made **in total** to `fix`, `unfix`, `flip`, `all`, `one`, `count`, and `toString`.
*   At least one call will be made to `all`, `one`, `count`, or `toString`.
*   At most `5` calls will be made to `toString`.

## A solution in Java

```java
public int validMoveCombinations(String[] pieces, int[][] positions) {
    int n = pieces.length;
    int count = 0;

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i != j && !(pieces[i].equals("bishop") && (positions[i][0] + positions[i][1]) % 2 != (positions[j][0] + positions[j][1]) % 2)) {
                count++;
            }
        }
    }

    return count;
}
```
The algorithm iterates over all pairs of pieces (not equal to each other) and checks if any of them can move towards the other without violating the rules of a bishop. If a pair passes this condition, it increments the count. In the end, it returns the total count of valid move combinations. It doesn't consider pieces other than bishops for blocking purposes, because rooks and queens can move in any direction and always be able to avoid a collision, while bishops are limited to squares with the same color as their own square.

## A solution in C++

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

int validMoveCombinations(std::vector<std::string> pieces, std::vector<std::vector<int>> positions) {
    int n = pieces.size();
    int count = 0;

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i != j && !(pieces[i] == "bishop" && (positions[i][0] + positions[i][1]) % 2 != (positions[j][0] + positions[j][1]) % 2)) {
                count++;
            }
        }
    }

    return count;
}
```
The algorithm iterates over all pairs of pieces (not equal to each other) and checks if any of them can move towards the other without violating the rules of a bishop. If a pair passes this condition, it increments the count. In the end, it returns the total count of valid move combinations. It doesn't consider pieces other than bishops for blocking purposes, because rooks and queens can move in any direction and always be able to avoid a collision, while bishops are limited to squares with the same color as their own square.

## A solution in Python

```python
def valid_move_combinations(pieces, positions):
    n = len(pieces)
    count = 0

    for i in range(n):
        for j in range(n):
            if i != j and not (pieces[i] == "bishop" and (positions[i][0] + positions[i][1]) % 2 != (positions[j][0] + positions[j][1]) % 2):
                count += 1

    return count
```
The algorithm iterates over all pairs of pieces (not equal to each other) and checks if any of them can move towards the other without violating the rules of a bishop. If a pair passes this condition, it increments the count. In the end, it returns the total count of valid move combinations. It doesn't consider pieces other than bishops for blocking purposes, because rooks and queens can move in any direction and always be able to avoid a collision, while bishops are limited to squares with the same color as their own square.

## A solution in Javascript

```javascript
function validMoveCombinations(pieces, positions) {
    const n = pieces.length;
    let count = 0;

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            if (i !== j && !(pieces[i] === "bishop" && (positions[i][0] + positions[i][1]) % 2 !== (positions[j][0] + positions[j][1]) % 2 )) {
                count++;
            }
        }
    }

    return count;
}
```
The algorithm iterates over all pairs of pieces (not equal to each other) and checks if any of them can move towards the other without violating the rules of a bishop. If a pair passes this condition, it increments the count. In the end, it returns the total count of valid move combinations. It doesn't consider pieces other than bishops for blocking purposes, because rooks and queens can move in any direction and always be able to avoid a collision, while bishops are limited to squares with the same color as their own square.


# Minimum Time to Remove All Cars Containing Illegal Goods

- slug: minimum-time-to-remove-all-cars-containing-illegal-goods
- difficulty: Hard

You are given a **0-indexed** binary string `s` which represents a sequence of train cars. `s[i] = '0'` denotes that the `ith` car does **not** contain illegal goods and `s[i] = '1'` denotes that the `ith` car does contain illegal goods.

As the train conductor, you would like to get rid of all the cars containing illegal goods. You can do any of the following three operations **any** number of times:

1.  Remove a train car from the **left** end (i.e., remove `s[0]`) which takes 1 unit of time.
2.  Remove a train car from the **right** end (i.e., remove `s[s.length - 1]`) which takes 1 unit of time.
3.  Remove a train car from **anywhere** in the sequence which takes 2 units of time.

Return _the **minimum** time to remove all the cars containing illegal goods_.

Note that an empty sequence of cars is considered to have no cars containing illegal goods.

**Example 1:**

**Input:** s =  "**11**00**1**0**1** "
**Output:** 5
**Explanation:**
One way to remove all the cars containing illegal goods from the sequence is to
- remove a car from the left end 2 times. Time taken is 2 \* 1 = 2.
- remove a car from the right end. Time taken is 1.
- remove the car containing illegal goods found in the middle. Time taken is 2.
This obtains a total time of 2 + 1 + 2 = 5.

An alternative way is to
- remove a car from the left end 2 times. Time taken is 2 \* 1 = 2.
- remove a car from the right end 3 times. Time taken is 3 \* 1 = 3.
This also obtains a total time of 2 + 3 = 5.

5 is the minimum time taken to remove all the cars containing illegal goods.
There are no other ways to remove them with less time.

**Example 2:**

**Input:** s =  "00**1**0 "
**Output:** 2
**Explanation:**
One way to remove all the cars containing illegal goods from the sequence is to
- remove a car from the left end 3 times. Time taken is 3 \* 1 = 3.
This obtains a total time of 3.

Another way to remove all the cars containing illegal goods from the sequence is to
- remove the car containing illegal goods found in the middle. Time taken is 2.
This obtains a total time of 2.

Another way to remove all the cars containing illegal goods from the sequence is to
- remove a car from the right end 2 times. Time taken is 2 \* 1 = 2.
This obtains a total time of 2.

2 is the minimum time taken to remove all the cars containing illegal goods.
There are no other ways to remove them with less time.

**Constraints:**

*   `1 <= s.length <= 2 * 105`
*   `s[i]` is either `'0'` or `'1'`.

## A solution in Java

```java
int min_time_to_remove_illegal_goods(String s) {
    int ones = 0, twos = 0;
    for (char c : s.toCharArray()) {
        if (c == '1') {
            twos += ones;
            ones++;
        }
    }
    return ones + Math.min(ones, twos);
}
```
The algorithm:
1. Initialize two counters, `ones` and `twos`, to 0.
2. Iterate through the characters in the string.
3. If a character is '1', increment `ones` then add the current value of `ones` to `twos`.
4. At the end, return `ones + min(ones, twos)`.

Step 3 updates the count based on either removing the car from the left (`ones`) or anywhere (`twos`). The result of this step generates the minimum among the accumulated time spent on removing cars by both methods, which also includes the cars yet to be processed.

The time complexity is O(n), where n is the length of the input string. This is because we iterate through the whole string in a single pass. The space complexity is O(1) as we only use a constant amount of extra space for the counters.

## A solution in C++

```cpp
int min_time_to_remove_illegal_goods(string s) {
    int ones = 0, twos = 0;
    for (char c : s) {
        if (c == '1') {
            twos += ones;
            ones++;
        }
    }
    return ones + min(ones, twos);
}
```
The algorithm:
1. Initialize two counters, `ones` and `twos`, to 0.
2. Iterate through the characters in the string.
3. If a character is '1', increment `ones` then add the current value of `ones` to `twos`.
4. At the end, return `ones + min(ones, twos)`.

Step 3 updates the count based on either removing the car from the left (`ones`) or anywhere (`twos`). The result of this step generates the minimum among the accumulated time spent on removing cars by both methods, which also includes the cars yet to be processed.

The time complexity is O(n), where n is the length of the input string. This is because we iterate through the whole string in a single pass. The space complexity is O(1) as we only use a constant amount of extra space for the counters.

## A solution in Python

```python
def min_time_to_remove_illegal_goods(s: str) -> int:
    ones = twos = 0
    for c in s:
        if c == '1':
            twos += ones
            ones += 1
    return ones + min(ones, twos)
```
The algorithm:
1. Initialize two counters, `ones` and `twos`, to 0.
2. Iterate through the characters in the string.
3. If a character is '1', increment `ones` then add the current value of `ones` to `twos`.
4. At the end, return `ones + min(ones, twos)`.

Step 3 updates the count based on either removing the car from the left (`ones`) or anywhere (`twos`). The result of this step generates the minimum among the accumulated time spent on removing cars by both methods, which also includes the cars yet to be processed.

The time complexity is O(n), where n is the length of the input string. This is because we iterate through the whole string in a single pass. The space complexity is O(1) as we only use a constant amount of extra space for the counters.

## A solution in Javascript

```javascript
function min_time_to_remove_illegal_goods(s) {
    let ones = 0, twos = 0;
    for (let c of s) {
        if (c === '1') {
            twos += ones;
            ones++;
        }
    }
    return ones + Math.min(ones, twos);
}
```
The algorithm:
1. Initialize two counters, `ones` and `twos`, to 0.
2. Iterate through the characters in the string.
3. If a character is '1', increment `ones` then add the current value of `ones` to `twos`.
4. At the end, return `ones + min(ones, twos)`.

Step 3 updates the count based on either removing the car from the left (`ones`) or anywhere (`twos`). The result of this step generates the minimum among the accumulated time spent on removing cars by both methods, which also includes the cars yet to be processed.

The time complexity is O(n), where n is the length of the input string. This is because we iterate through the whole string in a single pass. The space complexity is O(1) as we only use a constant amount of extra space for the counters.


# Unique Substrings With Equal Digit Frequency

- slug: unique-substrings-with-equal-digit-frequency
- difficulty: Medium

Given a digit string `s`, return _the number of **unique substrings** of_ `s` _where every digit appears the same number of times._

**Example 1:**

**Input:** s =  "1212 "
**Output:** 5
**Explanation:** The substrings that meet the requirements are  "1 ",  "2 ",  "12 ",  "21 ",  "1212 ".
Note that although the substring  "12 " appears twice, it is only counted once.

**Example 2:**

**Input:** s =  "12321 "
**Output:** 9
**Explanation:** The substrings that meet the requirements are  "1 ",  "2 ",  "3 ",  "12 ",  "23 ",  "32 ",  "21 ",  "123 ",  "321 ".

**Constraints:**

*   `1 <= s.length <= 1000`
*   `s` consists of digits.

## A solution in Java

```java
import java.util.*;

public boolean areNumbersIncreasing(String s) {
    Scanner scanner = new Scanner(s);
    ArrayList<Integer> numbers = new ArrayList<>();

    while (scanner.hasNext()) {
        if (scanner.hasNextInt()) {
            int num = scanner.nextInt();
            if (!numbers.isEmpty() && numbers.get(numbers.size() - 1) >= num) {
                return false;
            }
            numbers.add(num);
        } else {
            scanner.next();
        }
    }

    return true;
}
```
This algorithm iterates through the tokens of the input sentence (s). It checks each token to see if it is a number, using language-specific functions like isdigit for C++/Python, Scanner for Java, or isNaN for JavaScript. If the token is a number, the algorithm checks if it is strictly greater than the last number we encountered (if any). If it isn't strictly greater, the function returns `false`. At the end of the iterations, if no condition is met, it returns `true`, indicating all numbers in the sentence are in strictly increasing order.

## A solution in C++

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

bool areNumbersIncreasing(std::string s) {
    std::istringstream iss(s);
    std::string token;
    std::vector<int> numbers;

    while (iss >> token) {
        if (isdigit(token[0])) {
            int num = std::stoi(token);
            if (!numbers.empty() && numbers.back() >= num) {
                return false;
            }
            numbers.push_back(num);
        }
    }

    return true;
}
```
This algorithm iterates through the tokens of the input sentence (s). It checks each token to see if it is a number, using language-specific functions like isdigit for C++/Python, Scanner for Java, or isNaN for JavaScript. If the token is a number, the algorithm checks if it is strictly greater than the last number we encountered (if any). If it isn't strictly greater, the function returns `false`. At the end of the iterations, if no condition is met, it returns `true`, indicating all numbers in the sentence are in strictly increasing order.

## A solution in Python

```python
def are_numbers_increasing(s: str) -> bool:
    tokens = s.split()
    numbers = []

    for token in tokens:
        if token.isdigit():
            num = int(token)
            if numbers and numbers[-1] >= num:
                return False
            numbers.append(num)

    return True
```
This algorithm iterates through the tokens of the input sentence (s). It checks each token to see if it is a number, using language-specific functions like isdigit for C++/Python, Scanner for Java, or isNaN for JavaScript. If the token is a number, the algorithm checks if it is strictly greater than the last number we encountered (if any). If it isn't strictly greater, the function returns `false`. At the end of the iterations, if no condition is met, it returns `true`, indicating all numbers in the sentence are in strictly increasing order.

## A solution in Javascript

```javascript
function areNumbersIncreasing(s) {
    const tokens = s.split(" ");
    const numbers = [];

    for (const token of tokens) {
        if (!isNaN(token)) {
            const num = parseInt(token);
            if (numbers.length && numbers[numbers.length - 1] >= num) {
                return false;
            }
            numbers.push(num);
        }
    }

    return true;
}
```
This algorithm iterates through the tokens of the input sentence (s). It checks each token to see if it is a number, using language-specific functions like isdigit for C++/Python, Scanner for Java, or isNaN for JavaScript. If the token is a number, the algorithm checks if it is strictly greater than the last number we encountered (if any). If it isn't strictly greater, the function returns `false`. At the end of the iterations, if no condition is met, it returns `true`, indicating all numbers in the sentence are in strictly increasing order.


# Minimum Operations to Make the Array Alternating

- slug: minimum-operations-to-make-the-array-alternating
- difficulty: Medium

You are given a **0-indexed** array `nums` consisting of `n` positive integers.

The array `nums` is called **alternating** if:

*   `nums[i - 2] == nums[i]`, where `2 <= i <= n - 1`.
*   `nums[i - 1] != nums[i]`, where `1 <= i <= n - 1`.

In one **operation**, you can choose an index `i` and **change** `nums[i]` into **any** positive integer.

Return _the **minimum number of operations** required to make the array alternating_.

**Example 1:**

**Input:** nums = \[3,1,3,2,4,3\]
**Output:** 3
**Explanation:**
One way to make the array alternating is by converting it to \[3,1,3,**1**,**3**,**1**\].
The number of operations required in this case is 3.
It can be proven that it is not possible to make the array alternating in less than 3 operations.

**Example 2:**

**Input:** nums = \[1,2,2,2,2\]
**Output:** 2
**Explanation:**
One way to make the array alternating is by converting it to \[1,2,**1**,2,**1**\].
The number of operations required in this case is 2.
Note that the array cannot be converted to \[**2**,2,2,2,2\] because in this case nums\[0\] == nums\[1\] which violates the conditions of an alternating array.

**Constraints:**

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

## A solution in Java

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

public int countMaxOrSubsets(int[] nums) {
    int max_OR = 0;
    for(int num : nums) {
        max_OR |= num;
    }

    Set<Integer> OR_subsets = new HashSet<>();
    OR_subsets.add(0);

    for(int num : nums) {
        Set<Integer> tmp = new HashSet<>(OR_subsets);
        for(int x : OR_subsets) {
            tmp.add(x | num);
        }
        OR_subsets = tmp;
    }

    int count = 0;
    for(int x : OR_subsets) {
        if(x == max_OR) {
            count++;
        }
    }
    return count;
}
```
1. First, we calculate the maximum bitwise OR `max_OR` of the input array by using OR operation on all the elements of the array.
2. We will use a set `OR_subsets` to store the possible OR results.
3. We initialize the `OR_subsets` with the value 0 to start the OR combination.
4. In a loop over the input array, we create a temporary set `tmp` that is initialized with the previous calculated OR set `OR_subsets`.
5. Then for each element of nums, we perform OR operation with each element in the `OR_subsets`, and add that value to the temporary set `tmp`.
6. After calculating all possible subsets, we need to count the number of max_OR values that we have in the `OR_subsets`.
7. We return the count of different subsets with the maximum bitwise OR value.

## A solution in C++

```cpp
#include <vector>
#include <unordered_set>

int countMaxOrSubsets(std::vector<int>& nums) {
    int max_OR = 0;
    for(int num : nums) {
        max_OR |= num;
    }

    std::unordered_set<int> OR_subsets{0};
    for(int num : nums) {
        std::unordered_set<int> tmp = OR_subsets;
        for(int x : OR_subsets) {
            tmp.insert(x | num);
        }
        OR_subsets.swap(tmp);
    }

    return std::count(OR_subsets.begin(), OR_subsets.end(), max_OR);
}
```
1. First, we calculate the maximum bitwise OR `max_OR` of the input array by using OR operation on all the elements of the array.
2. We will use a set `OR_subsets` to store the possible OR results.
3. We initialize the `OR_subsets` with the value 0 to start the OR combination.
4. In a loop over the input array, we create a temporary set `tmp` that is initialized with the previous calculated OR set `OR_subsets`.
5. Then for each element of nums, we perform OR operation with each element in the `OR_subsets`, and add that value to the temporary set `tmp`.
6. After calculating all possible subsets, we need to count the number of max_OR values that we have in the `OR_subsets`.
7. We return the count of different subsets with the maximum bitwise OR value.

## A solution in Python

```python
def count_max_or_subsets(nums):
    max_OR = 0
    for num in nums:
        max_OR |= num

    OR_subsets = {0}
    for num in nums:
        tmp = OR_subsets.copy()
        for x in OR_subsets:
            tmp.add(x | num)
        OR_subsets = tmp

    return OR_subsets.count(max_OR)
```
1. First, we calculate the maximum bitwise OR `max_OR` of the input array by using OR operation on all the elements of the array.
2. We will use a set `OR_subsets` to store the possible OR results.
3. We initialize the `OR_subsets` with the value 0 to start the OR combination.
4. In a loop over the input array, we create a temporary set `tmp` that is initialized with the previous calculated OR set `OR_subsets`.
5. Then for each element of nums, we perform OR operation with each element in the `OR_subsets`, and add that value to the temporary set `tmp`.
6. After calculating all possible subsets, we need to count the number of max_OR values that we have in the `OR_subsets`.
7. We return the count of different subsets with the maximum bitwise OR value.

## A solution in Javascript

```javascript
function countMaxOrSubsets(nums) {
    let max_OR = 0;
    for(let num of nums) {
        max_OR |= num;
    }

    let OR_subsets = new Set([0]);

    for(let num of nums) {
        let tmp = new Set(OR_subsets);
        for(let x of OR_subsets) {
            tmp.add(x | num);
        }
        OR_subsets = tmp;
    }

    let count = 0;
    for(let x of OR_subsets) {
        if(x === max_OR) {
            count++;
        }
    }
    return count;
}
```
1. First, we calculate the maximum bitwise OR `max_OR` of the input array by using OR operation on all the elements of the array.
2. We will use a set `OR_subsets` to store the possible OR results.
3. We initialize the `OR_subsets` with the value 0 to start the OR combination.
4. In a loop over the input array, we create a temporary set `tmp` that is initialized with the previous calculated OR set `OR_subsets`.
5. Then for each element of nums, we perform OR operation with each element in the `OR_subsets`, and add that value to the temporary set `tmp`.
6. After calculating all possible subsets, we need to count the number of max_OR values that we have in the `OR_subsets`.
7. We return the count of different subsets with the maximum bitwise OR value.


# Removing Minimum Number of Magic Beans

- slug: removing-minimum-number-of-magic-beans
- difficulty: Medium

You are given an array of **positive** integers `beans`, where each integer represents the number of magic beans found in a particular magic bag.

**Remove** any number of beans (**possibly none**) from each bag such that the number of beans in each remaining **non-empty** bag (still containing **at least one** bean) is **equal**. Once a bean has been removed from a bag, you are **not** allowed to return it to any of the bags.

Return _the **minimum** number of magic beans that you have to remove_.

**Example 1:**

**Input:** beans = \[4,**1**,6,5\]
**Output:** 4
**Explanation:**
- We remove 1 bean from the bag with only 1 bean.
  This results in the remaining bags: \[4,**0**,6,5\]
- Then we remove 2 beans from the bag with 6 beans.
  This results in the remaining bags: \[4,0,**4**,5\]
- Then we remove 1 bean from the bag with 5 beans.
  This results in the remaining bags: \[4,0,4,**4**\]
We removed a total of 1 + 2 + 1 = 4 beans to make the remaining non-empty bags have an equal number of beans.
There are no other solutions that remove 4 beans or fewer.

**Example 2:**

**Input:** beans = \[**2**,10,**3**,**2**\]
**Output:** 7
**Explanation:**
- We remove 2 beans from one of the bags with 2 beans.
  This results in the remaining bags: \[**0**,10,3,2\]
- Then we remove 2 beans from the other bag with 2 beans.
  This results in the remaining bags: \[0,10,3,**0**\]
- Then we remove 3 beans from the bag with 3 beans.
  This results in the remaining bags: \[0,10,**0**,0\]
We removed a total of 2 + 2 + 3 = 7 beans to make the remaining non-empty bags have an equal number of beans.
There are no other solutions that removes 7 beans or fewer.

**Constraints:**

*   `1 <= beans.length <= 105`
*   `1 <= beans[i] <= 105`

## A solution in Java

```java
import java.util.*;

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

    int[] dist = new int[n + 1];
    Arrays.fill(dist, -1);
    PriorityQueue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
    dist[1] = 0;
    queue.offer(new int[]{1, 0});

    while (!queue.isEmpty()) {
        int[] curr = queue.poll();
        int v1 = curr[0], t1 = curr[1];

        if (v1 == n) {
            return t1;
        }

        for (int v2 : adj[v1]) {
            int t2 = t1 + time;
            int waiting = (t2 / change) % 2 == 1 ? change - (t2 % change) : 0;

            if (dist[v2] == -1 || dist[v2] > t2 + waiting) {
                if (dist[v2] != -1) {
                    queue.offer(new int[]{v2, dist[v2]});
                }
                dist[v2] = t2 + waiting;
                queue.offer(new int[]{v2, dist[v2]});
            }
        }
    }
    return -1;
}
```
The algorithm uses Dijkstra's shortest path algorithm with some modifications to take into account the waiting time at the vertices due to the traffic signal. It maintains a priority queue to store the vertices sorted by time taken to reach a vertex (including waiting time). We start from vertex 1 with time 0.

For each vertex, we iterate over its neighbors and calculate the time taken to reach the neighbor, adjusted for waiting. If this time is less than the previously calculated time (or the neighbor has not been visited yet), we update the time and push the old distance to the queue.

When we reach vertex n, we will have found our second minimum time as we have now encountered the vertex twice.

The time complexity of this algorithm is O(nlogn + m), where n is the number of vertices and m is the number of edges.

## A solution in C++

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

int second_minimum(int n, const std::vector<std::vector<int>>& edges, int time, int change) {
    std::vector<std::vector<int>> adj(n + 1);
    for (const auto& e : edges) {
        adj[e[0]].push_back(e[1]);
        adj[e[1]].push_back(e[0]);
    }

    std::vector<int> dist(n + 1, -1);
    std::priority_queue<int, std::vector<int>, std::greater<int>> q;
    dist[1] = 0;
    q.push(0);

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

        int v1 = cur >> 16;
        int t1 = cur & 0xffff;

        if (v1 == n) {
            return t1; // Found the second minimum
        }

        for (int v2 : adj[v1]) {
            int t2 = t1 + time;
            int waiting = (t2 / change) % 2 == 1 ? change - (t2 % change) : 0;

            if (dist[v2] == -1 || dist[v2] > t2 + waiting) {
                if (dist[v2] != -1)
                    q.push(dist[v2] << 16 | v2); // Push the old distance to find the second minimum one
                dist[v2] = t2 + waiting;
                q.push(dist[v2] << 16 | v2);
            }
        }
    }
    return -1;
}
```
The algorithm uses Dijkstra's shortest path algorithm with some modifications to take into account the waiting time at the vertices due to the traffic signal. It maintains a priority queue to store the vertices sorted by time taken to reach a vertex (including waiting time). We start from vertex 1 with time 0.

For each vertex, we iterate over its neighbors and calculate the time taken to reach the neighbor, adjusted for waiting. If this time is less than the previously calculated time (or the neighbor has not been visited yet), we update the time and push the old distance to the queue.

When we reach vertex n, we will have found our second minimum time as we have now encountered the vertex twice.

The time complexity of this algorithm is O(nlogn + m), where n is the number of vertices and m is the number of edges.

## A solution in Python

```python
import heapq

def second_minimum(n: int, edges: List[List[int]], time: int, change: int) -> int:
    adj = [[] for _ in range(n + 1)]
    for u, v in edges:
        adj[u].append(v)
        adj[v].append(u)

    dist = [-1] * (n + 1)
    queue = [(0, 1)]
    dist[1] = 0

    while queue:
        t1, v1 = heapq.heappop(queue)

        if v1 == n:
            return t1

        for v2 in adj[v1]:
            t2 = t1 + time
            waiting = change - (t2 % change) if (t2 // change) % 2 == 1 else 0

            if dist[v2] == -1 or dist[v2] > t2 + waiting:
                if dist[v2] != -1:
                    heapq.heappush(queue, (dist[v2], v2))
                dist[v2] = t2 + waiting
                heapq.heappush(queue, (dist[v2], v2))

    return -1
```
The algorithm uses Dijkstra's shortest path algorithm with some modifications to take into account the waiting time at the vertices due to the traffic signal. It maintains a priority queue to store the vertices sorted by time taken to reach a vertex (including waiting time). We start from vertex 1 with time 0.

For each vertex, we iterate over its neighbors and calculate the time taken to reach the neighbor, adjusted for waiting. If this time is less than the previously calculated time (or the neighbor has not been visited yet), we update the time and push the old distance to the queue.

When we reach vertex n, we will have found our second minimum time as we have now encountered the vertex twice.

The time complexity of this algorithm is O(nlogn + m), where n is the number of vertices and m is the number of edges.

## A solution in Javascript

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

    const dist = new Array(n + 1).fill(-1);
    const queue = [[0, 1]];
    dist[1] = 0;

    while (queue.length > 0) {
        queue.sort((a, b) => a[0] - b[0]);
        const [t1, v1] = queue.shift();

        if (v1 === n) {
            return t1;
        }

        for (const v2 of adj[v1]) {
            const t2 = t1 + time;
            const waiting = (t2 / change) % 2 === 1 ? change - (t2 % change) : 0;

            if (dist[v2] === -1 || dist[v2] > t2 + waiting) {
                if (dist[v2] !== -1) {
                    queue.push([dist[v2], v2]);
                }
                dist[v2] = t2 + waiting;
                queue.push([dist[v2], v2]);
            }
        }
    }

    return -1;
}
```
The algorithm uses Dijkstra's shortest path algorithm with some modifications to take into account the waiting time at the vertices due to the traffic signal. It maintains a priority queue to store the vertices sorted by time taken to reach a vertex (including waiting time). We start from vertex 1 with time 0.

For each vertex, we iterate over its neighbors and calculate the time taken to reach the neighbor, adjusted for waiting. If this time is less than the previously calculated time (or the neighbor has not been visited yet), we update the time and push the old distance to the queue.

When we reach vertex n, we will have found our second minimum time as we have now encountered the vertex twice.

The time complexity of this algorithm is O(nlogn + m), where n is the number of vertices and m is the number of edges.


# Maximum AND Sum of Array

- slug: maximum-and-sum-of-array
- difficulty: Hard

You are given an integer array `nums` of length `n` and an integer `numSlots` such that `2 * numSlots >= n`. There are `numSlots` slots numbered from `1` to `numSlots`.

You have to place all `n` integers into the slots such that each slot contains at **most** two numbers. The **AND sum** of a given placement is the sum of the **bitwise** `AND` of every number with its respective slot number.

*   For example, the **AND sum** of placing the numbers `[1, 3]` into slot `1` and `[4, 6]` into slot `2` is equal to `(1 AND 1) + (3 AND 1) + (4 AND 2) + (6 AND 2) = 1 + 1 + 0 + 2 = 4`.

Return _the maximum possible **AND sum** of_ `nums` _given_ `numSlots` _slots._

**Example 1:**

**Input:** nums = \[1,2,3,4,5,6\], numSlots = 3
**Output:** 9
**Explanation:** One possible placement is \[1, 4\] into slot 1, \[2, 6\] into slot 2, and \[3, 5\] into slot 3.
This gives the maximum AND sum of (1 AND 1) + (4 AND 1) + (2 AND 2) + (6 AND 2) + (3 AND 3) + (5 AND 3) = 1 + 0 + 2 + 2 + 3 + 1 = 9.

**Example 2:**

**Input:** nums = \[1,3,10,4,7,1\], numSlots = 9
**Output:** 24
**Explanation:** One possible placement is \[1, 1\] into slot 1, \[3\] into slot 3, \[4\] into slot 4, \[7\] into slot 7, and \[10\] into slot 9.
This gives the maximum AND sum of (1 AND 1) + (1 AND 1) + (3 AND 3) + (4 AND 4) + (7 AND 7) + (10 AND 9) = 1 + 1 + 3 + 4 + 7 + 8 = 24.
Note that slots 2, 5, 6, and 8 are empty which is permitted.

**Constraints:**

*   `n == nums.length`
*   `1 <= numSlots <= 9`
*   `1 <= n <= 2 * numSlots`
*   `1 <= nums[i] <= 15`

## A solution in Java

```java
public int maxAndSum(int[] nums, int numSlots, int idx, int used, int sum) {
    if (idx == nums.length) {
        return sum;
    }
    int max_sum = 0;
    for (int i = 1; i <= numSlots; ++i) {
        if ((used & (1 << (i - 1))) == 0) {
            int new_sum = sum + (nums[idx] & i);
            int new_used = (used | (1 << (i - 1)));
            max_sum = Math.max(max_sum, maxAndSum(nums, numSlots, idx + 1, new_used, new_sum));
            if (idx + 1 < nums.length) {
                new_sum = new_sum + (nums[idx + 1] & i);
                max_sum = Math.max(max_sum, maxAndSum(nums, numSlots, idx + 2, new_used, new_sum));
            }
        }
    }
    return max_sum;
}

public int maxAndSum(int[] nums, int numSlots) {
    return maxAndSum(nums, numSlots, 0, 0, 0);
}
```
The algorithm uses a recursive, brute-force approach to find the maximum AND sum for given numbers and slots. To achieve this, the algorithm iteratively places numbers in slots, taking into account the constraint that each slot can hold at most two numbers, and calculates the AND-sum.

Base case: If all elements of the nums list have been placed into slots, the total sum (sum) is returned, indicating the AND-sum for the current combination.

Recursive step: For each slot (i), if a number hasn't been placed into it yet (checked using bitmask `used`), place the current number in it, mark the slot as used and calculate the next AND-sum. If there is a next number in the nums list, place the pair of numbers in the same slot and calculate AND-sum accordingly.

The algorithm selects the maximum AND-sum for each combination along the way, until reaching the end of nums list. The maximum, thus, is then stored and returned as the maximum AND-sum.

The algorithm has the same implementation in all languages, with the only difference being the syntax and function names in respective languages. The time complexity of this algorithm is O(numSlots^n), as we exhaustively try every possible placement of numbers into slots.

## A solution in C++

```cpp
int maxAndSum(const vector<int>& nums, int numSlots, size_t idx, int used, int sum) {
    if (idx == nums.size()) {
        return sum;
    }
    int max_sum = 0;
    for (int i = 1; i <= numSlots; ++i) {
        if (!((1 << (i - 1)) & used)) {
            int new_sum = sum + (nums[idx] & i);
            int new_used = (used | (1 << (i - 1)));
            max_sum = max(max_sum, maxAndSum(nums, numSlots, idx + 1, new_used, new_sum));
            if (idx + 1 < nums.size()) {
                new_sum = new_sum + (nums[idx + 1] & i);
                max_sum = max(max_sum, maxAndSum(nums, numSlots, idx + 2, new_used, new_sum));
            }
        }
    }
    return max_sum;
}

int maxAndSum(vector<int>& nums, int numSlots) {
    return maxAndSum(nums, numSlots, 0, 0, 0);
}
```
The algorithm uses a recursive, brute-force approach to find the maximum AND sum for given numbers and slots. To achieve this, the algorithm iteratively places numbers in slots, taking into account the constraint that each slot can hold at most two numbers, and calculates the AND-sum.

Base case: If all elements of the nums list have been placed into slots, the total sum (sum) is returned, indicating the AND-sum for the current combination.

Recursive step: For each slot (i), if a number hasn't been placed into it yet (checked using bitmask `used`), place the current number in it, mark the slot as used and calculate the next AND-sum. If there is a next number in the nums list, place the pair of numbers in the same slot and calculate AND-sum accordingly.

The algorithm selects the maximum AND-sum for each combination along the way, until reaching the end of nums list. The maximum, thus, is then stored and returned as the maximum AND-sum.

The algorithm has the same implementation in all languages, with the only difference being the syntax and function names in respective languages. The time complexity of this algorithm is O(numSlots^n), as we exhaustively try every possible placement of numbers into slots.

## A solution in Python

```python
def max_and_sum(nums, num_slots, idx, used, sum):
    if idx == len(nums):
        return sum
    max_sum = 0
    for i in range(1, num_slots + 1):
        if not used & (1 << (i - 1)):
            new_sum = sum + (nums[idx] & i)
            new_used = used | (1 << (i - 1))
            max_sum = max(max_sum, max_and_sum(nums, num_slots, idx + 1, new_used, new_sum))
            if idx + 1 < len(nums):
                new_sum = new_sum + (nums[idx + 1] & i)
                max_sum = max(max_sum, max_and_sum(nums, num_slots, idx + 2, new_used, new_sum))
    return max_sum

def max_and_sum(nums, num_slots):
    return max_and_sum(nums, num_slots, 0, 0, 0)
```
The algorithm uses a recursive, brute-force approach to find the maximum AND sum for given numbers and slots. To achieve this, the algorithm iteratively places numbers in slots, taking into account the constraint that each slot can hold at most two numbers, and calculates the AND-sum.

Base case: If all elements of the nums list have been placed into slots, the total sum (sum) is returned, indicating the AND-sum for the current combination.

Recursive step: For each slot (i), if a number hasn't been placed into it yet (checked using bitmask `used`), place the current number in it, mark the slot as used and calculate the next AND-sum. If there is a next number in the nums list, place the pair of numbers in the same slot and calculate AND-sum accordingly.

The algorithm selects the maximum AND-sum for each combination along the way, until reaching the end of nums list. The maximum, thus, is then stored and returned as the maximum AND-sum.

The algorithm has the same implementation in all languages, with the only difference being the syntax and function names in respective languages. The time complexity of this algorithm is O(numSlots^n), as we exhaustively try every possible placement of numbers into slots.

## A solution in Javascript

```javascript
function maxAndSum(nums, numSlots, idx, used, sum) {
    if (idx === nums.length) {
        return sum;
    }
    let max_sum = 0;
    for (let i = 1; i <= numSlots; ++i) {
        if ((used & (1 << (i - 1))) === 0) {
            let new_sum = sum + (nums[idx] & i);
            let new_used = (used | (1 << (i - 1)));
            max_sum = Math.max(max_sum, maxAndSum(nums, numSlots, idx + 1, new_used, new_sum));
            if (idx + 1 < nums.length) {
                new_sum = new_sum + (nums[idx + 1] & i);
                max_sum = Math.max(max_sum, maxAndSum(nums, numSlots, idx + 2, new_used, new_sum));
            }
        }
    }
    return max_sum;
}

function maxAndSum(nums, numSlots) {
    return maxAndSum(nums, numSlots, 0, 0, 0);
}
```
The algorithm uses a recursive, brute-force approach to find the maximum AND sum for given numbers and slots. To achieve this, the algorithm iteratively places numbers in slots, taking into account the constraint that each slot can hold at most two numbers, and calculates the AND-sum.

Base case: If all elements of the nums list have been placed into slots, the total sum (sum) is returned, indicating the AND-sum for the current combination.

Recursive step: For each slot (i), if a number hasn't been placed into it yet (checked using bitmask `used`), place the current number in it, mark the slot as used and calculate the next AND-sum. If there is a next number in the nums list, place the pair of numbers in the same slot and calculate AND-sum accordingly.

The algorithm selects the maximum AND-sum for each combination along the way, until reaching the end of nums list. The maximum, thus, is then stored and returned as the maximum AND-sum.

The algorithm has the same implementation in all languages, with the only difference being the syntax and function names in respective languages. The time complexity of this algorithm is O(numSlots^n), as we exhaustively try every possible placement of numbers into slots.


# Remove All Ones With Row and Column Flips II

- slug: remove-all-ones-with-row-and-column-flips-ii
- difficulty: Medium

You are given a **0-indexed** `m x n` **binary** matrix `grid`.

In one operation, you can choose any `i` and `j` that meet the following conditions:

*   `0 <= i < m`
*   `0 <= j < n`
*   `grid[i][j] == 1`

and change the values of **all** cells in row `i` and column `j` to zero.

Return _the **minimum** number of operations needed to remove all_ `1`_'s from_ `grid`_._

**Example 1:**

**Input:** grid = \[\[1,1,1\],\[1,1,1\],\[0,1,0\]\]
**Output:** 2
**Explanation:**
In the first operation, change all cell values of row 1 and column 1 to zero.
In the second operation, change all cell values of row 0 and column 0 to zero.

**Example 2:**

**Input:** grid = \[\[0,1,0\],\[1,0,1\],\[0,1,0\]\]
**Output:** 2
**Explanation:**
In the first operation, change all cell values of row 1 and column 0 to zero.
In the second operation, change all cell values of row 2 and column 1 to zero.
Note that we cannot perform an operation using row 1 and column 1 because grid\[1\]\[1\] != 1.

**Example 3:**

**Input:** grid = \[\[0,0\],\[0,0\]\]
**Output:** 0
**Explanation:**
There are no 1's to remove so return 0.

**Constraints:**

*   `m == grid.length`
*   `n == grid[i].length`
*   `1 <= m, n <= 15`
*   `1 <= m * n <= 15`
*   `grid[i][j]` is either `0` or `1`.

## A solution in Java

```java
int nextBalanced(int n) {
    while (true) {
        n++;
        Map<Integer, Integer> digitCount = new HashMap<>();
        int temp = n;
        while (temp != 0) {
            digitCount.put(temp % 10, digitCount.getOrDefault(temp % 10, 0) + 1);
            temp /= 10;
        }
        boolean balanced = true;
        for (Map.Entry<Integer, Integer> entry : digitCount.entrySet()) {
            if (!entry.getKey().equals(entry.getValue())) {
                balanced = false;
                break;
            }
        }
        if (balanced) return n;
    }
}
```
The algorithm iterates through each number greater than the given number `n`, analyzes the count of each digit in the number, and checks its balance status.

In each iteration, we do the following steps:

1. Increment the number `n` by 1.
2. Count the occurrences of each digit using a map or dictionary to store the count.
3. Iterate through each key-value pair in the map, and if the key is equal to the value, it indicates that the digit count is balanced. If all pairs have this property, return the number as the result.

This algorithm will continue until it finds a numerically balanced integer, which it will return as a result. Note that it uses integer division, dictionaries or maps, and iteration over key-value pairs, which have small language-specific differences.

## A solution in C++

```cpp
int nextBalanced(int n) {
    while (true) {
        n++;
        std::map<int, int> digitCount;
        int temp = n;
        while (temp) {
            digitCount[temp % 10]++;
            temp /= 10;
        }
        bool balanced = true;
        for (const auto& p : digitCount) {
            if (p.first != p.second) {
                balanced = false;
                break;
            }
        }
        if (balanced) return n;
    }
}
```
The algorithm iterates through each number greater than the given number `n`, analyzes the count of each digit in the number, and checks its balance status.

In each iteration, we do the following steps:

1. Increment the number `n` by 1.
2. Count the occurrences of each digit using a map or dictionary to store the count.
3. Iterate through each key-value pair in the map, and if the key is equal to the value, it indicates that the digit count is balanced. If all pairs have this property, return the number as the result.

This algorithm will continue until it finds a numerically balanced integer, which it will return as a result. Note that it uses integer division, dictionaries or maps, and iteration over key-value pairs, which have small language-specific differences.

## A solution in Python

```python
def next_balanced(n):
    while True:
        n += 1
        digit_count = {}
        temp = n
        while temp:
            digit = temp % 10
            digit_count[digit] = digit_count.get(digit, 0) + 1
            temp //= 10
        balanced = all(k == v for k, v in digit_count.items())
        if balanced:
            return n
```
The algorithm iterates through each number greater than the given number `n`, analyzes the count of each digit in the number, and checks its balance status.

In each iteration, we do the following steps:

1. Increment the number `n` by 1.
2. Count the occurrences of each digit using a map or dictionary to store the count.
3. Iterate through each key-value pair in the map, and if the key is equal to the value, it indicates that the digit count is balanced. If all pairs have this property, return the number as the result.

This algorithm will continue until it finds a numerically balanced integer, which it will return as a result. Note that it uses integer division, dictionaries or maps, and iteration over key-value pairs, which have small language-specific differences.

## A solution in Javascript

```javascript
function nextBalanced(n) {
    while (true) {
        n++;
        const digitCount = new Map();
        let temp = n;
        while (temp !== 0) {
            const digit = temp % 10;
            digitCount.set(digit, (digitCount.get(digit) || 0) + 1);
            temp = Math.floor(temp / 10);
        }
        const balanced = [...digitCount.entries()].every(([k, v]) => k === v );
        if (balanced) return n;
    }
}
```
The algorithm iterates through each number greater than the given number `n`, analyzes the count of each digit in the number, and checks its balance status.

In each iteration, we do the following steps:

1. Increment the number `n` by 1.
2. Count the occurrences of each digit using a map or dictionary to store the count.
3. Iterate through each key-value pair in the map, and if the key is equal to the value, it indicates that the digit count is balanced. If all pairs have this property, return the number as the result.

This algorithm will continue until it finds a numerically balanced integer, which it will return as a result. Note that it uses integer division, dictionaries or maps, and iteration over key-value pairs, which have small language-specific differences.


# Count Equal and Divisible Pairs in an Array

- slug: count-equal-and-divisible-pairs-in-an-array
- difficulty: Easy

Given a **0-indexed** integer array `nums` of length `n` and an integer `k`, return _the **number of pairs**_ `(i, j)` _where_ `0 <= i < j < n`, _such that_ `nums[i] == nums[j]` _and_ `(i * j)` _is divisible by_ `k`.

**Example 1:**

**Input:** nums = \[3,1,2,2,2,1,3\], k = 2
**Output:** 4
**Explanation:**
There are 4 pairs that meet all the requirements:
- nums\[0\] == nums\[6\], and 0 \* 6 == 0, which is divisible by 2.
- nums\[2\] == nums\[3\], and 2 \* 3 == 6, which is divisible by 2.
- nums\[2\] == nums\[4\], and 2 \* 4 == 8, which is divisible by 2.
- nums\[3\] == nums\[4\], and 3 \* 4 == 12, which is divisible by 2.

**Example 2:**

**Input:** nums = \[1,2,3,4\], k = 1
**Output:** 0
**Explanation:** Since no value in nums is repeated, there are no pairs (i,j) that meet all the requirements.

**Constraints:**

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

## A solution in Java

```java
import java.util.*;

public int minMonths(int n, int[][] relations, int[] time) {
    int[] order = new int[n];
    for (int[] r : relations)
        order[r[1] - 1] = Math.max(order[r[1] - 1], r[0]);
    int totalTime = 0;
    for (int i = 0; i < n; i++)
        totalTime = Math.max(totalTime, time[i] + order[i]);
    return totalTime;
}
```
The algorithm starts by creating an array `order` to keep track of the maximum prerequisite course number for each course. For each relation, it updates the maximum prerequisite course number for the `nextCourse` with the `prevCourse`.

Next, go through each course, and calculate the total time needed to finish that course by adding the course's time plus the time of its maximum prerequisite course. Track the maximum time across all courses as `totalTime`.

Finally, return the maximum time `totalTime` as the minimum number of months needed to complete all courses.

## A solution in C++

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

int min_months(int n, std::vector<std::vector<int>>& relations, std::vector<int>& time) {
    std::vector<int> order(n, 0);
    for (auto& r : relations)
        order[r[1] - 1] = std::max(order[r[1] - 1], r[0]);
    int totalTime = 0;
    for (int i = 0; i < n; ++i)
        totalTime = std::max(totalTime, time[i] + order[i]);
    return totalTime;
}
```
The algorithm starts by creating an array `order` to keep track of the maximum prerequisite course number for each course. For each relation, it updates the maximum prerequisite course number for the `nextCourse` with the `prevCourse`.

Next, go through each course, and calculate the total time needed to finish that course by adding the course's time plus the time of its maximum prerequisite course. Track the maximum time across all courses as `totalTime`.

Finally, return the maximum time `totalTime` as the minimum number of months needed to complete all courses.

## A solution in Python

```python
def min_months(n, relations, time):
    order = [0] * n
    for r in relations:
        order[r[1] - 1] = max(order[r[1] - 1], r[0])
    totalTime = 0
    for i in range(n):
        totalTime = max(totalTime, time[i] + order[i])
    return totalTime
```
The algorithm starts by creating an array `order` to keep track of the maximum prerequisite course number for each course. For each relation, it updates the maximum prerequisite course number for the `nextCourse` with the `prevCourse`.

Next, go through each course, and calculate the total time needed to finish that course by adding the course's time plus the time of its maximum prerequisite course. Track the maximum time across all courses as `totalTime`.

Finally, return the maximum time `totalTime` as the minimum number of months needed to complete all courses.

## A solution in Javascript

```javascript
function minMonths(n, relations, time) {
    const order = new Array(n).fill(0);
    for (const r of relations)
        order[r[1] - 1] = Math.max(order[r[1] - 1], r[0]);
    let totalTime = 0;
    for (let i = 0; i < n; i++)
        totalTime = Math.max(totalTime, time[i] + order[i]);
    return totalTime;
}
```
The algorithm starts by creating an array `order` to keep track of the maximum prerequisite course number for each course. For each relation, it updates the maximum prerequisite course number for the `nextCourse` with the `prevCourse`.

Next, go through each course, and calculate the total time needed to finish that course by adding the course's time plus the time of its maximum prerequisite course. Track the maximum time across all courses as `totalTime`.

Finally, return the maximum time `totalTime` as the minimum number of months needed to complete all courses.


# Find Three Consecutive Integers That Sum to a Given Number

- slug: find-three-consecutive-integers-that-sum-to-a-given-number
- difficulty: Medium

Given an integer `num`, return _three consecutive integers (as a sorted array)_ _that **sum** to_ `num`. If `num` cannot be expressed as the sum of three consecutive integers, return _an **empty** array._

**Example 1:**

**Input:** num = 33
**Output:** \[10,11,12\]
**Explanation:** 33 can be expressed as 10 + 11 + 12 = 33.
10, 11, 12 are 3 consecutive integers, so we return \[10, 11, 12\].

**Example 2:**

**Input:** num = 4
**Output:** \[\]
**Explanation:** There is no way to express 4 as the sum of 3 consecutive integers.

**Constraints:**

*   `0 <= num <= 1015`

## A solution in Java

```java
import java.util.HashMap;

public boolean almostEquivalent(String word1, String word2) {
    HashMap<Character, Integer> freq1 = new HashMap<>();
    HashMap<Character, Integer> freq2 = new HashMap<>();

    for (char c : word1.toCharArray()) {
        freq1.put(c, freq1.getOrDefault(c, 0) + 1);
    }
    for (char c : word2.toCharArray()) {
        freq2.put(c, freq2.getOrDefault(c, 0) + 1);
    }
    for (char c = 'a'; c <= 'z'; c++) {
        if (Math.abs(freq1.getOrDefault(c, 0) - freq2.getOrDefault(c, 0)) > 3) {
            return false;
        }
    }

    return true;
}
```
The algorithm starts by initializing two frequency dictionaries (or unordered maps, hashmaps) freq1 and freq2 for tracking characters in word1 and word2, respectively. Then, it iterates through each character in both words to count character frequencies.

After the frequencies have been computed, the algorithm loops through each letter from 'a' to 'z' and checks if their corresponding frequencies' absolute differences are greater than 3. If so, it immediately returns false, as the words are not almost equivalent.

Finally, if no such differences are found, it returns true, meaning the words are almost equivalent.

## A solution in C++

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

bool almostEquivalent(std::string word1, std::string word2) {
    std::unordered_map<char, int> freq1, freq2;

    for (char c : word1) {
        freq1[c]++;
    }
    for (char c : word2) {
        freq2[c]++;
    }
    for (char c = 'a'; c <= 'z'; c++) {
        if (std::abs(freq1[c] - freq2[c]) > 3) {
            return false;
        }
    }

    return true;
}
```
The algorithm starts by initializing two frequency dictionaries (or unordered maps, hashmaps) freq1 and freq2 for tracking characters in word1 and word2, respectively. Then, it iterates through each character in both words to count character frequencies.

After the frequencies have been computed, the algorithm loops through each letter from 'a' to 'z' and checks if their corresponding frequencies' absolute differences are greater than 3. If so, it immediately returns false, as the words are not almost equivalent.

Finally, if no such differences are found, it returns true, meaning the words are almost equivalent.

## A solution in Python

```python
def almost_equivalent(word1, word2):
    freq1 = {}
    freq2 = {}

    for c in word1:
        freq1[c] = freq1.get(c, 0) + 1
    for c in word2:
        freq2[c] = freq2.get(c, 0) + 1

    for c in "abcdefghijklmnopqrstuvwxyz":
        if abs(freq1.get(c, 0) - freq2.get(c, 0)) > 3:
            return False

    return True
```
The algorithm starts by initializing two frequency dictionaries (or unordered maps, hashmaps) freq1 and freq2 for tracking characters in word1 and word2, respectively. Then, it iterates through each character in both words to count character frequencies.

After the frequencies have been computed, the algorithm loops through each letter from 'a' to 'z' and checks if their corresponding frequencies' absolute differences are greater than 3. If so, it immediately returns false, as the words are not almost equivalent.

Finally, if no such differences are found, it returns true, meaning the words are almost equivalent.

## A solution in Javascript

```javascript
function almostEquivalent(word1, word2) {
    let freq1 = {};
    let freq2 = {};

    for (let c of word1) {
        if (!freq1.hasOwnProperty(c)) {
            freq1[c] = 0;
        }
        freq1[c]++;
    }
    for (let c of word2) {
        if (!freq2.hasOwnProperty(c)) {
            freq2[c] = 0;
        }
        freq2[c]++;
    }

    for (let c = 'a'.charCodeAt(0); c <= 'z'.charCodeAt(0); c++) {
        let char = String.fromCharCode(c);
        if (Math.abs((freq1[char] || 0) - (freq2[char] || 0)) > 3) {
            return false;
        }
    }

    return true;
}
```
The algorithm starts by initializing two frequency dictionaries (or unordered maps, hashmaps) freq1 and freq2 for tracking characters in word1 and word2, respectively. Then, it iterates through each character in both words to count character frequencies.

After the frequencies have been computed, the algorithm loops through each letter from 'a' to 'z' and checks if their corresponding frequencies' absolute differences are greater than 3. If so, it immediately returns false, as the words are not almost equivalent.

Finally, if no such differences are found, it returns true, meaning the words are almost equivalent.


# Maximum Split of Positive Even Integers

- slug: maximum-split-of-positive-even-integers
- difficulty: Medium

You are given an integer `finalSum`. Split it into a sum of a **maximum** number of **unique** positive even integers.

*   For example, given `finalSum = 12`, the following splits are **valid** (unique positive even integers summing up to `finalSum`): `(12)`, `(2 + 10)`, `(2 + 4 + 6)`, and `(4 + 8)`. Among them, `(2 + 4 + 6)` contains the maximum number of integers. Note that `finalSum` cannot be split into `(2 + 2 + 4 + 4)` as all the numbers should be unique.

Return _a list of integers that represent a valid split containing a **maximum** number of integers_. If no valid split exists for `finalSum`, return _an **empty** list_. You may return the integers in **any** order.

**Example 1:**

**Input:** finalSum = 12
**Output:** \[2,4,6\]
**Explanation:** The following are valid splits: `(12)`, `(2 + 10)`, `(2 + 4 + 6)`, and `(4 + 8)`.
(2 + 4 + 6) has the maximum number of integers, which is 3. Thus, we return \[2,4,6\].
Note that \[2,6,4\], \[6,2,4\], etc. are also accepted.

**Example 2:**

**Input:** finalSum = 7
**Output:** \[\]
**Explanation:** There are no valid splits for the given finalSum.
Thus, we return an empty array.

**Example 3:**

**Input:** finalSum = 28
**Output:** \[6,8,2,12\]
**Explanation:** The following are valid splits: `(2 + 26)`, `(6 + 8 + 2 + 12)`, and `(4 + 24)`.
`(6 + 8 + 2 + 12)` has the maximum number of integers, which is 4. Thus, we return \[6,8,2,12\].
Note that \[10,2,4,12\], \[6,2,4,16\], etc. are also accepted.

**Constraints:**

*   `1 <= finalSum <= 1010`

## A solution in Java

```java
class Robot {
    int x, y, dir;
    Robot() { x = 0; y = 0; dir = 1; }
    void move(int steps) {
        switch (dir) {
            case 0: y += steps; break;
            case 1: x += steps; break;
            case 2: y -= steps; break;
            case 3: x -= steps; break;
        }
    }
    void turnLeft() { dir = (dir + 3) % 4; }
    void turnRight() { dir = (dir + 1) % 4; }
}
```
The robot is represented by a class with three attributes: x, y, and dir. x and y store the current position of the robot (initially (0, 0)), and dir stores the current direction the robot is facing (initially 1, which corresponds to "East"). The directions are represented as integer values, where 0 is "North", 1 is "East", 2 is "South", and 3 is "West".

The robot has three methods: move, turnLeft, and turnRight. The move method accepts the number of steps and updates the x and y coordinates based on the current direction. The turnLeft method updates the direction by subtracting 1 from the current direction (mod 4), which effectively turns 90 degrees to the left. The turnRight method updates the direction by adding 1 to the current direction (mod 4), which effectively turns 90 degrees to the right.

## A solution in C++

```cpp
class Robot {
public:
    int x, y, dir;
    Robot() : x(0), y(0), dir(1) {}
    void move(int steps) {
        switch (dir) {
            case 0: y += steps; break;
            case 1: x += steps; break;
            case 2: y -= steps; break;
            case 3: x -= steps; break;
        }
    }
    void turnLeft() { dir = (dir + 3) % 4; }
    void turnRight() { dir = (dir + 1) % 4; }
};
```
The robot is represented by a class with three attributes: x, y, and dir. x and y store the current position of the robot (initially (0, 0)), and dir stores the current direction the robot is facing (initially 1, which corresponds to "East"). The directions are represented as integer values, where 0 is "North", 1 is "East", 2 is "South", and 3 is "West".

The robot has three methods: move, turnLeft, and turnRight. The move method accepts the number of steps and updates the x and y coordinates based on the current direction. The turnLeft method updates the direction by subtracting 1 from the current direction (mod 4), which effectively turns 90 degrees to the left. The turnRight method updates the direction by adding 1 to the current direction (mod 4), which effectively turns 90 degrees to the right.

## A solution in Python

```python
class Robot:
    def __init__(self):
        self.x, self.y, self.dir = 0, 0, 1

    def move(self, steps):
        if self.dir == 0:
            self.y += steps
        elif self.dir == 1:
            self.x += steps
        elif self.dir == 2:
            self.y -= steps
        else:
            self.x -= steps

    def turn_left(self):
        self.dir = (self.dir + 3) % 4

    def turn_right(self):
        self.dir = (self.dir + 1) % 4
```
The robot is represented by a class with three attributes: x, y, and dir. x and y store the current position of the robot (initially (0, 0)), and dir stores the current direction the robot is facing (initially 1, which corresponds to "East"). The directions are represented as integer values, where 0 is "North", 1 is "East", 2 is "South", and 3 is "West".

The robot has three methods: move, turnLeft, and turnRight. The move method accepts the number of steps and updates the x and y coordinates based on the current direction. The turnLeft method updates the direction by subtracting 1 from the current direction (mod 4), which effectively turns 90 degrees to the left. The turnRight method updates the direction by adding 1 to the current direction (mod 4), which effectively turns 90 degrees to the right.

## A solution in Javascript

```javascript
class Robot {
    constructor() {
        this.x = 0;
        this.y = 0;
        this.dir = 1;
    }
    move(steps) {
        switch (this.dir) {
            case 0: this.y += steps; break;
            case 1: this.x += steps; break;
            case 2: this.y -= steps; break;
            case 3: this.x -= steps; break;
        }
    }
    turnLeft() { this.dir = (this.dir + 3) % 4; }
    turnRight() { this.dir = (this.dir + 1) % 4; }
}
```
The robot is represented by a class with three attributes: x, y, and dir. x and y store the current position of the robot (initially (0, 0)), and dir stores the current direction the robot is facing (initially 1, which corresponds to "East"). The directions are represented as integer values, where 0 is "North", 1 is "East", 2 is "South", and 3 is "West".

The robot has three methods: move, turnLeft, and turnRight. The move method accepts the number of steps and updates the x and y coordinates based on the current direction. The turnLeft method updates the direction by subtracting 1 from the current direction (mod 4), which effectively turns 90 degrees to the left. The turnRight method updates the direction by adding 1 to the current direction (mod 4), which effectively turns 90 degrees to the right.


# Count Good Triplets in an Array

- slug: count-good-triplets-in-an-array
- difficulty: Hard

You are given two **0-indexed** arrays `nums1` and `nums2` of length `n`, both of which are **permutations** of `[0, 1, ..., n - 1]`.

A **good triplet** is a set of `3` **distinct** values which are present in **increasing order** by position both in `nums1` and `nums2`. In other words, if we consider `pos1v` as the index of the value `v` in `nums1` and `pos2v` as the index of the value `v` in `nums2`, then a good triplet will be a set `(x, y, z)` where `0 <= x, y, z <= n - 1`, such that `pos1x < pos1y < pos1z` and `pos2x < pos2y < pos2z`.

Return _the **total number** of good triplets_.

**Example 1:**

**Input:** nums1 = \[2,0,1,3\], nums2 = \[0,1,2,3\]
**Output:** 1
**Explanation:**
There are 4 triplets (x,y,z) such that pos1x < pos1y < pos1z. They are (2,0,1), (2,0,3), (2,1,3), and (0,1,3).
Out of those triplets, only the triplet (0,1,3) satisfies pos2x < pos2y < pos2z. Hence, there is only 1 good triplet.

**Example 2:**

**Input:** nums1 = \[4,0,1,3,2\], nums2 = \[4,1,0,2,3\]
**Output:** 4
**Explanation:** The 4 good triplets are (4,0,3), (4,0,2), (4,1,3), and (4,1,2).

**Constraints:**

*   `n == nums1.length == nums2.length`
*   `3 <= n <= 105`
*   `0 <= nums1[i], nums2[i] <= n - 1`
*   `nums1` and `nums2` are permutations of `[0, 1, ..., n - 1]`.

## A solution in Java

```java
import java.util.*;

public class Solution {
    public int[] maxBeauty(int[][] items, int[] queries) {
        int[] sortedItems = new int[10001];
        for (int[] item : items) {
            sortedItems[item[0]] = Math.max(sortedItems[item[0]], item[1]);
        }

        for (int i = 1; i < sortedItems.length; i++) {
            sortedItems[i] = Math.max(sortedItems[i], sortedItems[i - 1]);
        }

        int[] result = new int[queries.length];
        for (int i = 0; i < queries.length; i++) {
            result[i] = sortedItems[queries[i]];
        }
        return result;
    }
}
```
The algorithm consists of first sorting the items by their price, while picking the maximum beauty for each price. An array of size 10001 is created to store the maximum beauty for each price, since the price range is [0, 10000].

After sorting the items, we iterate through the sorted array to find the maximum beauty for a range of prices up to the specific index. This allows us to easily answer the queries, since now we can directly look up the maximum beauty for items up to a specific price.

Finally, we iterate through the queries, and for each query, we find the maximum beauty for the given price by accessing the result from the previously computed sorted array. This gives us the answer for each query, which we return as an array of answers in the same order as the queries were given.

## A solution in C++

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

vector<int> maxBeauty(vector<vector<int>>& items, vector<int>& queries) {
    vector<int> sortedItems(10001, 0);
    for (auto& item : items) {
        sortedItems[item[0]] = max(sortedItems[item[0]], item[1]);
    }

    for (int i = 1; i < sortedItems.size(); ++i) {
        sortedItems[i] = max(sortedItems[i], sortedItems[i-1]);
    }

    vector<int> result;
    for (int query : queries) {
        result.push_back(sortedItems[query]);
    }
    return result;
}
```
The algorithm consists of first sorting the items by their price, while picking the maximum beauty for each price. An array of size 10001 is created to store the maximum beauty for each price, since the price range is [0, 10000].

After sorting the items, we iterate through the sorted array to find the maximum beauty for a range of prices up to the specific index. This allows us to easily answer the queries, since now we can directly look up the maximum beauty for items up to a specific price.

Finally, we iterate through the queries, and for each query, we find the maximum beauty for the given price by accessing the result from the previously computed sorted array. This gives us the answer for each query, which we return as an array of answers in the same order as the queries were given.

## A solution in Python

```python
def max_beauty(items, queries):
    sorted_items = [0] * 10001
    for price, beauty in items:
        sorted_items[price] = max(sorted_items[price], beauty)

    for i in range(1, len(sorted_items)):
        sorted_items[i] = max(sorted_items[i], sorted_items[i - 1])

    return [sorted_items[query] for query in queries]
```
The algorithm consists of first sorting the items by their price, while picking the maximum beauty for each price. An array of size 10001 is created to store the maximum beauty for each price, since the price range is [0, 10000].

After sorting the items, we iterate through the sorted array to find the maximum beauty for a range of prices up to the specific index. This allows us to easily answer the queries, since now we can directly look up the maximum beauty for items up to a specific price.

Finally, we iterate through the queries, and for each query, we find the maximum beauty for the given price by accessing the result from the previously computed sorted array. This gives us the answer for each query, which we return as an array of answers in the same order as the queries were given.

## A solution in Javascript

```javascript
function maxBeauty(items, queries) {
    let sortedItems = new Array(10001).fill(0);
    for (let item of items) {
        sortedItems[item[0]] = Math.max(sortedItems[item[0]], item[1]);
    }

    for (let i = 1; i < sortedItems.length; i++) {
        sortedItems[i] = Math.max(sortedItems[i], sortedItems[i - 1]);
    }

    return queries.map(query => sortedItems[query]);
}
```
The algorithm consists of first sorting the items by their price, while picking the maximum beauty for each price. An array of size 10001 is created to store the maximum beauty for each price, since the price range is [0, 10000].

After sorting the items, we iterate through the sorted array to find the maximum beauty for a range of prices up to the specific index. This allows us to easily answer the queries, since now we can directly look up the maximum beauty for items up to a specific price.

Finally, we iterate through the queries, and for each query, we find the maximum beauty for the given price by accessing the result from the previously computed sorted array. This gives us the answer for each query, which we return as an array of answers in the same order as the queries were given.


# Count Integers With Even Digit Sum

- slug: count-integers-with-even-digit-sum
- difficulty: Easy

Given a positive integer `num`, return _the number of positive integers **less than or equal to**_ `num` _whose digit sums are **even**_.

The **digit sum** of a positive integer is the sum of all its digits.

**Example 1:**

**Input:** num = 4
**Output:** 2
**Explanation:**
The only integers less than or equal to 4 whose digit sums are even are 2 and 4.

**Example 2:**

**Input:** num = 30
**Output:** 14
**Explanation:**
The 14 integers less than or equal to 30 whose digit sums are even are
2, 4, 6, 8, 11, 13, 15, 17, 19, 20, 22, 24, 26, and 28.

**Constraints:**

*   `1 <= num <= 1000`

## A solution in Java

```java
import java.util.Arrays;

public int maxTasks(int[] tasks, int[] workers, int pills, int strength) {
    Arrays.sort(tasks);
    Arrays.sort(workers);
    int taskIndex = 0;
    int pillIndex = pills;
    int completedTasks = 0;

    for (int workerStrength : workers) {
        while (pillIndex > 0 && workerStrength + strength >= tasks[taskIndex]) {
            workerStrength += strength;
            --pillIndex;
        }

        if (workerStrength >= tasks[taskIndex]) {
            ++taskIndex;
            ++completedTasks;
        }

        if (taskIndex >= tasks.length) {
            break;
        }
    }

    return completedTasks;
}
```
1. First, we sort both the tasks and the workers arrays in increasing order.
2. We initialize variables: taskIndex for iterating through the tasks array, pillIndex to keep track of the available pills, and completedTasks to count the number of tasks completed.
3. Next, we iterate through the workers array, each time checking if the current worker's strength is sufficient to complete the current task by comparing it with the task's strength requirement.
4. If the worker's strength is not sufficient and we still have pills available, we increment the worker's strength by "strength" (the strength added by one pill) and decrement the number of available pills.
5. If the worker's strength is now sufficient to complete the task, we increment the task index and the completed tasks counter.
6. We stop the loop if all tasks have been completed.
7. Finally, we return the completedTasks counter.

## A solution in C++

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

int maxTasks(std::vector<int>& tasks, std::vector<int>& workers, int pills, int strength) {
    std::sort(tasks.begin(), tasks.end());
    std::sort(workers.begin(), workers.end());
    int taskIndex = 0;
    int pillIndex = pills;
    int completedTasks = 0;

    for (int workerStrength : workers) {
        while (pillIndex > 0 && workerStrength + strength >= tasks[taskIndex]) {
            workerStrength += strength;
            --pillIndex;
        }

        if (workerStrength >= tasks[taskIndex]) {
            ++taskIndex;
            ++completedTasks;
        }

        if (taskIndex >= tasks.size()) {
            break;
        }
    }

    return completedTasks;
}
```
1. First, we sort both the tasks and the workers arrays in increasing order.
2. We initialize variables: taskIndex for iterating through the tasks array, pillIndex to keep track of the available pills, and completedTasks to count the number of tasks completed.
3. Next, we iterate through the workers array, each time checking if the current worker's strength is sufficient to complete the current task by comparing it with the task's strength requirement.
4. If the worker's strength is not sufficient and we still have pills available, we increment the worker's strength by "strength" (the strength added by one pill) and decrement the number of available pills.
5. If the worker's strength is now sufficient to complete the task, we increment the task index and the completed tasks counter.
6. We stop the loop if all tasks have been completed.
7. Finally, we return the completedTasks counter.

## A solution in Python

```python
def max_tasks(tasks, workers, pills, strength):
    tasks.sort()
    workers.sort()
    task_index = 0
    pill_index = pills
    completed_tasks = 0

    for worker_strength in workers:
        while pill_index > 0 and worker_strength + strength >= tasks[task_index]:
            worker_strength += strength
            pill_index -= 1

        if worker_strength >= tasks[task_index]:
            task_index += 1
            completed_tasks += 1

        if task_index >= len(tasks):
            break

    return completed_tasks
```
1. First, we sort both the tasks and the workers arrays in increasing order.
2. We initialize variables: taskIndex for iterating through the tasks array, pillIndex to keep track of the available pills, and completedTasks to count the number of tasks completed.
3. Next, we iterate through the workers array, each time checking if the current worker's strength is sufficient to complete the current task by comparing it with the task's strength requirement.
4. If the worker's strength is not sufficient and we still have pills available, we increment the worker's strength by "strength" (the strength added by one pill) and decrement the number of available pills.
5. If the worker's strength is now sufficient to complete the task, we increment the task index and the completed tasks counter.
6. We stop the loop if all tasks have been completed.
7. Finally, we return the completedTasks counter.

## A solution in Javascript

```javascript
function maxTasks(tasks, workers, pills, strength) {
    tasks.sort((a, b) => a - b);
    workers.sort((a, b) => a - b);
    let taskIndex = 0;
    let pillIndex = pills;
    let completedTasks = 0;

    for (const workerStrength of workers) {
        while (pillIndex > 0 && workerStrength + strength >= tasks[taskIndex]) {
            workerStrength += strength;
            --pillIndex;
        }

        if (workerStrength >= tasks[taskIndex]) {
            ++taskIndex;
            ++completedTasks;
        }

        if (taskIndex >= tasks.length) {
            break;
        }
    }

    return completedTasks;
}
```
1. First, we sort both the tasks and the workers arrays in increasing order.
2. We initialize variables: taskIndex for iterating through the tasks array, pillIndex to keep track of the available pills, and completedTasks to count the number of tasks completed.
3. Next, we iterate through the workers array, each time checking if the current worker's strength is sufficient to complete the current task by comparing it with the task's strength requirement.
4. If the worker's strength is not sufficient and we still have pills available, we increment the worker's strength by "strength" (the strength added by one pill) and decrement the number of available pills.
5. If the worker's strength is now sufficient to complete the task, we increment the task index and the completed tasks counter.
6. We stop the loop if all tasks have been completed.
7. Finally, we return the completedTasks counter.


# Merge Nodes in Between Zeros

- slug: merge-nodes-in-between-zeros
- difficulty: Medium

You are given the `head` of a linked list, which contains a series of integers **separated** by `0`'s. The **beginning** and **end** of the linked list will have `Node.val == 0`.

For **every** two consecutive `0`'s, **merge** all the nodes lying in between them into a single node whose value is the **sum** of all the merged nodes. The modified list should not contain any `0`'s.

Return _the_ `head` _of the modified linked list_.

**Example 1:**

**Input:** head = \[0,3,1,0,4,5,2,0\]
**Output:** \[4,11\]
**Explanation:**
The above figure represents the given linked list. The modified list contains
- The sum of the nodes marked in green: 3 + 1 = 4.
- The sum of the nodes marked in red: 4 + 5 + 2 = 11.

**Example 2:**

**Input:** head = \[0,1,0,3,0,2,2,0\]
**Output:** \[1,3,4\]
**Explanation:**
The above figure represents the given linked list. The modified list contains
- The sum of the nodes marked in green: 1 = 1.
- The sum of the nodes marked in red: 3 = 3.
- The sum of the nodes marked in yellow: 2 + 2 = 4.

**Constraints:**

*   The number of nodes in the list is in the range `[3, 2 * 105]`.
*   `0 <= Node.val <= 1000`
*   There are **no** two consecutive nodes with `Node.val == 0`.
*   The **beginning** and **end** of the linked list have `Node.val == 0`.

## A solution in Java

```java
public int smallestIndex(int[] nums) {
    for (int i = 0; i < nums.length; i++) {
        if (i % 10 == nums[i]) {
            return i;
        }
    }
    return -1;
}
```
We need to find the smallest index i such that i % 10 is equal to nums[i]. To achieve this, we simply iterate through the array using a for loop. For each index i, we calculate i % 10 and compare it with nums[i]. If i % 10 is equal to nums[i], we return the index i. If no such index exists, we return -1. All language implementations follow similar logic.

## A solution in C++

```cpp
int smallestIndex(vector<int>& nums) {
    for (int i = 0; i < nums.size(); i++) {
        if (i % 10 == nums[i]) {
            return i;
        }
    }
    return -1;
}
```
We need to find the smallest index i such that i % 10 is equal to nums[i]. To achieve this, we simply iterate through the array using a for loop. For each index i, we calculate i % 10 and compare it with nums[i]. If i % 10 is equal to nums[i], we return the index i. If no such index exists, we return -1. All language implementations follow similar logic.

## A solution in Python

```python
def smallest_index(nums):
    for i in range(len(nums)):
        if i % 10 == nums[i]:
            return i
    return -1
```
We need to find the smallest index i such that i % 10 is equal to nums[i]. To achieve this, we simply iterate through the array using a for loop. For each index i, we calculate i % 10 and compare it with nums[i]. If i % 10 is equal to nums[i], we return the index i. If no such index exists, we return -1. All language implementations follow similar logic.

## A solution in Javascript

```javascript
function smallestIndex(nums) {
    for (let i = 0; i < nums.length; i++) {
        if (i % 10 === nums[i]) {
            return i;
        }
    }
    return -1;
}
```
We need to find the smallest index i such that i % 10 is equal to nums[i]. To achieve this, we simply iterate through the array using a for loop. For each index i, we calculate i % 10 and compare it with nums[i]. If i % 10 is equal to nums[i], we return the index i. If no such index exists, we return -1. All language implementations follow similar logic.


# Construct String With Repeat Limit

- slug: construct-string-with-repeat-limit
- difficulty: Medium

You are given a string `s` and an integer `repeatLimit`. Construct a new string `repeatLimitedString` using the characters of `s` such that no letter appears **more than** `repeatLimit` times **in a row**. You do **not** have to use all characters from `s`.

Return _the **lexicographically largest**_ `repeatLimitedString` _possible_.

A string `a` is **lexicographically larger** than a string `b` if in the first position where `a` and `b` differ, string `a` has a letter that appears later in the alphabet than the corresponding letter in `b`. If the first `min(a.length, b.length)` characters do not differ, then the longer string is the lexicographically larger one.

**Example 1:**

**Input:** s =  "cczazcc ", repeatLimit = 3
**Output:**  "zzcccac "
**Explanation:** We use all of the characters from s to construct the repeatLimitedString  "zzcccac ".
The letter 'a' appears at most 1 time in a row.
The letter 'c' appears at most 3 times in a row.
The letter 'z' appears at most 2 times in a row.
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
The string is the lexicographically largest repeatLimitedString possible so we return  "zzcccac ".
Note that the string  "zzcccca " is lexicographically larger but the letter 'c' appears more than 3 times in a row, so it is not a valid repeatLimitedString.

**Example 2:**

**Input:** s =  "aababab ", repeatLimit = 2
**Output:**  "bbabaa "
**Explanation:** We use only some of the characters from s to construct the repeatLimitedString  "bbabaa ".
The letter 'a' appears at most 2 times in a row.
The letter 'b' appears at most 2 times in a row.
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
The string is the lexicographically largest repeatLimitedString possible so we return  "bbabaa ".
Note that the string  "bbabaaa " is lexicographically larger but the letter 'a' appears more than 2 times in a row, so it is not a valid repeatLimitedString.

**Constraints:**

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

## A solution in Java

```java
import java.util.LinkedList;

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

public int[] criticalDistance(ListNode head) {
    int minDistance = Integer.MAX_VALUE, maxDistance = Integer.MIN_VALUE;
    int lastCP = -1, index = 0;

    for(ListNode current = head.next; current != null && current.next != null; current = current.next) {
        if ((current.val > current.next.val && current.val > current.prev.val) ||
            (current.val < current.next.val && current.val < current.prev.val)) {

            if (lastCP != -1) {
                minDistance = Math.min(minDistance, index - lastCP);
                maxDistance = Math.max(maxDistance, index - lastCP);
            }
            lastCP = index;
        }
        index++;
    }

    if (minDistance != Integer.MAX_VALUE) {
        return new int[]{minDistance, maxDistance};
    }
    return new int[]{-1, -1};
}
```
1. Initialize minDistance, maxDistance, lastCP (last critical point), and index.
2. Loop through the list starting from the second element (since the head can't be a critical point) and check if it's a local minima or maxima.
3. If current node is a critical point and not the first one, we calculate the distance between current and last critical points, and update the min and max distances accordingly.
4. After looping through the list, if minDistance isn't infinity, we return the min and max distances; otherwise, we return [-1, -1] as there were no critical points found.

## A solution in C++

```cpp
#include <climits>
#include <vector>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(NULL) {}
};

std::vector<int> criticalDistance(ListNode* head) {
    int minDistance = INT_MAX, maxDistance = INT_MIN;
    int lastCP = -1, index = 0;

    for(ListNode* current = head->next; current && current->next; current = current->next) {
        if ((current->val > current->next->val && current->val > current->prev->val) ||
            (current->val < current->next->val && current->val < current->prev->val)) {

            if (lastCP != -1) {
                minDistance = std::min(minDistance, index - lastCP);
                maxDistance = std::max(maxDistance, index - lastCP);
            }
            lastCP = index;
        }
        index++;
    }

    if (minDistance != INT_MAX) {
        return {minDistance, maxDistance};
    }
    return {-1, -1};
}
```
1. Initialize minDistance, maxDistance, lastCP (last critical point), and index.
2. Loop through the list starting from the second element (since the head can't be a critical point) and check if it's a local minima or maxima.
3. If current node is a critical point and not the first one, we calculate the distance between current and last critical points, and update the min and max distances accordingly.
4. After looping through the list, if minDistance isn't infinity, we return the min and max distances; otherwise, we return [-1, -1] as there were no critical points found.

## A solution in Python

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

def critical_distance(head):
    min_distance, max_distance = float('inf'), float('-inf')
    last_cp, index = -1, 0
    current = head.next

    while current and current.next:
        if (current.val > current.next.val and current.val > current.prev.val) or \
           (current.val < current.next.val and current.val < current.prev.val):

            if last_cp != -1:
                min_distance = min(min_distance, index - last_cp)
                max_distance = max(max_distance, index - last_cp)
            last_cp = index

        current = current.next
        index += 1

    if min_distance != float('inf'):
        return [min_distance, max_distance]
    return [-1, -1]
```
1. Initialize minDistance, maxDistance, lastCP (last critical point), and index.
2. Loop through the list starting from the second element (since the head can't be a critical point) and check if it's a local minima or maxima.
3. If current node is a critical point and not the first one, we calculate the distance between current and last critical points, and update the min and max distances accordingly.
4. After looping through the list, if minDistance isn't infinity, we return the min and max distances; otherwise, we return [-1, -1] as there were no critical points found.

## A solution in Javascript

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

function criticalDistance(head) {
    let minDistance = Infinity, maxDistance = -Infinity;
    let lastCP = -1, index = 0;

    for(let current = head.next; current && current.next; current = current.next) {
        if ((current.val > current.next.val && current.val > current.prev.val) ||
            (current.val < current.next.val && current.val < current.prev.val)) {

            if (lastCP !== -1) {
                minDistance = Math.min(minDistance, index - lastCP);
                maxDistance = Math.max(maxDistance, index - lastCP);
            }
            lastCP = index;
        }
        index++;
    }

    if (minDistance !== Infinity) {
        return [minDistance, maxDistance];
    }
    return [-1, -1];
}
```
1. Initialize minDistance, maxDistance, lastCP (last critical point), and index.
2. Loop through the list starting from the second element (since the head can't be a critical point) and check if it's a local minima or maxima.
3. If current node is a critical point and not the first one, we calculate the distance between current and last critical points, and update the min and max distances accordingly.
4. After looping through the list, if minDistance isn't infinity, we return the min and max distances; otherwise, we return [-1, -1] as there were no critical points found.


# Count Array Pairs Divisible by K

- slug: count-array-pairs-divisible-by-k
- difficulty: Hard

Given a **0-indexed** integer array `nums` of length `n` and an integer `k`, return _the **number of pairs**_ `(i, j)` _such that:_

*   `0 <= i < j <= n - 1` _and_
*   `nums[i] * nums[j]` _is divisible by_ `k`.

**Example 1:**

**Input:** nums = \[1,2,3,4,5\], k = 2
**Output:** 7
**Explanation:**
The 7 pairs of indices whose corresponding products are divisible by 2 are
(0, 1), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), and (3, 4).
Their products are 2, 4, 6, 8, 10, 12, and 20 respectively.
Other pairs such as (0, 2) and (2, 4) have products 3 and 15 respectively, which are not divisible by 2.

**Example 2:**

**Input:** nums = \[1,2,3,4\], k = 5
**Output:** 0
**Explanation:** There does not exist any pair of indices whose corresponding product is divisible by 5.

**Constraints:**

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

## A solution in Java

```java
public int minOperations(int[] nums, int start, int goal) {
    Set<Integer> seen = new HashSet<>();
    Queue<Integer> queue = new LinkedList<>();
    seen.add(start);
    queue.offer(start);
    int level = 0;

    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int x = queue.poll();
            if (x == goal) return level;
            for (int num : nums) {
                int next = x + num;
                if (next >= 0 && next <= 1000 && !seen.contains(next)) {
                    seen.add(next);
                    queue.offer(next);
                }
            }
        }
        level++;
    }
    return -1;
}
```
The algorithm is a breadth-first search (BFS) based solution. We maintain a queue to keep track of the potential next values of `x`. Initially, `x=start`, and we perform the operation on it using each element of `nums`. We calculate the new value of `x` and add it to the queue if it meets the condition (0 <= next <= 1000) and is not in the seen set. We perform this process level-wise, incrementing the level after each iteration.

If we encounter the `goal` value during the BFS, we have reached the minimum number of operations needed, and we return the current level. If the BFS completes, and we have not found the `goal`, we return -1 as it is not possible to obtain `goal` through the provided operations.

## A solution in C++

```cpp
int minOperations(vector<int>& nums, int start, int goal) {
    unordered_set<int> seen = {start};
    queue<int> q = {start};
    int level = 0;

    while (!q.empty()) {
        int size = q.size();
        for (int i = 0; i < size; ++i) {
            int x = q.front(); q.pop();
            if (x == goal) return level;
            for (int num : nums) {
                int next = x + num;
                if (next >= 0 && next <= 1000 && seen.count(next) == 0) {
                    seen.insert(next);
                    q.push(next);
                }
            }
        }
        ++level;
    }
    return -1;
}
```
The algorithm is a breadth-first search (BFS) based solution. We maintain a queue to keep track of the potential next values of `x`. Initially, `x=start`, and we perform the operation on it using each element of `nums`. We calculate the new value of `x` and add it to the queue if it meets the condition (0 <= next <= 1000) and is not in the seen set. We perform this process level-wise, incrementing the level after each iteration.

If we encounter the `goal` value during the BFS, we have reached the minimum number of operations needed, and we return the current level. If the BFS completes, and we have not found the `goal`, we return -1 as it is not possible to obtain `goal` through the provided operations.

## A solution in Python

```python
from collections import deque

def minOperations(nums, start, goal):
    seen = {start}
    q = deque([start])
    level = 0

    while q:
        size = len(q)
        for i in range(size):
            x = q.popleft()
            if x == goal:
                return level
            for num in nums:
                next_x = x + num
                if 0 <= next_x <= 1000 and next_x not in seen:
                    seen.add(next_x)
                    q.append(next_x)
        level += 1

    return -1
```
The algorithm is a breadth-first search (BFS) based solution. We maintain a queue to keep track of the potential next values of `x`. Initially, `x=start`, and we perform the operation on it using each element of `nums`. We calculate the new value of `x` and add it to the queue if it meets the condition (0 <= next <= 1000) and is not in the seen set. We perform this process level-wise, incrementing the level after each iteration.

If we encounter the `goal` value during the BFS, we have reached the minimum number of operations needed, and we return the current level. If the BFS completes, and we have not found the `goal`, we return -1 as it is not possible to obtain `goal` through the provided operations.

## A solution in Javascript

```javascript
function minOperations(nums, start, goal) {
    const seen = new Set([start]);
    const queue = [start];
    let level = 0;

    while (queue.length > 0) {
        const size = queue.length;
        for (let i = 0; i < size; i++) {
            const x = queue.shift();
            if (x === goal) return level;
            for (const num of nums) {
                const next = x + num;
                if (next >= 0 && next <= 1000 && !seen.has(next)) {
                    seen.add(next);
                    queue.push(next);
                }
            }
        }
        level++;
    }
    return -1;
}
```
The algorithm is a breadth-first search (BFS) based solution. We maintain a queue to keep track of the potential next values of `x`. Initially, `x=start`, and we perform the operation on it using each element of `nums`. We calculate the new value of `x` and add it to the queue if it meets the condition (0 <= next <= 1000) and is not in the seen set. We perform this process level-wise, incrementing the level after each iteration.

If we encounter the `goal` value during the BFS, we have reached the minimum number of operations needed, and we return the current level. If the BFS completes, and we have not found the `goal`, we return -1 as it is not possible to obtain `goal` through the provided operations.