# Lowest Common Ancestor of a Binary Tree IV

- slug: lowest-common-ancestor-of-a-binary-tree-iv
- difficulty: Medium

Given the `root` of a binary tree and an array of `TreeNode` objects `nodes`, return _the lowest common ancestor (LCA) of **all the nodes** in_ `nodes`. All the nodes will exist in the tree, and all values of the tree's nodes are **unique**.

Extending the **[definition of LCA on Wikipedia](https://en.wikipedia.org/wiki/Lowest_common_ancestor)**: "The lowest common ancestor of `n` nodes `p1`, `p2`, ..., `pn` in a binary tree `T` is the lowest node that has every `pi` as a **descendant** (where we allow **a node to be a descendant of itself**) for every valid `i` ". A **descendant** of a node `x` is a node `y` that is on the path from node `x` to some leaf node.

**Example 1:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], nodes = \[4,7\]
**Output:** 2
**Explanation:** The lowest common ancestor of nodes 4 and 7 is node 2.

**Example 2:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], nodes = \[1\]
**Output:** 1
**Explanation:** The lowest common ancestor of a single node is the node itself.

**Example 3:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], nodes = \[7,6,2,4\]
**Output:** 5
**Explanation:** The lowest common ancestor of the nodes 7, 6, 2, and 4 is node 5.

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 104]`.
*   `-109 <= Node.val <= 109`
*   All `Node.val` are **unique**.
*   All `nodes[i]` will exist in the tree.
*   All `nodes[i]` are distinct.

## A solution in Java

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

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode[] nodes) {
    if (root == null || Arrays.asList(nodes).contains(root))
        return root;
    TreeNode left = lowestCommonAncestor(root.left, nodes);
    TreeNode right = lowestCommonAncestor(root.right, nodes);
    if (left != null && right != null)
        return root;
    return left != null ? left : right;
}
```
The algorithm used here is a recursive depth-first search approach. We start at the given root node and make a recursive call for both left and right subtrees. If the current node is null or it exists in the given input array, we return the current node.

Once the left and right recursive calls are completed, we check if left and right are not null, which means we have found at least two target nodes in both the subtrees. In that case, the current node is the LCA we are looking for, so return it. If one of the left or right is null, then we return the one which is not null (i.e., has the target node(s) as its descendant).

The base case is a node that is either null or exists in the input nodes array. When we reach such a point, we return that node.

## A solution in C++

```cpp
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

TreeNode* lowestCommonAncestor(TreeNode* root, const vector<TreeNode*> &nodes) {
    if (root == nullptr || find(nodes.begin(), nodes.end(), root) != nodes.end())
        return root;
    TreeNode* left = lowestCommonAncestor(root->left, nodes);
    TreeNode* right = lowestCommonAncestor(root->right, nodes);
    if (left != nullptr && right != nullptr)
        return root;
    return left != nullptr ? left : right;
}
```
The algorithm used here is a recursive depth-first search approach. We start at the given root node and make a recursive call for both left and right subtrees. If the current node is null or it exists in the given input array, we return the current node.

Once the left and right recursive calls are completed, we check if left and right are not null, which means we have found at least two target nodes in both the subtrees. In that case, the current node is the LCA we are looking for, so return it. If one of the left or right is null, then we return the one which is not null (i.e., has the target node(s) as its descendant).

The base case is a node that is either null or exists in the input nodes array. When we reach such a point, we return that node.

## A solution in Python

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

def lowestCommonAncestor(root, nodes):
    if root is None or root in nodes:
        return root
    left = lowestCommonAncestor(root.left, nodes)
    right = lowestCommonAncestor(root.right, nodes)
    if left is not None and right is not None:
        return root
    return left if left is not None else right
```
The algorithm used here is a recursive depth-first search approach. We start at the given root node and make a recursive call for both left and right subtrees. If the current node is null or it exists in the given input array, we return the current node.

Once the left and right recursive calls are completed, we check if left and right are not null, which means we have found at least two target nodes in both the subtrees. In that case, the current node is the LCA we are looking for, so return it. If one of the left or right is null, then we return the one which is not null (i.e., has the target node(s) as its descendant).

The base case is a node that is either null or exists in the input nodes array. When we reach such a point, we return that node.

## A solution in Javascript

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

function lowestCommonAncestor(root, nodes) {
    if (root === null || nodes.includes(root))
        return root;
    let left = lowestCommonAncestor(root.left, nodes);
    let right = lowestCommonAncestor(root.right, nodes);
    if (left !== null && right !== null)
        return root;
    return left !== null ? left : right;
}
```
The algorithm used here is a recursive depth-first search approach. We start at the given root node and make a recursive call for both left and right subtrees. If the current node is null or it exists in the given input array, we return the current node.

Once the left and right recursive calls are completed, we check if left and right are not null, which means we have found at least two target nodes in both the subtrees. In that case, the current node is the LCA we are looking for, so return it. If one of the left or right is null, then we return the one which is not null (i.e., has the target node(s) as its descendant).

The base case is a node that is either null or exists in the input nodes array. When we reach such a point, we return that node.


# Goal Parser Interpretation

- slug: goal-parser-interpretation
- difficulty: Easy

You own a **Goal Parser** that can interpret a string `command`. The `command` consists of an alphabet of `"G "`, `"() "` and/or `"(al) "` in some order. The Goal Parser will interpret `"G "` as the string `"G "`, `"() "` as the string `"o "`, and `"(al) "` as the string `"al "`. The interpreted strings are then concatenated in the original order.

Given the string `command`, return _the **Goal Parser**'s interpretation of_ `command`.

**Example 1:**

**Input:** command =  "G()(al) "
**Output:**  "Goal "
**Explanation:** The Goal Parser interprets the command as follows:
G -> G
() -> o
(al) -> al
The final concatenated result is  "Goal ".

**Example 2:**

**Input:** command =  "G()()()()(al) "
**Output:**  "Gooooal "

**Example 3:**

**Input:** command =  "(al)G(al)()()G "
**Output:**  "alGalooG "

**Constraints:**

*   `1 <= command.length <= 100`
*   `command` consists of `"G "`, `"() "`, and/or `"(al) "` in some order.

## A solution in Java

```java
public int numWays(String s) {
    int numberOfOnes = 0;
    for (char c : s.toCharArray()) {
        if (c == '1') numberOfOnes++;
    }
    if (numberOfOnes % 3 != 0) return 0;

    int target = numberOfOnes / 3;
    if (target == 0) {
        long n = s.length();
        return (int) ((n - 1) * (n - 2) / 2 % 1000000007);
    }

    int onesSoFar1 = 0, onesSoFar2 = 0;
    long way1 = 0, way2 = 0;
    for (char c : s.toCharArray()) {
        if (c == '1') {
            onesSoFar1++;
            if (onesSoFar1 == target) {
                way1++;
                onesSoFar1 = 0;
            }

            onesSoFar2++;
            if (onesSoFar2 == target * 2) {
                way2++;
                onesSoFar2 = 0;
            }
        }
    }

    return (int) (way1 * way2 % 1000000007);
}
```
First, count the number of ones in the binary string s. If the number of ones is not divisible by three, there is no valid way to split s. If the number of ones is zero, calculate the result as the number of ways to pick two positions out of (s.length() - 1) positions to insert separator. In other cases, we iterate through the string and count ones. If the count reaches target ones, we accumulate the result for s1 and clear the count. Similarly for s2, we accumulate the result based on the count reaching target * 2. Finally, we calculate the result as (way1 * way2) % 1000000007.

## A solution in C++

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

int numWays(string s) {
    int numberOfOnes = 0;
    for (char c : s) {
        if (c == '1') numberOfOnes++;
    }
    if (numberOfOnes % 3 != 0) return 0;

    int target = numberOfOnes / 3;
    if (target == 0) {
        long n = s.length();
        return ((n - 1) * (n - 2) / 2) % 1000000007;
    }

    int onesSoFar1 = 0, onesSoFar2 = 0;
    long way1 = 0, way2 = 0;
    for (char c : s) {
        if (c == '1') {
            onesSoFar1++;
            if (onesSoFar1 == target) {
                way1++;
                onesSoFar1 = 0;
            }

            onesSoFar2++;
            if (onesSoFar2 == target * 2) {
                way2++;
                onesSoFar2 = 0;
            }
        }
    }

    return (way1 * way2) % 1000000007;
}
```
First, count the number of ones in the binary string s. If the number of ones is not divisible by three, there is no valid way to split s. If the number of ones is zero, calculate the result as the number of ways to pick two positions out of (s.length() - 1) positions to insert separator. In other cases, we iterate through the string and count ones. If the count reaches target ones, we accumulate the result for s1 and clear the count. Similarly for s2, we accumulate the result based on the count reaching target * 2. Finally, we calculate the result as (way1 * way2) % 1000000007.

## A solution in Python

```python
def num_ways(s: str) -> int:
    number_of_ones = s.count('1')
    if number_of_ones % 3 != 0:
        return 0

    target = number_of_ones // 3
    if target == 0:
        n = len(s)
        return ((n - 1) * (n - 2) // 2) % 1000000007

    ones_so_far1, ones_so_far2 = 0, 0
    way1, way2 = 0, 0
    for c in s:
        if c == '1':
            ones_so_far1 += 1
            if ones_so_far1 == target:
                way1 += 1
                ones_so_far1 = 0

            ones_so_far2 += 1
            if ones_so_far2 == target * 2:
                way2 += 1
                ones_so_far2 = 0

    return (way1 * way2) % 1000000007
```
First, count the number of ones in the binary string s. If the number of ones is not divisible by three, there is no valid way to split s. If the number of ones is zero, calculate the result as the number of ways to pick two positions out of (s.length() - 1) positions to insert separator. In other cases, we iterate through the string and count ones. If the count reaches target ones, we accumulate the result for s1 and clear the count. Similarly for s2, we accumulate the result based on the count reaching target * 2. Finally, we calculate the result as (way1 * way2) % 1000000007.

## A solution in Javascript

```javascript
function numWays(s) {
  let numberOfOnes = s.split('').filter(c => c === '1').length;
  if (numberOfOnes % 3 !== 0) return 0;

  let target = numberOfOnes / 3;
  if (target === 0) {
    let n = s.length;
    return ((n - 1) * (n - 2) / 2) % 1000000007;
  }

  let onesSoFar1 = 0, onesSoFar2 = 0;
  let way1 = 0, way2 = 0;
  for (let c of s) {
    if (c === '1') {
      onesSoFar1++;
      if (onesSoFar1 === target) {
        way1++;
        onesSoFar1 = 0;
      }

      onesSoFar2++;
      if (onesSoFar2 === target * 2) {
        way2++;
        onesSoFar2 = 0;
      }
    }
  }

  return (way1 * way2) % 1000000007;
}
```
First, count the number of ones in the binary string s. If the number of ones is not divisible by three, there is no valid way to split s. If the number of ones is zero, calculate the result as the number of ways to pick two positions out of (s.length() - 1) positions to insert separator. In other cases, we iterate through the string and count ones. If the count reaches target ones, we accumulate the result for s1 and clear the count. Similarly for s2, we accumulate the result based on the count reaching target * 2. Finally, we calculate the result as (way1 * way2) % 1000000007.


# Max Number of K-Sum Pairs

- slug: max-number-of-k-sum-pairs
- difficulty: Medium

You are given an integer array `nums` and an integer `k`.

In one operation, you can pick two numbers from the array whose sum equals `k` and remove them from the array.

Return _the maximum number of operations you can perform on the array_.

**Example 1:**

**Input:** nums = \[1,2,3,4\], k = 5
**Output:** 2
**Explanation:** Starting with nums = \[1,2,3,4\]:
- Remove numbers 1 and 4, then nums = \[2,3\]
- Remove numbers 2 and 3, then nums = \[\]
There are no more pairs that sum up to 5, hence a total of 2 operations.

**Example 2:**

**Input:** nums = \[3,1,3,4,3\], k = 6
**Output:** 1
**Explanation:** Starting with nums = \[3,1,3,4,3\]:
- Remove the first two 3's, then nums = \[1,4,3\]
There are no more pairs that sum up to 6, hence a total of 1 operation.

**Constraints:**

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

## A solution in Java

```java
public int findLengthOfShortestSubarray(int[] arr) {
    int n = arr.length;
    int left = 0, right = n - 1;

    while (left < n - 1 && arr[left] <= arr[left + 1]) left++;
    if (left == n - 1) return 0;

    while (right > 0 && arr[right] >= arr[right - 1]) right--;

    int result = Math.min(right, n - left - 1);

    int i = 0, j = right;

    while (i <= left && j < n) {
        if (arr[i] <= arr[j]) {
            result = Math.min(result, j - i - 1);
            i++;
        } else {
            j++;
        }
    }

    return result;
}
```
The algorithm starts by finding the longest non-decreasing prefixes and suffixes of the input array. After finding the left and right boundaries, we check if the entire array is non-decreasing (i.e., `left == n - 1`). If so, we can return 0 as no subarray needs to be removed.

Next, we initialize the result as the minimum of the length of the right boundary and the complement of the left boundary, ensuring that we cover the case where the removal occurs at either end.

We then iterate through the array with two pointers `i` and `j`, starting with `i=0` and `j=right`, and compare the elements at these indices. If `arr[i] <= arr[j]`, we update the result by taking the minimum of the distance between `i` and `j` minus 1 or the current result, and increment `i`. Otherwise, we increment `j`. The loop runs until both pointers have traversed the full array.

The function finally returns the minimum length subarray that needs to be removed to make the remaining elements non-decreasing.

## A solution in C++

```cpp
int findLengthOfShortestSubarray(vector<int>& arr) {
    int n = arr.size();
    int left = 0, right = n - 1;

    while (left < n - 1 && arr[left] <= arr[left + 1]) left++;
    if (left == n - 1) return 0;

    while (right > 0 && arr[right] >= arr[right - 1]) right--;

    int result = min(right, n - left - 1);

    int i = 0, j = right;

    while (i <= left && j < n) {
        if (arr[i] <= arr[j]) {
            result = min(result, j - i - 1);
            i++;
        } else {
            j++;
        }
    }

    return result;
}
```
The algorithm starts by finding the longest non-decreasing prefixes and suffixes of the input array. After finding the left and right boundaries, we check if the entire array is non-decreasing (i.e., `left == n - 1`). If so, we can return 0 as no subarray needs to be removed.

Next, we initialize the result as the minimum of the length of the right boundary and the complement of the left boundary, ensuring that we cover the case where the removal occurs at either end.

We then iterate through the array with two pointers `i` and `j`, starting with `i=0` and `j=right`, and compare the elements at these indices. If `arr[i] <= arr[j]`, we update the result by taking the minimum of the distance between `i` and `j` minus 1 or the current result, and increment `i`. Otherwise, we increment `j`. The loop runs until both pointers have traversed the full array.

The function finally returns the minimum length subarray that needs to be removed to make the remaining elements non-decreasing.

## A solution in Python

```python
def findLengthOfShortestSubarray(arr):
    n = len(arr)
    left, right = 0, n - 1

    while left < n - 1 and arr[left] <= arr[left + 1]:
        left += 1

    if left == n - 1:
        return 0

    while right > 0 and arr[right] >= arr[right - 1]:
        right -= 1

    result = min(right, n - left - 1)

    i, j = 0, right

    while i <= left and j < n:
        if arr[i] <= arr[j]:
            result = min(result, j - i - 1)
            i += 1
        else:
            j += 1

    return result
```
The algorithm starts by finding the longest non-decreasing prefixes and suffixes of the input array. After finding the left and right boundaries, we check if the entire array is non-decreasing (i.e., `left == n - 1`). If so, we can return 0 as no subarray needs to be removed.

Next, we initialize the result as the minimum of the length of the right boundary and the complement of the left boundary, ensuring that we cover the case where the removal occurs at either end.

We then iterate through the array with two pointers `i` and `j`, starting with `i=0` and `j=right`, and compare the elements at these indices. If `arr[i] <= arr[j]`, we update the result by taking the minimum of the distance between `i` and `j` minus 1 or the current result, and increment `i`. Otherwise, we increment `j`. The loop runs until both pointers have traversed the full array.

The function finally returns the minimum length subarray that needs to be removed to make the remaining elements non-decreasing.

## A solution in Javascript

```javascript
function findLengthOfShortestSubarray(arr) {
    const n = arr.length;
    let left = 0, right = n - 1;

    while (left < n - 1 && arr[left] <= arr[left + 1]) left++;
    if (left === n - 1) return 0;

    while (right > 0 && arr[right] >= arr[right - 1]) right--;

    let result = Math.min(right, n - left - 1);

    let i = 0, j = right;

    while (i <= left && j < n) {
        if (arr[i] <= arr[j]) {
            result = Math.min(result, j - i - 1);
            i++;
        } else {
            j++;
        }
    }

    return result;
}
```
The algorithm starts by finding the longest non-decreasing prefixes and suffixes of the input array. After finding the left and right boundaries, we check if the entire array is non-decreasing (i.e., `left == n - 1`). If so, we can return 0 as no subarray needs to be removed.

Next, we initialize the result as the minimum of the length of the right boundary and the complement of the left boundary, ensuring that we cover the case where the removal occurs at either end.

We then iterate through the array with two pointers `i` and `j`, starting with `i=0` and `j=right`, and compare the elements at these indices. If `arr[i] <= arr[j]`, we update the result by taking the minimum of the distance between `i` and `j` minus 1 or the current result, and increment `i`. Otherwise, we increment `j`. The loop runs until both pointers have traversed the full array.

The function finally returns the minimum length subarray that needs to be removed to make the remaining elements non-decreasing.


# Concatenation of Consecutive Binary Numbers

- slug: concatenation-of-consecutive-binary-numbers
- difficulty: Medium

Given an integer `n`, return _the **decimal value** of the binary string formed by concatenating the binary representations of_ `1` _to_ `n` _in order, **modulo**_ `109 + 7`.

**Example 1:**

**Input:** n = 1
**Output:** 1
**Explanation: ** "1 " in binary corresponds to the decimal value 1.

**Example 2:**

**Input:** n = 3
**Output:** 27
**Explanation:** In binary, 1, 2, and 3 corresponds to  "1 ",  "10 ", and  "11 ".
After concatenating them, we have  "11011 ", which corresponds to the decimal value 27.

**Example 3:**

**Input:** n = 12
**Output:** 505379714
**Explanation**: The concatenation results in  "1101110010111011110001001101010111100 ".
The decimal value of that is 118505380540.
After modulo 109 + 7, the result is 505379714.

**Constraints:**

*   `1 <= n <= 105`

## A solution in Java

```java
public int countRoutes(int[] locations, int start, int finish, int fuel) {
    Integer[][] memo = new Integer[locations.length][fuel + 1];
    return countRoutes(locations, start, finish, fuel, start, fuel, memo);
}

private int countRoutes(int[] locations, int start, int finish, int fuel, int curr, int remainingFuel, Integer[][] memo) {
    if (remainingFuel < 0) {
        return 0;
    }

    if (memo[curr][remainingFuel] != null) {
        return memo[curr][remainingFuel];
    }

    int ans = curr == finish ? 1 : 0;
    for (int next = 0; next < locations.length; ++next) {
        if (next != curr) {
            ans += countRoutes(locations, start, finish, fuel, next, remainingFuel - Math.abs(locations[curr] - locations[next]), memo);
            ans %= 1000000007;
        }
    }
    memo[curr][remainingFuel] = ans;
    return ans;
}
```
The algorithm is a depth-first search with memoization. We start from the given start city and move to any other city as long as we have enough fuel. If we reach the finish city, we count the route. We recursively try all combinations of moves, using memoization to store the intermediate results for each city and the remaining fuel. This way, we avoid recomputing the same subproblems multiple times, which reduces the overall time complexity of the algorithm. Since the answer may be too large, we return it modulo 10^9 + 7.

## A solution in C++

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

int countRoutes(vector<int>& locations, int start, int finish, int fuel, int curr = -1, int remainingFuel = -1, vector<vector<int>>& memo = vector<vector<int>>(100, vector<int>(201, -1))) {
    if (curr == -1) {
        curr = start;
        remainingFuel = fuel;
    }

    if (remainingFuel < 0)
        return 0;

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

    int ans = (curr == finish);
    for (int next = 0; next < locations.size(); next++) {
        if (next != curr) {
            ans += countRoutes(locations, start, finish, fuel, next, remainingFuel - abs(locations[curr] - locations[next]), memo);
            ans %= 1000000007;
        }
    }
    memo[curr][remainingFuel] = ans;
    return ans;
}
```
The algorithm is a depth-first search with memoization. We start from the given start city and move to any other city as long as we have enough fuel. If we reach the finish city, we count the route. We recursively try all combinations of moves, using memoization to store the intermediate results for each city and the remaining fuel. This way, we avoid recomputing the same subproblems multiple times, which reduces the overall time complexity of the algorithm. Since the answer may be too large, we return it modulo 10^9 + 7.

## A solution in Python

```python
def count_routes(locations, start, finish, fuel, curr=None, remaining_fuel=None, memo=None):
    if memo is None:
        memo = {}

    if curr is None:
        curr = start
        remaining_fuel = fuel

    if remaining_fuel < 0:
        return 0

    if (curr, remaining_fuel) in memo:
        return memo[(curr, remaining_fuel)]

    ans = 1 if curr == finish else 0
    for next in range(len(locations)):
        if next != curr:
            ans += count_routes(locations, start, finish, fuel, next, remaining_fuel - abs(locations[curr] - locations[next]), memo)
            ans %= 1000000007

    memo[(curr, remaining_fuel)] = ans
    return ans
```
The algorithm is a depth-first search with memoization. We start from the given start city and move to any other city as long as we have enough fuel. If we reach the finish city, we count the route. We recursively try all combinations of moves, using memoization to store the intermediate results for each city and the remaining fuel. This way, we avoid recomputing the same subproblems multiple times, which reduces the overall time complexity of the algorithm. Since the answer may be too large, we return it modulo 10^9 + 7.

## A solution in Javascript

```javascript
function countRoutes(locations, start, finish, fuel, curr = null, remainingFuel = null, memo = {}) {
    if (curr === null) {
        curr = start;
        remainingFuel = fuel;
    }

    if (remainingFuel < 0) {
        return 0;
    }

    const key = `${curr}:${remainingFuel}`;
    if (memo.hasOwnProperty(key)) {
        return memo[key];
    }

    let ans = (curr === finish) ? 1 : 0;
    for (let next = 0; next < locations.length; ++next) {
        if (next !== curr) {
            ans += countRoutes(locations, start, finish, fuel, next, remainingFuel - Math.abs(locations[curr] - locations[next]), memo);
            ans %= 1000000007;
        }
    }
    memo[key] = ans;
    return ans;
}
```
The algorithm is a depth-first search with memoization. We start from the given start city and move to any other city as long as we have enough fuel. If we reach the finish city, we count the route. We recursively try all combinations of moves, using memoization to store the intermediate results for each city and the remaining fuel. This way, we avoid recomputing the same subproblems multiple times, which reduces the overall time complexity of the algorithm. Since the answer may be too large, we return it modulo 10^9 + 7.


# Longest Palindromic Subsequence II

- slug: longest-palindromic-subsequence-ii
- difficulty: Medium

A subsequence of a string `s` is considered a **good palindromic subsequence** if:

*   It is a subsequence of `s`.
*   It is a palindrome (has the same value if reversed).
*   It has an **even** length.
*   No two consecutive characters are equal, except the two middle ones.

For example, if `s = "abcabcabb "`, then `"abba "` is considered a **good palindromic subsequence**, while `"bcb "` (not even length) and `"bbbb "` (has equal consecutive characters) are not.

Given a string `s`, return _the **length** of the **longest good palindromic subsequence** in_ `s`.

**Example 1:**

**Input:** s =  "bbabab "
**Output:** 4
**Explanation:** The longest good palindromic subsequence of s is  "baab ".

**Example 2:**

**Input:** s =  "dcbccacdb "
**Output:** 4
**Explanation:** The longest good palindromic subsequence of s is  "dccd ".

**Constraints:**

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

## A solution in Java

```java
import java.util.*;

public List<Integer> mostVisited(int n, int[] rounds) {
    int[] visited = new int[n + 1];
    for (int i = 1; i < rounds.length; ++i) {
        for (int start = rounds[i - 1], end = rounds[i]; start != end; start = start % n + 1) {
            ++visited[start];
        }
    }
    ++visited[rounds[rounds.length - 1]];

    int maxVisits = Arrays.stream(visited).max().getAsInt();
    List<Integer> result = new ArrayList<>();

    for (int i = 1; i <= n; ++i) {
        if (visited[i] == maxVisits) {
            result.add(i);
        }
    }
    return result;
}
```
The algorithm initializes an array `visited` that counts the visits for each sector. We iterate over the given `rounds` array, and for each consecutive pair of sectors (i.e., from `rounds[i - 1]` to `rounds[i]`), we increment the count of visits for each sector in between (inclusive of the starting sector). After updating the visit count for each round, we find the maximum number of visits (`maxVisits`). Lastly, we iterate over the `visited` array and create a list of all sectors with maximum visits (`result`). The function returns the `result` list.

## A solution in C++

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

vector<int> mostVisited(int n, vector<int>& rounds) {
    vector<int> visited(n + 1, 0);

    for (int i = 1; i < rounds.size(); i++) {
        int start = rounds[i - 1], end = rounds[i];
        while (start != end) {
            visited[start]++;
            start = start % n + 1;
        }
    }
    visited[rounds.back()]++;

    int maxVisits = *max_element(visited.begin(), visited.end());
    vector<int> result;

    for (int i = 1; i <= n; i++) {
        if (visited[i] == maxVisits)
            result.push_back(i);
    }

    return result;
}
```
The algorithm initializes an array `visited` that counts the visits for each sector. We iterate over the given `rounds` array, and for each consecutive pair of sectors (i.e., from `rounds[i - 1]` to `rounds[i]`), we increment the count of visits for each sector in between (inclusive of the starting sector). After updating the visit count for each round, we find the maximum number of visits (`maxVisits`). Lastly, we iterate over the `visited` array and create a list of all sectors with maximum visits (`result`). The function returns the `result` list.

## A solution in Python

```python
def most_visited(n, rounds):
    visited = [0] * (n + 1)

    for i in range(1, len(rounds)):
        start, end = rounds[i - 1], rounds[i]
        while start != end:
            visited[start] += 1
            start = (start % n) + 1
    visited[rounds[-1]] += 1

    max_visits = max(visited);
    return [i for i in range(1, n + 1) if visited[i] == max_visits]
```
The algorithm initializes an array `visited` that counts the visits for each sector. We iterate over the given `rounds` array, and for each consecutive pair of sectors (i.e., from `rounds[i - 1]` to `rounds[i]`), we increment the count of visits for each sector in between (inclusive of the starting sector). After updating the visit count for each round, we find the maximum number of visits (`maxVisits`). Lastly, we iterate over the `visited` array and create a list of all sectors with maximum visits (`result`). The function returns the `result` list.

## A solution in Javascript

```javascript
function mostVisited(n, rounds) {
    const visited = new Array(n + 1).fill(0);

    for (let i = 1; i < rounds.length; ++i) {
        for (let start = rounds[i - 1], end = rounds[i]; start !== end; start = start % n + 1) {
            ++visited[start];
        }
    }
    ++visited[rounds[rounds.length - 1]];

    const maxVisits = Math.max(...visited);
    const result = [];

    for (let i = 1; i <= n; ++i) {
        if (visited[i] === maxVisits) {
            result.push(i);
        }
    }
    return result;
}
```
The algorithm initializes an array `visited` that counts the visits for each sector. We iterate over the given `rounds` array, and for each consecutive pair of sectors (i.e., from `rounds[i - 1]` to `rounds[i]`), we increment the count of visits for each sector in between (inclusive of the starting sector). After updating the visit count for each round, we find the maximum number of visits (`maxVisits`). Lastly, we iterate over the `visited` array and create a list of all sectors with maximum visits (`result`). The function returns the `result` list.


# Count the Number of Consistent Strings

- slug: count-the-number-of-consistent-strings
- difficulty: Easy

You are given a string `allowed` consisting of **distinct** characters and an array of strings `words`. A string is **consistent** if all characters in the string appear in the string `allowed`.

Return _the number of **consistent** strings in the array_ `words`.

**Example 1:**

**Input:** allowed =  "ab ", words = \[ "ad ", "bd ", "aaab ", "baa ", "badab "\]
**Output:** 2
**Explanation:** Strings  "aaab " and  "baa " are consistent since they only contain characters 'a' and 'b'.

**Example 2:**

**Input:** allowed =  "abc ", words = \[ "a ", "b ", "c ", "ab ", "ac ", "bc ", "abc "\]
**Output:** 7
**Explanation:** All strings are consistent.

**Example 3:**

**Input:** allowed =  "cad ", words = \[ "cc ", "acd ", "b ", "ba ", "bac ", "bad ", "ac ", "d "\]
**Output:** 4
**Explanation:** Strings  "cc ",  "acd ",  "ac ", and  "d " are consistent.

**Constraints:**

*   `1 <= words.length <= 104`
*   `1 <= allowed.length <= 26`
*   `1 <= words[i].length <= 10`
*   The characters in `allowed` are **distinct**.
*   `words[i]` and `allowed` contain only lowercase English letters.

## A solution in Java

```java
public int findLatestStep(int[] arr, int m) {
    int n = arr.length;
    int[] lengthLeft = new int[n + 2], lengthRight = new int[n + 2];
    int count = 0, result = -1;

    for (int i = 0; i < n; ++i) {
        int pos = arr[i];
        int leftLength = lengthRight[pos - 1];
        int rightLength = lengthLeft[pos + 1];
        int newLength = leftLength + rightLength + 1;

        if (leftLength == m || rightLength == m) {
            count--;
        }

        if (newLength == m) {
            count++;
        }

        if (newLength > 0) {
            lengthLeft[pos - leftLength] = newLength;
            lengthRight[pos + rightLength] = newLength;
            result = i + 1;
        }
    }

    return count > 0 ? result : -1;
}
```
The algorithm initializes two arrays `lengthLeft` and `lengthRight` to keep track of the left and right lengths of contiguous groups of 1's. It also initializes a `count` variable that will be incremented when finding a group of 1's with length `m` and decremented when a group of 1's is extended beyond length `m`.

For each step `i` from 1 to n, the position in the binary string is set to 1 using the value from the array `arr`. The left length, right length, and total new length of the newly created group of 1's is then calculated using `lengthLeft` and `lengthRight`.

After calculating the new lengths, we modify the count:
- If the left length is equal to `m` or the right length is equal to `m`, decrement the count
- If the new length is equal to `m`, increment the count

After that, if the new length is greater than 0, we set the values of new left and right lengths in `lengthLeft` and `lengthRight` arrays and update the `result` with the current step `i + 1`.

Once all steps are completed, if the count is greater than 0, then the `result` is returned. If the count is 0 or less, then we return -1 as no such group of 1's exists with length `m`.

## A solution in C++

```cpp
int findLatestStep(vector<int>& arr, int m) {
    int n = arr.size();
    vector<int> lengthLeft(n + 2, 0), lengthRight(n + 2, 0);
    int count = 0, result = -1;

    for (int i = 0; i < n; ++i) {
        int pos = arr[i];
        int leftLength = lengthRight[pos - 1];
        int rightLength = lengthLeft[pos + 1];
        int newLength = leftLength + rightLength + 1;

        if (leftLength == m || rightLength == m) {
            count--;
        }

        if (newLength == m) {
            count++;
        }

        if (newLength > 0) {
            lengthLeft[pos - leftLength] = newLength;
            lengthRight[pos + rightLength] = newLength;
            result = i + 1;
        }
    }

    return count > 0 ? result : -1;
}
```
The algorithm initializes two arrays `lengthLeft` and `lengthRight` to keep track of the left and right lengths of contiguous groups of 1's. It also initializes a `count` variable that will be incremented when finding a group of 1's with length `m` and decremented when a group of 1's is extended beyond length `m`.

For each step `i` from 1 to n, the position in the binary string is set to 1 using the value from the array `arr`. The left length, right length, and total new length of the newly created group of 1's is then calculated using `lengthLeft` and `lengthRight`.

After calculating the new lengths, we modify the count:
- If the left length is equal to `m` or the right length is equal to `m`, decrement the count
- If the new length is equal to `m`, increment the count

After that, if the new length is greater than 0, we set the values of new left and right lengths in `lengthLeft` and `lengthRight` arrays and update the `result` with the current step `i + 1`.

Once all steps are completed, if the count is greater than 0, then the `result` is returned. If the count is 0 or less, then we return -1 as no such group of 1's exists with length `m`.

## A solution in Python

```python
def find_latest_step(arr, m):
    n = len(arr)
    length_left, length_right = [0] * (n + 2), [0] * (n + 2)
    count, result = 0, -1

    for i, pos in enumerate(arr):
        left_length = length_right[pos - 1]
        right_length = length_left[pos + 1]
        new_length = left_length + right_length + 1

        if left_length == m or right_length == m:
            count -= 1

        if new_length == m:
            count += 1

        if new_length > 0:
            length_left[pos - left_length] = new_length
            length_right[pos + right_length] = new_length
            result = i + 1

    return result if count > 0 else -1
```
The algorithm initializes two arrays `lengthLeft` and `lengthRight` to keep track of the left and right lengths of contiguous groups of 1's. It also initializes a `count` variable that will be incremented when finding a group of 1's with length `m` and decremented when a group of 1's is extended beyond length `m`.

For each step `i` from 1 to n, the position in the binary string is set to 1 using the value from the array `arr`. The left length, right length, and total new length of the newly created group of 1's is then calculated using `lengthLeft` and `lengthRight`.

After calculating the new lengths, we modify the count:
- If the left length is equal to `m` or the right length is equal to `m`, decrement the count
- If the new length is equal to `m`, increment the count

After that, if the new length is greater than 0, we set the values of new left and right lengths in `lengthLeft` and `lengthRight` arrays and update the `result` with the current step `i + 1`.

Once all steps are completed, if the count is greater than 0, then the `result` is returned. If the count is 0 or less, then we return -1 as no such group of 1's exists with length `m`.

## A solution in Javascript

```javascript
function findLatestStep(arr, m) {
    const n = arr.length;
    const lengthLeft = new Array(n + 2).fill(0);
    const lengthRight = new Array(n + 2).fill(0);
    let count = 0;
    let result = -1;

    for (let i = 0; i < n; ++i) {
        const pos = arr[i];
        const leftLength = lengthRight[pos - 1];
        const rightLength = lengthLeft[pos + 1];
        const newLength = leftLength + rightLength + 1;

        if (leftLength === m || rightLength === m) {
            count--;
        }

        if (newLength === m) {
            count++;
        }

        if (newLength > 0) {
            lengthLeft[pos - leftLength] = newLength;
            lengthRight[pos + rightLength] = newLength;
            result = i + 1;
        }
    }

    return count > 0 ? result : -1;
}
```
The algorithm initializes two arrays `lengthLeft` and `lengthRight` to keep track of the left and right lengths of contiguous groups of 1's. It also initializes a `count` variable that will be incremented when finding a group of 1's with length `m` and decremented when a group of 1's is extended beyond length `m`.

For each step `i` from 1 to n, the position in the binary string is set to 1 using the value from the array `arr`. The left length, right length, and total new length of the newly created group of 1's is then calculated using `lengthLeft` and `lengthRight`.

After calculating the new lengths, we modify the count:
- If the left length is equal to `m` or the right length is equal to `m`, decrement the count
- If the new length is equal to `m`, increment the count

After that, if the new length is greater than 0, we set the values of new left and right lengths in `lengthLeft` and `lengthRight` arrays and update the `result` with the current step `i + 1`.

Once all steps are completed, if the count is greater than 0, then the `result` is returned. If the count is 0 or less, then we return -1 as no such group of 1's exists with length `m`.


# Sum of Absolute Differences in a Sorted Array

- slug: sum-of-absolute-differences-in-a-sorted-array
- difficulty: Medium

You are given an integer array `nums` sorted in **non-decreasing** order.

Build and return _an integer array_ `result` _with the same length as_ `nums` _such that_ `result[i]` _is equal to the **summation of absolute differences** between_ `nums[i]` _and all the other elements in the array._

In other words, `result[i]` is equal to `sum(|nums[i]-nums[j]|)` where `0 <= j < nums.length` and `j != i` (**0-indexed**).

**Example 1:**

**Input:** nums = \[2,3,5\]
**Output:** \[4,3,5\]
**Explanation:** Assuming the arrays are 0-indexed, then
result\[0\] = |2-2| + |2-3| + |2-5| = 0 + 1 + 3 = 4,
result\[1\] = |3-2| + |3-3| + |3-5| = 1 + 0 + 2 = 3,
result\[2\] = |5-2| + |5-3| + |5-5| = 3 + 2 + 0 = 5.

**Example 2:**

**Input:** nums = \[1,4,6,8,10\]
**Output:** \[24,15,13,15,21\]

**Constraints:**

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

## A solution in Java

```java
public int stoneGameV(int[] stoneValue) {
    int n = stoneValue.length;
    int[][] memo = new int[n][n];
    return maxScore(stoneValue, 0, n - 1, memo);
}

private int maxScore(int[] stoneValue, int start, int end, int[][] memo) {
    if (start == end) return 0;
    if (memo[start][end] != 0) return memo[start][end];

    int leftSum = 0, rightSum = 0;
    for (int i = start; i < end; ++i) {
        leftSum += stoneValue[i];
        rightSum = 0;
        for (int j = i + 1; j <= end; ++j)
            rightSum += stoneValue[j];

        if (leftSum > rightSum)
            memo[start][end] = Math.max(memo[start][end], rightSum + maxScore(stoneValue, i + 1, end, memo));
        else if (leftSum < rightSum)
            memo[start][end] = Math.max(memo[start][end], leftSum + maxScore(stoneValue, start, i, memo));
        else
            memo[start][end] = Math.max(memo[start][end], leftSum + Math.max(maxScore(stoneValue, start, i, memo), maxScore(stoneValue, i + 1, end, memo)));
    }
    return memo[start][end];
}
```
The algorithm is based on dynamic programming with memoization. First, we initialize a memo table to store the intermediate results. The function `maxScore` calculates the maximum score Alice can obtain for a given subarray of `stoneValue`.

For each pair of indices `(start, end)`, we iterate through the subarray and calculate the running sum of the left and right parts of the subarray for every split at index `i`. Based on the value comparison of both parts, we call the `maxScore` function recursively to handle the remaining part and store the sum of the remaining part and the best result of the recursive call in the memo table.

The base case occurs when `start == end`, which means there is only one stone left, in that case, the maximum score Alice can obtain is 0 as the game ends.

Finally, the main function `stoneGameV` initializes the memo table and calls the `maxScore` function for the whole array of `stoneValue`.

## A solution in C++

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

int maxScore(const vector<int>& stoneValue, int start, int end, vector<vector<int>>& memo) {
    if (start == end) return 0;
    if (memo[start][end] != -1) return memo[start][end];

    int leftSum = 0, rightSum = 0;
    for (int i = start; i < end; ++i) {
        leftSum += stoneValue[i];
        rightSum = 0;
        for (int j = i + 1; j <= end; ++j)
            rightSum += stoneValue[j];

        if (leftSum > rightSum)
            memo[start][end] = max(memo[start][end], rightSum + maxScore(stoneValue, i + 1, end, memo));
        else if (leftSum < rightSum)
            memo[start][end] = max(memo[start][end], leftSum + maxScore(stoneValue, start, i, memo));
        else
            memo[start][end] = max(memo[start][end], leftSum + max(maxScore(stoneValue, start, i, memo), maxScore(stoneValue, i + 1, end, memo)));
    }
    return memo[start][end];
}

int stoneGameV(vector<int>& stoneValue) {
    int n = stoneValue.size();
    vector<vector<int>> memo(n, vector<int>(n, -1));
    return maxScore(stoneValue, 0, n - 1, memo);
}
```
The algorithm is based on dynamic programming with memoization. First, we initialize a memo table to store the intermediate results. The function `maxScore` calculates the maximum score Alice can obtain for a given subarray of `stoneValue`.

For each pair of indices `(start, end)`, we iterate through the subarray and calculate the running sum of the left and right parts of the subarray for every split at index `i`. Based on the value comparison of both parts, we call the `maxScore` function recursively to handle the remaining part and store the sum of the remaining part and the best result of the recursive call in the memo table.

The base case occurs when `start == end`, which means there is only one stone left, in that case, the maximum score Alice can obtain is 0 as the game ends.

Finally, the main function `stoneGameV` initializes the memo table and calls the `maxScore` function for the whole array of `stoneValue`.

## A solution in Python

```python
def stoneGameV(stoneValue):
    memo = [[-1 for _ in range(len(stoneValue))] for _ in range(len(stoneValue))]
    return maxScore(stoneValue, 0, len(stoneValue) - 1, memo)

def maxScore(stoneValue, start, end, memo):
    if start == end:
        return 0
    if memo[start][end] != -1:
        return memo[start][end]

    left_sum, right_sum = 0, 0
    for i in range(start, end):
        left_sum += stoneValue[i]
        right_sum = sum(stoneValue[i + 1:end + 1])

        if left_sum > right_sum:
            memo[start][end] = max(memo[start][end], right_sum + maxScore(stoneValue, i + 1, end, memo))
        elif left_sum < right_sum:
            memo[start][end] = max(memo[start][end], left_sum + maxScore(stoneValue, start, i, memo))
        else:
            memo[start][end] = max(memo[start][end], left_sum + max(maxScore(stoneValue, start, i, memo), maxScore(stoneValue, i + 1, end, memo)))

    return memo[start][end]
```
The algorithm is based on dynamic programming with memoization. First, we initialize a memo table to store the intermediate results. The function `maxScore` calculates the maximum score Alice can obtain for a given subarray of `stoneValue`.

For each pair of indices `(start, end)`, we iterate through the subarray and calculate the running sum of the left and right parts of the subarray for every split at index `i`. Based on the value comparison of both parts, we call the `maxScore` function recursively to handle the remaining part and store the sum of the remaining part and the best result of the recursive call in the memo table.

The base case occurs when `start == end`, which means there is only one stone left, in that case, the maximum score Alice can obtain is 0 as the game ends.

Finally, the main function `stoneGameV` initializes the memo table and calls the `maxScore` function for the whole array of `stoneValue`.

## A solution in Javascript

```javascript
var stoneGameV = function(stoneValue) {
    const memo = new Array(stoneValue.length).fill(null).map(() => new Array(stoneValue.length).fill(-1));
    return maxScore(stoneValue, 0, stoneValue.length - 1, memo);
};

function maxScore(stoneValue, start, end, memo) {
    if (start === end) return 0;
    if (memo[start][end] !== -1) return memo[start][end];

    let leftSum = 0, rightSum = 0;
    for (let i = start; i < end; ++i) {
        leftSum += stoneValue[i];
        rightSum = 0;
        for (let j = i + 1; j <= end; ++j)
            rightSum += stoneValue[j];

        if (leftSum > rightSum)
            memo[start][end] = Math.max(memo[start][end], rightSum + maxScore(stoneValue, i + 1, end, memo));
        else if (leftSum < rightSum)
            memo[start][end] = Math.max(memo[start][end], leftSum + maxScore(stoneValue, start, i, memo));
        else
            memo[start][end] = Math.max(memo[start][end], leftSum + Math.max(maxScore(stoneValue, start, i, memo), maxScore(stoneValue, i + 1, end, memo)));
    }
    return memo[start][end];
}
```
The algorithm is based on dynamic programming with memoization. First, we initialize a memo table to store the intermediate results. The function `maxScore` calculates the maximum score Alice can obtain for a given subarray of `stoneValue`.

For each pair of indices `(start, end)`, we iterate through the subarray and calculate the running sum of the left and right parts of the subarray for every split at index `i`. Based on the value comparison of both parts, we call the `maxScore` function recursively to handle the remaining part and store the sum of the remaining part and the best result of the recursive call in the memo table.

The base case occurs when `start == end`, which means there is only one stone left, in that case, the maximum score Alice can obtain is 0 as the game ends.

Finally, the main function `stoneGameV` initializes the memo table and calls the `maxScore` function for the whole array of `stoneValue`.


# Stone Game VI

- slug: stone-game-vi
- difficulty: Medium

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

There are `n` stones in a pile. On each player's turn, they can **remove** a stone from the pile and receive points based on the stone's value. Alice and Bob may **value the stones differently**.

You are given two integer arrays of length `n`, `aliceValues` and `bobValues`. Each `aliceValues[i]` and `bobValues[i]` represents how Alice and Bob, respectively, value the `ith` stone.

The winner is the person with the most points after all the stones are chosen. If both players have the same amount of points, the game results in a draw. Both players will play **optimally**. Both players know the other's values.

Determine the result of the game, and:

*   If Alice wins, return `1`.
*   If Bob wins, return `-1`.
*   If the game results in a draw, return `0`.

**Example 1:**

**Input:** aliceValues = \[1,3\], bobValues = \[2,1\]
**Output:** 1
**Explanation:**
If Alice takes stone 1 (0-indexed) first, Alice will receive 3 points.
Bob can only choose stone 0, and will only receive 2 points.
Alice wins.

**Example 2:**

**Input:** aliceValues = \[1,2\], bobValues = \[3,1\]
**Output:** 0
**Explanation:**
If Alice takes stone 0, and Bob takes stone 1, they will both have 1 point.
Draw.

**Example 3:**

**Input:** aliceValues = \[2,4,3\], bobValues = \[1,6,7\]
**Output:** -1
**Explanation:**
Regardless of how Alice plays, Bob will be able to have more points than Alice.
For example, if Alice takes stone 1, Bob can take stone 2, and Alice takes stone 0, Alice will have 6 points to Bob's 7.
Bob wins.

**Constraints:**

*   `n == aliceValues.length == bobValues.length`
*   `1 <= n <= 105`
*   `1 <= aliceValues[i], bobValues[i] <= 100`

## A solution in Java

```java
import java.util.Arrays;
import java.util.Comparator;

public int stoneGameVI(int[] aliceValues, int[] bobValues) {
    int n = aliceValues.length;
    Integer[] indices = new Integer[n];
    for (int i = 0; i < n; i++) {
        indices[i] = i;
    }

    Arrays.sort(indices, (a, b) -> (bobValues[a] + aliceValues[a]) - (bobValues[b] + aliceValues[b]));

    int aliceSum = 0, bobSum = 0;
    for (int i = n - 1; i >= 0; i--) {
        if ((n - 1 - i) % 2 == 0)
            aliceSum += aliceValues[indices[i]];
        else
            bobSum += bobValues[indices[i]];
    }

    return Integer.compare(aliceSum, bobSum);
}
```
Instead of looking at the stones' values separately, we can look at them by their total value (`total = aliceValue + bobValue`). We sort the stones in decreasing order of their total value. Essentially, we want both Alice and Bob to take higher value stones.

Then, we iterate over the sorted stones, giving each stone i to the current player (Alice gets the stones from even indices, Bob gets the stones from odd indices). After that, we compare the sum of values obtained by both players, and return the appropriate result value (win, lose, or draw) as per the problem statement.

## A solution in C++

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

int stoneGameVI(std::vector<int>& aliceValues, std::vector<int>& bobValues) {
    int n = aliceValues.size();
    std::vector<std::pair<int, int>> diff;
    for (int i = 0; i < n; ++i) {
        diff.push_back({aliceValues[i] + bobValues[i], i});
    }

    std::sort(diff.rbegin(), diff.rend());
    int aliceSum = 0, bobSum = 0;
    for (int i = 0; i < n; ++i) {
        if (i % 2 == 0) {
            aliceSum += aliceValues[diff[i].second];
        } else {
            bobSum += bobValues[diff[i].second];
        }
    }

    return (aliceSum == bobSum) ? 0 : ((aliceSum > bobSum) ? 1 : -1);
}
```
Instead of looking at the stones' values separately, we can look at them by their total value (`total = aliceValue + bobValue`). We sort the stones in decreasing order of their total value. Essentially, we want both Alice and Bob to take higher value stones.

Then, we iterate over the sorted stones, giving each stone i to the current player (Alice gets the stones from even indices, Bob gets the stones from odd indices). After that, we compare the sum of values obtained by both players, and return the appropriate result value (win, lose, or draw) as per the problem statement.

## A solution in Python

```python
def stoneGameVI(aliceValues, bobValues):
    n = len(aliceValues)
    diff = sorted([(aliceValues[i] + bobValues[i], i) for i in range(n)], reverse=True)

    aliceSum, bobSum = 0, 0
    for i in range(n):
        if i % 2 == 0:
            aliceSum += aliceValues[diff[i][1]]
        else:
            bobSum += bobValues[diff[i][1]]

    return 0 if aliceSum == bobSum else (1 if aliceSum > bobSum else -1)
```
Instead of looking at the stones' values separately, we can look at them by their total value (`total = aliceValue + bobValue`). We sort the stones in decreasing order of their total value. Essentially, we want both Alice and Bob to take higher value stones.

Then, we iterate over the sorted stones, giving each stone i to the current player (Alice gets the stones from even indices, Bob gets the stones from odd indices). After that, we compare the sum of values obtained by both players, and return the appropriate result value (win, lose, or draw) as per the problem statement.

## A solution in Javascript

```javascript
function stoneGameVI(aliceValues, bobValues) {
    const n = aliceValues.length;
    const diff = aliceValues.map((val, i) => [val + bobValues[i], i]).sort((a, b) => b[0] - a[0]);

    let aliceSum = 0, bobSum = 0;
    for (let i = 0; i < n; i++) {
        if (i % 2 === 0)
            aliceSum += aliceValues[diff[i][1]];
        else
            bobSum += bobValues[diff[i][1]];
    }

    return aliceSum === bobSum ? 0 : (aliceSum > bobSum ? 1 : -1);
}
```
Instead of looking at the stones' values separately, we can look at them by their total value (`total = aliceValue + bobValue`). We sort the stones in decreasing order of their total value. Essentially, we want both Alice and Bob to take higher value stones.

Then, we iterate over the sorted stones, giving each stone i to the current player (Alice gets the stones from even indices, Bob gets the stones from odd indices). After that, we compare the sum of values obtained by both players, and return the appropriate result value (win, lose, or draw) as per the problem statement.


# Delivering Boxes from Storage to Ports

- slug: delivering-boxes-from-storage-to-ports
- difficulty: Hard

You have the task of delivering some boxes from storage to their ports using only one ship. However, this ship has a **limit** on the **number of boxes** and the **total weight** that it can carry.

You are given an array `boxes`, where `boxes[i] = [portsi, weighti]`, and three integers `portsCount`, `maxBoxes`, and `maxWeight`.

*   `portsi` is the port where you need to deliver the `ith` box and `weightsi` is the weight of the `ith` box.
*   `portsCount` is the number of ports.
*   `maxBoxes` and `maxWeight` are the respective box and weight limits of the ship.

The boxes need to be delivered **in the order they are given**. The ship will follow these steps:

*   The ship will take some number of boxes from the `boxes` queue, not violating the `maxBoxes` and `maxWeight` constraints.
*   For each loaded box **in order**, the ship will make a **trip** to the port the box needs to be delivered to and deliver it. If the ship is already at the correct port, no **trip** is needed, and the box can immediately be delivered.
*   The ship then makes a return **trip** to storage to take more boxes from the queue.

The ship must end at storage after all the boxes have been delivered.

Return _the **minimum** number of **trips** the ship needs to make to deliver all boxes to their respective ports._

**Example 1:**

**Input:** boxes = \[\[1,1\],\[2,1\],\[1,1\]\], portsCount = 2, maxBoxes = 3, maxWeight = 3
**Output:** 4
**Explanation:** The optimal strategy is as follows:
- The ship takes all the boxes in the queue, goes to port 1, then port 2, then port 1 again, then returns to storage. 4 trips.
So the total number of trips is 4.
Note that the first and third boxes cannot be delivered together because the boxes need to be delivered in order (i.e. the second box needs to be delivered at port 2 before the third box).

**Example 2:**

**Input:** boxes = \[\[1,2\],\[3,3\],\[3,1\],\[3,1\],\[2,4\]\], portsCount = 3, maxBoxes = 3, maxWeight = 6
**Output:** 6
**Explanation:** The optimal strategy is as follows:
- The ship takes the first box, goes to port 1, then returns to storage. 2 trips.
- The ship takes the second, third and fourth boxes, goes to port 3, then returns to storage. 2 trips.
- The ship takes the fifth box, goes to port 2, then returns to storage. 2 trips.
So the total number of trips is 2 + 2 + 2 = 6.

**Example 3:**

**Input:** boxes = \[\[1,4\],\[1,2\],\[2,1\],\[2,1\],\[3,2\],\[3,4\]\], portsCount = 3, maxBoxes = 6, maxWeight = 7
**Output:** 6
**Explanation:** The optimal strategy is as follows:
- The ship takes the first and second boxes, goes to port 1, then returns to storage. 2 trips.
- The ship takes the third and fourth boxes, goes to port 2, then returns to storage. 2 trips.
- The ship takes the fifth and sixth boxes, goes to port 3, then returns to storage. 2 trips.
So the total number of trips is 2 + 2 + 2 = 6.

**Constraints:**

*   `1 <= boxes.length <= 105`
*   `1 <= portsCount, maxBoxes, maxWeight <= 105`
*   `1 <= portsi <= portsCount`
*   `1 <= weightsi <= maxWeight`

## A solution in Java

```java
public int min_trips(int[][] boxes, int portsCount, int maxBoxes, int maxWeight) {
    int trips = 0, idx = 0, n = boxes.length;
    while (idx < n) {
        int curr_limit = maxWeight, prev_port = 0;
        for (int count = 0; count < maxBoxes && idx < n; ++idx) {
            if (boxes[idx][1] <= curr_limit) {
                if (prev_port != boxes[idx][0]) {
                    prev_port = boxes[idx][0];
                    ++trips;
                }
                curr_limit -= boxes[idx][1];
                ++count;
            }
        }
        ++trips;
    }
    return trips;
}
```
The algorithm works as follows:
1. Initialize `trips` to store minimum trips, `idx` to traverse boxes, length `n` of boxes.
2. Create a while loop, while `idx` is less than `n`, repeating steps 3-9.
3. Set `curr_limit` as the maximum weight to keep track of remaining weight allowed, and set `prev_port` to 0 as the initial previous port.
4. Run a for loop upto `maxBoxes` and `idx` less than `n`.
5. Check if the `weights_i` from boxes less than or equal to the `curr_limit`, if yes, go to step 6, else break.
6. If `ports_i` is not equal to the `prev_port`, update the `prev_port` with the value of `ports_i` and increment `trips`.
7. Decrement the `curr_limit` by the value of `weights_i`.
8. Increment the counter for the inner for loop (for the number of boxes).
9. Increment the `trips`.
10. Return the value of `trips`.

## A solution in C++

```cpp
int min_trips(vector<vector<int>> &boxes, int portsCount, int maxBoxes, int maxWeight) {
    int trips = 0, idx = 0, n = boxes.size();
    while (idx < n) {
        int curr_limit = maxWeight, prev_port = 0;
        for (int count = 0; count < maxBoxes && idx < n; ++idx) {
            if (boxes[idx][1] <= curr_limit) {
                if (prev_port != boxes[idx][0]) {
                    prev_port = boxes[idx][0];
                    ++trips;
                }
                curr_limit -= boxes[idx][1];
                ++count;
            }
        }
        ++trips;
    }
    return trips;
}
```
The algorithm works as follows:
1. Initialize `trips` to store minimum trips, `idx` to traverse boxes, length `n` of boxes.
2. Create a while loop, while `idx` is less than `n`, repeating steps 3-9.
3. Set `curr_limit` as the maximum weight to keep track of remaining weight allowed, and set `prev_port` to 0 as the initial previous port.
4. Run a for loop upto `maxBoxes` and `idx` less than `n`.
5. Check if the `weights_i` from boxes less than or equal to the `curr_limit`, if yes, go to step 6, else break.
6. If `ports_i` is not equal to the `prev_port`, update the `prev_port` with the value of `ports_i` and increment `trips`.
7. Decrement the `curr_limit` by the value of `weights_i`.
8. Increment the counter for the inner for loop (for the number of boxes).
9. Increment the `trips`.
10. Return the value of `trips`.

## A solution in Python

```python
def min_trips(boxes, portsCount, maxBoxes, maxWeight):
    trips = 0
    idx = 0
    n = len(boxes)
    while idx < n:
        curr_limit = maxWeight
        prev_port = 0
        count = 0
        while count < maxBoxes and idx < n:
            if boxes[idx][1] <= curr_limit:
                if prev_port != boxes[idx][0]:
                    prev_port = boxes[idx][0]
                    trips += 1
                curr_limit -= boxes[idx][1]
                count += 1
                idx += 1
            else:
                break
        trips += 1
    return trips
```
The algorithm works as follows:
1. Initialize `trips` to store minimum trips, `idx` to traverse boxes, length `n` of boxes.
2. Create a while loop, while `idx` is less than `n`, repeating steps 3-9.
3. Set `curr_limit` as the maximum weight to keep track of remaining weight allowed, and set `prev_port` to 0 as the initial previous port.
4. Run a for loop upto `maxBoxes` and `idx` less than `n`.
5. Check if the `weights_i` from boxes less than or equal to the `curr_limit`, if yes, go to step 6, else break.
6. If `ports_i` is not equal to the `prev_port`, update the `prev_port` with the value of `ports_i` and increment `trips`.
7. Decrement the `curr_limit` by the value of `weights_i`.
8. Increment the counter for the inner for loop (for the number of boxes).
9. Increment the `trips`.
10. Return the value of `trips`.

## A solution in Javascript

```javascript
function min_trips(boxes, portsCount, maxBoxes, maxWeight) {
    let trips = 0, idx = 0, n = boxes.length;
    while (idx < n) {
        let curr_limit = maxWeight, prev_port = 0;
        for (let count = 0; count < maxBoxes && idx < n; ++idx) {
            if (boxes[idx][1] <= curr_limit) {
                if (prev_port !== boxes[idx][0]) {
                    prev_port = boxes[idx][0];
                    trips += 1;
                }
                curr_limit -= boxes[idx][1];
                count += 1;
            }
        }
        trips += 1;
    }
    return trips;
}
```
The algorithm works as follows:
1. Initialize `trips` to store minimum trips, `idx` to traverse boxes, length `n` of boxes.
2. Create a while loop, while `idx` is less than `n`, repeating steps 3-9.
3. Set `curr_limit` as the maximum weight to keep track of remaining weight allowed, and set `prev_port` to 0 as the initial previous port.
4. Run a for loop upto `maxBoxes` and `idx` less than `n`.
5. Check if the `weights_i` from boxes less than or equal to the `curr_limit`, if yes, go to step 6, else break.
6. If `ports_i` is not equal to the `prev_port`, update the `prev_port` with the value of `ports_i` and increment `trips`.
7. Decrement the `curr_limit` by the value of `weights_i`.
8. Increment the counter for the inner for loop (for the number of boxes).
9. Increment the `trips`.
10. Return the value of `trips`.


# Count of Matches in Tournament

- slug: count-of-matches-in-tournament
- difficulty: Easy

You are given an integer `n`, the number of teams in a tournament that has strange rules:

*   If the current number of teams is **even**, each team gets paired with another team. A total of `n / 2` matches are played, and `n / 2` teams advance to the next round.
*   If the current number of teams is **odd**, one team randomly advances in the tournament, and the rest gets paired. A total of `(n - 1) / 2` matches are played, and `(n - 1) / 2 + 1` teams advance to the next round.

Return _the number of matches played in the tournament until a winner is decided._

**Example 1:**

**Input:** n = 7
**Output:** 6
**Explanation:** Details of the tournament:
- 1st Round: Teams = 7, Matches = 3, and 4 teams advance.
- 2nd Round: Teams = 4, Matches = 2, and 2 teams advance.
- 3rd Round: Teams = 2, Matches = 1, and 1 team is declared the winner.
Total number of matches = 3 + 2 + 1 = 6.

**Example 2:**

**Input:** n = 14
**Output:** 13
**Explanation:** Details of the tournament:
- 1st Round: Teams = 14, Matches = 7, and 7 teams advance.
- 2nd Round: Teams = 7, Matches = 3, and 4 teams advance.
- 3rd Round: Teams = 4, Matches = 2, and 2 teams advance.
- 4th Round: Teams = 2, Matches = 1, and 1 team is declared the winner.
Total number of matches = 7 + 3 + 2 + 1 = 13.

**Constraints:**

*   `1 <= n <= 200`

## A solution in Java

```java
public int numberOfMatches(int n) {
    int matches = 0;
    while (n > 1) {
        matches += n / 2;
        n = (n + 1) / 2;
    }
    return matches;
}
```
The algorithm starts with `n` teams and initializes a `matches` counter with 0. In each iteration of the loop, it calculates the number of matches played in the current round and adds it to the `matches` counter. Then, the number of teams advancing to the next round is calculated as `(n + 1) / 2`. The loop continues until there is a single winner left, i.e., `n === 1`. Finally, the total number of matches played throughout the tournament is returned.

## A solution in C++

```cpp
int numberOfMatches(int n) {
    int matches = 0;
    while (n > 1) {
        matches += n / 2;
        n = (n + 1) / 2;
    }
    return matches;
}
```
The algorithm starts with `n` teams and initializes a `matches` counter with 0. In each iteration of the loop, it calculates the number of matches played in the current round and adds it to the `matches` counter. Then, the number of teams advancing to the next round is calculated as `(n + 1) / 2`. The loop continues until there is a single winner left, i.e., `n === 1`. Finally, the total number of matches played throughout the tournament is returned.

## A solution in Python

```python
def numberOfMatches(n: int) -> int:
    matches = 0
    while n > 1:
        matches += n // 2
        n = (n + 1) // 2
    return matches
```
The algorithm starts with `n` teams and initializes a `matches` counter with 0. In each iteration of the loop, it calculates the number of matches played in the current round and adds it to the `matches` counter. Then, the number of teams advancing to the next round is calculated as `(n + 1) / 2`. The loop continues until there is a single winner left, i.e., `n === 1`. Finally, the total number of matches played throughout the tournament is returned.

## A solution in Javascript

```javascript
function numberOfMatches(n) {
    let matches = 0;
    while (n > 1) {
        matches += Math.floor(n / 2);
        n = Math.floor((n + 1) / 2);
    }
    return matches;
}
```
The algorithm starts with `n` teams and initializes a `matches` counter with 0. In each iteration of the loop, it calculates the number of matches played in the current round and adds it to the `matches` counter. Then, the number of teams advancing to the next round is calculated as `(n + 1) / 2`. The loop continues until there is a single winner left, i.e., `n === 1`. Finally, the total number of matches played throughout the tournament is returned.


# Partitioning Into Minimum Number Of Deci-Binary Numbers

- slug: partitioning-into-minimum-number-of-deci-binary-numbers
- difficulty: Medium

A decimal number is called **deci-binary** if each of its digits is either `0` or `1` without any leading zeros. For example, `101` and `1100` are **deci-binary**, while `112` and `3001` are not.

Given a string `n` that represents a positive decimal integer, return _the **minimum** number of positive **deci-binary** numbers needed so that they sum up to_ `n`_._

**Example 1:**

**Input:** n =  "32 "
**Output:** 3
**Explanation:** 10 + 11 + 11 = 32

**Example 2:**

**Input:** n =  "82734 "
**Output:** 8

**Example 3:**

**Input:** n =  "27346209830709182346 "
**Output:** 9

**Constraints:**

*   `1 <= n.length <= 105`
*   `n` consists of only digits.
*   `n` does not contain any leading zeros and represents a positive integer.

## A solution in Java

```java
public boolean containsPattern(int[] arr, int m, int k) {
    int n = arr.length;
    if (m * k > n) return false;

    for (int i = 0; i + m * k <= n; i++) {
        boolean patternFound = true;
        for (int j = 0; j < m; j++) {
            for (int l = 1; l < k; l++) {
                if (arr[i + j] != arr[i + j + l * m]) {
                    patternFound = false;
                    break;
                }
            }
            if (!patternFound) break;
        }
        if (patternFound) return true;
    }
    return false;
}
```
1. Check if the condition `m * k > n` is true, if so return false because it is impossible to find a subarray pattern of length m repeated k times if their product is greater than the array length.
2. Iterate through the array, checking for the presence of the pattern. Create a nested loop over the pattern length(m) and repetitions(k).
3. If at any point a pattern doesn't match, mark patternFound as false and break the inner loop.
4. If a valid pattern is found, return true. Otherwise, continue searching.
5. If no valid pattern is found by the end of the iteration, return false.

## A solution in C++

```cpp
bool containsPattern(vector<int>& arr, int m, int k) {
    int n = arr.size();
    if (m * k > n) return false;

    for (int i = 0; i + m * k <= n; i++) {
        bool patternFound = true;
        for (int j = 0; j < m; j++) {
            for (int l = 1; l < k; l++) {
                if (arr[i + j] != arr[i + j + l * m]) {
                    patternFound = false;
                    break;
                }
            }
            if (!patternFound) break;
        }
        if (patternFound) return true;
    }
    return false;
}
```
1. Check if the condition `m * k > n` is true, if so return false because it is impossible to find a subarray pattern of length m repeated k times if their product is greater than the array length.
2. Iterate through the array, checking for the presence of the pattern. Create a nested loop over the pattern length(m) and repetitions(k).
3. If at any point a pattern doesn't match, mark patternFound as false and break the inner loop.
4. If a valid pattern is found, return true. Otherwise, continue searching.
5. If no valid pattern is found by the end of the iteration, return false.

## A solution in Python

```python
def containsPattern(arr, m, k):
    n = len(arr)
    if m * k > n:
        return False

    for i in range(n - m * k + 1):
        patternFound = True
        for j in range(m):
            for l in range(1, k):
                if arr[i + j] != arr[i + j + l * m]:
                    patternFound = False
                    break
            if not patternFound:
                break
        if patternFound:
            return True
    return False
```
1. Check if the condition `m * k > n` is true, if so return false because it is impossible to find a subarray pattern of length m repeated k times if their product is greater than the array length.
2. Iterate through the array, checking for the presence of the pattern. Create a nested loop over the pattern length(m) and repetitions(k).
3. If at any point a pattern doesn't match, mark patternFound as false and break the inner loop.
4. If a valid pattern is found, return true. Otherwise, continue searching.
5. If no valid pattern is found by the end of the iteration, return false.

## A solution in Javascript

```javascript
function containsPattern(arr, m, k) {
    const n = arr.length;
    if (m * k > n) return false;

    for (let i = 0; i + m * k <= n; i++) {
        let patternFound = true;
        for (let j = 0; j < m; j++) {
            for (let l = 1; l < k; l++) {
                if (arr[i + j] !== arr[i + j + l * m]) {
                    patternFound = false;
                    break;
                }
            }
            if (!patternFound) break;
        }
        if (patternFound) return true;
    }
    return false;
}
```
1. Check if the condition `m * k > n` is true, if so return false because it is impossible to find a subarray pattern of length m repeated k times if their product is greater than the array length.
2. Iterate through the array, checking for the presence of the pattern. Create a nested loop over the pattern length(m) and repetitions(k).
3. If at any point a pattern doesn't match, mark patternFound as false and break the inner loop.
4. If a valid pattern is found, return true. Otherwise, continue searching.
5. If no valid pattern is found by the end of the iteration, return false.


# Stone Game VII

- slug: stone-game-vii
- difficulty: Medium

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

There are `n` stones arranged in a row. On each player's turn, they can **remove** either the leftmost stone or the rightmost stone from the row and receive points equal to the **sum** of the remaining stones' values in the row. The winner is the one with the higher score when there are no stones left to remove.

Bob found that he will always lose this game (poor Bob, he always loses), so he decided to **minimize the score's difference**. Alice's goal is to **maximize the difference** in the score.

Given an array of integers `stones` where `stones[i]` represents the value of the `ith` stone **from the left**, return _the **difference** in Alice and Bob's score if they both play **optimally**._

**Example 1:**

**Input:** stones = \[5,3,1,4,2\]
**Output:** 6
**Explanation:**
- Alice removes 2 and gets 5 + 3 + 1 + 4 = 13 points. Alice = 13, Bob = 0, stones = \[5,3,1,4\].
- Bob removes 5 and gets 3 + 1 + 4 = 8 points. Alice = 13, Bob = 8, stones = \[3,1,4\].
- Alice removes 3 and gets 1 + 4 = 5 points. Alice = 18, Bob = 8, stones = \[1,4\].
- Bob removes 1 and gets 4 points. Alice = 18, Bob = 12, stones = \[4\].
- Alice removes 4 and gets 0 points. Alice = 18, Bob = 12, stones = \[\].
The score difference is 18 - 12 = 6.

**Example 2:**

**Input:** stones = \[7,90,5,1,100,10,10,2\]
**Output:** 122

**Constraints:**

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

## A solution in Java

```java
public int getMaxLen(int[] nums) {
    int maxLength = 0, currentLen = 0, currentNegLen = 0;

    for (int num : nums) {
        if (num > 0) {
            ++currentLen;
            if (currentNegLen > 0) ++currentNegLen;
        } else if (num < 0) {
            int tmp = currentLen;
            currentLen = currentNegLen;
            currentNegLen = tmp + 1;
        } else {
            currentLen = 0;
            currentNegLen = 0;
        }
        maxLength = Math.max(maxLength, currentLen);
    }

    return maxLength;
}
```
The algorithm iterates through the array, maintaining two lengths: `currentLen` for the length of the current subarray with a positive product, and `currentNegLen` for the length of the current subarray with a negative product.

1. If the current number is positive, increment `currentLen`, and increment `currentNegLen` if it is greater than zero.
2. If the current number is negative, swap `currentLen` and `currentNegLen`, and increment `currentNegLen` by 1.
3. If the current number is zero, reset both `currentLen` and `currentNegLen` to zero.

At each step, update the maximum length with the value of `currentLen`.

After iterating through the array, the maximum length found during the iterations is returned.

## A solution in C++

```cpp
int getMaxLen(vector<int>& nums) {
    int maxLength = 0, currentLen = 0, currentNegLen = 0;

    for (int num : nums) {
        if (num > 0) {
            ++currentLen;
            if (currentNegLen > 0) ++currentNegLen;
        } else if (num < 0) {
            int tmp = currentLen;
            currentLen = currentNegLen;
            currentNegLen = tmp + 1;
        } else {
            currentLen = 0;
            currentNegLen = 0;
        }
        maxLength = max(maxLength, currentLen);
    }

    return maxLength;
}
```
The algorithm iterates through the array, maintaining two lengths: `currentLen` for the length of the current subarray with a positive product, and `currentNegLen` for the length of the current subarray with a negative product.

1. If the current number is positive, increment `currentLen`, and increment `currentNegLen` if it is greater than zero.
2. If the current number is negative, swap `currentLen` and `currentNegLen`, and increment `currentNegLen` by 1.
3. If the current number is zero, reset both `currentLen` and `currentNegLen` to zero.

At each step, update the maximum length with the value of `currentLen`.

After iterating through the array, the maximum length found during the iterations is returned.

## A solution in Python

```python
def getMaxLen(nums):
    maxLength = currentLen = currentNegLen = 0

    for num in nums:
        if num > 0:
            currentLen += 1
            if currentNegLen > 0:
                currentNegLen += 1
        elif num < 0:
            currentLen, currentNegLen = currentNegLen, currentLen + 1
        else:
            currentLen = currentNegLen = 0
        maxLength = max(maxLength, currentLen)

    return maxLength
```
The algorithm iterates through the array, maintaining two lengths: `currentLen` for the length of the current subarray with a positive product, and `currentNegLen` for the length of the current subarray with a negative product.

1. If the current number is positive, increment `currentLen`, and increment `currentNegLen` if it is greater than zero.
2. If the current number is negative, swap `currentLen` and `currentNegLen`, and increment `currentNegLen` by 1.
3. If the current number is zero, reset both `currentLen` and `currentNegLen` to zero.

At each step, update the maximum length with the value of `currentLen`.

After iterating through the array, the maximum length found during the iterations is returned.

## A solution in Javascript

```javascript
function getMaxLen(nums) {
    let maxLength = 0, currentLen = 0, currentNegLen = 0;

    for (const num of nums) {
        if (num > 0) {
            ++currentLen;
            if (currentNegLen > 0) ++currentNegLen;
        } else if (num < 0) {
            [currentLen, currentNegLen] = [currentNegLen, currentLen + 1];
        } else {
            currentLen = 0;
            currentNegLen = 0;
        }
        maxLength = Math.max(maxLength, currentLen);
    }

    return maxLength;
}
```
The algorithm iterates through the array, maintaining two lengths: `currentLen` for the length of the current subarray with a positive product, and `currentNegLen` for the length of the current subarray with a negative product.

1. If the current number is positive, increment `currentLen`, and increment `currentNegLen` if it is greater than zero.
2. If the current number is negative, swap `currentLen` and `currentNegLen`, and increment `currentNegLen` by 1.
3. If the current number is zero, reset both `currentLen` and `currentNegLen` to zero.

At each step, update the maximum length with the value of `currentLen`.

After iterating through the array, the maximum length found during the iterations is returned.


# Count Ways to Distribute Candies

- slug: count-ways-to-distribute-candies
- difficulty: Hard

There are `n` **unique** candies (labeled `1` through `n`) and `k` bags. You are asked to distribute **all** the candies into the bags such that every bag has **at least** one candy.

There can be multiple ways to distribute the candies. Two ways are considered **different** if the candies in one bag in the first way are not all in the same bag in the second way. The order of the bags and the order of the candies within each bag do not matter.

For example, `(1), (2,3)` and `(2), (1,3)` are considered different because candies `2` and `3` in the bag `(2,3)` in the first way are not in the same bag in the second way (they are split between the bags `(2)` and `(1,3)`). However, `(1), (2,3)` and `(3,2), (1)` are considered the same because the candies in each bag are all in the same bags in both ways.

Given two integers, `n` and `k`, return _the **number** of different ways to distribute the candies_. As the answer may be too large, return it **modulo** `109 + 7`.

**Example 1:**

**Input:** n = 3, k = 2
**Output:** 3
**Explanation:** You can distribute 3 candies into 2 bags in 3 ways:
(1), (2,3)
(1,2), (3)
(1,3), (2)

**Example 2:**

**Input:** n = 4, k = 2
**Output:** 7
**Explanation:** You can distribute 4 candies into 2 bags in 7 ways:
(1), (2,3,4)
(1,2), (3,4)
(1,3), (2,4)
(1,4), (2,3)
(1,2,3), (4)
(1,2,4), (3)
(1,3,4), (2)

**Example 3:**

**Input:** n = 20, k = 5
**Output:** 206085257
**Explanation:** You can distribute 20 candies into 5 bags in 1881780996 ways. 1881780996 modulo 109 + 7 = 206085257.

**Constraints:**

*   `1 <= k <= n <= 1000`

## A solution in Java

```java
public int numTrees(int n) {
    int[] dp = new int[n + 1];
    dp[0] = 1;
    dp[1] = 1;

    for (int i = 2; i <= n; i++) {
        for (int j = 0; j < i; j++) {
            dp[i] += dp[j] * dp[i - 1 - j];
            dp[i] %= 1000000007;
        }
    }

    return dp[n];
}
```
The problem can be solved using dynamic programming. We can define a function `numTrees(i)` that returns the number of possible binary search trees with `i` nodes. We iterate through each possible number of nodes `i` from 2 to `n`. For each of these, we iterate through all possible left sub-tree sizes `j` (from 0 to i-1). Now, the total number of possible right sub-trees for the current `i` will be `i - 1 - j`.

Thus, the total number of possible BSTs for the current `i` will be the Cartesian product of the possible left sub-trees and possible right sub-trees. Hence, we can update `dp[i]` as `dp[i] += dp[j] * dp[i - 1 - j]`.

We continue doing this for all values of `i` until we reach `n`. The final answer will be `dp[n]`, the number of possible BSTs with `n` nodes. Note that we take the answer modulo 10^9 + 7 as the result can be quite large.

## A solution in C++

```cpp
#include <vector>

int numTrees(int n) {
    std::vector<int> dp(n + 1, 0);
    dp[0] = 1;
    dp[1] = 1;

    for (int i = 2; i <= n; ++i) {
        for (int j = 0; j < i; ++j) {
            dp[i] += dp[j] * dp[i - 1 - j];
            dp[i] %= 1000000007;
        }
    }

    return dp[n];
}
```
The problem can be solved using dynamic programming. We can define a function `numTrees(i)` that returns the number of possible binary search trees with `i` nodes. We iterate through each possible number of nodes `i` from 2 to `n`. For each of these, we iterate through all possible left sub-tree sizes `j` (from 0 to i-1). Now, the total number of possible right sub-trees for the current `i` will be `i - 1 - j`.

Thus, the total number of possible BSTs for the current `i` will be the Cartesian product of the possible left sub-trees and possible right sub-trees. Hence, we can update `dp[i]` as `dp[i] += dp[j] * dp[i - 1 - j]`.

We continue doing this for all values of `i` until we reach `n`. The final answer will be `dp[n]`, the number of possible BSTs with `n` nodes. Note that we take the answer modulo 10^9 + 7 as the result can be quite large.

## A solution in Python

```python
def numTrees(n: int) -> int:
    dp = [0] * (n + 1)
    dp[0] = 1
    dp[1] = 1

    for i in range(2, n + 1):
        for j in range(i):
            dp[i] += dp[j] * dp[i - 1 - j]
            dp[i] %= (10**9 + 7)

    return dp[n]
```
The problem can be solved using dynamic programming. We can define a function `numTrees(i)` that returns the number of possible binary search trees with `i` nodes. We iterate through each possible number of nodes `i` from 2 to `n`. For each of these, we iterate through all possible left sub-tree sizes `j` (from 0 to i-1). Now, the total number of possible right sub-trees for the current `i` will be `i - 1 - j`.

Thus, the total number of possible BSTs for the current `i` will be the Cartesian product of the possible left sub-trees and possible right sub-trees. Hence, we can update `dp[i]` as `dp[i] += dp[j] * dp[i - 1 - j]`.

We continue doing this for all values of `i` until we reach `n`. The final answer will be `dp[n]`, the number of possible BSTs with `n` nodes. Note that we take the answer modulo 10^9 + 7 as the result can be quite large.

## A solution in Javascript

```javascript
function numTrees(n) {
    const dp = Array(n + 1).fill(0);
    dp[0] = 1;
    dp[1] = 1;

    for (let i = 2; i <= n; i++) {
        for (let j = 0; j < i; j++) {
            dp[i] += dp[j] * dp[i - 1 - j];
            dp[i] %= 1000000007;
        }
    }

    return dp[n];
}
```
The problem can be solved using dynamic programming. We can define a function `numTrees(i)` that returns the number of possible binary search trees with `i` nodes. We iterate through each possible number of nodes `i` from 2 to `n`. For each of these, we iterate through all possible left sub-tree sizes `j` (from 0 to i-1). Now, the total number of possible right sub-trees for the current `i` will be `i - 1 - j`.

Thus, the total number of possible BSTs for the current `i` will be the Cartesian product of the possible left sub-trees and possible right sub-trees. Hence, we can update `dp[i]` as `dp[i] += dp[j] * dp[i - 1 - j]`.

We continue doing this for all values of `i` until we reach `n`. The final answer will be `dp[n]`, the number of possible BSTs with `n` nodes. Note that we take the answer modulo 10^9 + 7 as the result can be quite large.


# Reformat Phone Number

- slug: reformat-phone-number
- difficulty: Easy

You are given a phone number as a string `number`. `number` consists of digits, spaces `' '`, and/or dashes `'-'`.

You would like to reformat the phone number in a certain manner. Firstly, **remove** all spaces and dashes. Then, **group** the digits from left to right into blocks of length 3 **until** there are 4 or fewer digits. The final digits are then grouped as follows:

*   2 digits: A single block of length 2.
*   3 digits: A single block of length 3.
*   4 digits: Two blocks of length 2 each.

The blocks are then joined by dashes. Notice that the reformatting process should **never** produce any blocks of length 1 and produce **at most** two blocks of length 2.

Return _the phone number after formatting._

**Example 1:**

**Input:** number =  "1-23-45 6 "
**Output:**  "123-456 "
**Explanation:** The digits are  "123456 ".
Step 1: There are more than 4 digits, so group the next 3 digits. The 1st block is  "123 ".
Step 2: There are 3 digits remaining, so put them in a single block of length 3. The 2nd block is  "456 ".
Joining the blocks gives  "123-456 ".

**Example 2:**

**Input:** number =  "123 4-567 "
**Output:**  "123-45-67 "
**Explanation:** The digits are  "1234567 ".
Step 1: There are more than 4 digits, so group the next 3 digits. The 1st block is  "123 ".
Step 2: There are 4 digits left, so split them into two blocks of length 2. The blocks are  "45 " and  "67 ".
Joining the blocks gives  "123-45-67 ".

**Example 3:**

**Input:** number =  "123 4-5678 "
**Output:**  "123-456-78 "
**Explanation:** The digits are  "12345678 ".
Step 1: The 1st block is  "123 ".
Step 2: The 2nd block is  "456 ".
Step 3: There are 2 digits left, so put them in a single block of length 2. The 3rd block is  "78 ".
Joining the blocks gives  "123-456-78 ".

**Constraints:**

*   `2 <= number.length <= 100`
*   `number` consists of digits and the characters `'-'` and `' '`.
*   There are at least **two** digits in `number`.

## A solution in Java

```java
import java.util.HashMap;

public int minSubarray(int[] nums, int p) {
    int n = nums.length, need = 0, cur = 0, res = n;
    for (int num : nums) need = (need + num) % p;
    if (need == 0) return 0;
    HashMap<Integer, Integer> last_seen = new HashMap<>();
    last_seen.put(cur, -1);
    for (int i = 0; i < n; ++i) {
        cur = (cur + nums[i]) % p;
        last_seen.put(cur, i);
        int want = (cur - need + p) % p;
        if (last_seen.containsKey(want)) {
            res = Math.min(res, i-last_seen.get(want));
        }
    }
    return res == n ? -1 : res;
}
```
The algorithm starts by calculating the sum modulo p of the entire array (called "need"). If the sum is already divisible by p (i.e., need is 0), it returns 0 as no elements need to be removed.

Next, we define an unordered_map (in C++), a HashMap (in Java), a dictionary (in Python), or a Map (in JavaScript) called "last_seen" which keeps track of the last_seen index where each "cur" value appears. "cur" represents the current accumulated sum modulo p.

While iterating through the array, we calculate the "cur" value and put it into the last_seen data structure with the corresponding index i as the value. We also calculate the "want" value, which is the value we need in last_seen to ensure the sum of the remaining elements is divisible by p. If "want" is in last_seen, we update the minimum result length with the difference between the current index and the index where the "want" value was last seen in last_seen.

Finally, if the result length is still equal to the length of the array, it means it is impossible to get a subarray whose sum is divisible by p, so we return -1; otherwise, we return the result length.

## A solution in C++

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

int minSubarray(vector<int>& nums, int p) {
    int n = nums.size(), need = 0, cur = 0, res = n;
    for (int num : nums) need = (need + num) % p;
    if (need == 0) return 0;
    unordered_map<int, int> last_seen;
    last_seen[cur] = -1;
    for (int i = 0; i < n; ++i) {
        cur = (cur + nums[i]) % p;
        last_seen[cur] = i;
        int want = (cur - need + p) % p;
        if (last_seen.count(want)) {
            res = min(res, i-last_seen[want]);
        }
    }
    return res == n ? -1 : res;
}
```
The algorithm starts by calculating the sum modulo p of the entire array (called "need"). If the sum is already divisible by p (i.e., need is 0), it returns 0 as no elements need to be removed.

Next, we define an unordered_map (in C++), a HashMap (in Java), a dictionary (in Python), or a Map (in JavaScript) called "last_seen" which keeps track of the last_seen index where each "cur" value appears. "cur" represents the current accumulated sum modulo p.

While iterating through the array, we calculate the "cur" value and put it into the last_seen data structure with the corresponding index i as the value. We also calculate the "want" value, which is the value we need in last_seen to ensure the sum of the remaining elements is divisible by p. If "want" is in last_seen, we update the minimum result length with the difference between the current index and the index where the "want" value was last seen in last_seen.

Finally, if the result length is still equal to the length of the array, it means it is impossible to get a subarray whose sum is divisible by p, so we return -1; otherwise, we return the result length.

## A solution in Python

```python
def min_subarray(nums, p):
    n = len(nums)
    need, cur, res = 0, 0, n
    last_seen = {}

    for num in nums:
        need = (need + num) % p

    if need == 0:
        return 0

    last_seen[cur] = -1
    for i, num in enumerate(nums):
        cur = (cur + num) % p
        last_seen[cur] = i
        want = (cur - need + p) % p
        if want in last_seen:
            res = min(res, i - last_seen[want])

    return res if res != n else -1
```
The algorithm starts by calculating the sum modulo p of the entire array (called "need"). If the sum is already divisible by p (i.e., need is 0), it returns 0 as no elements need to be removed.

Next, we define an unordered_map (in C++), a HashMap (in Java), a dictionary (in Python), or a Map (in JavaScript) called "last_seen" which keeps track of the last_seen index where each "cur" value appears. "cur" represents the current accumulated sum modulo p.

While iterating through the array, we calculate the "cur" value and put it into the last_seen data structure with the corresponding index i as the value. We also calculate the "want" value, which is the value we need in last_seen to ensure the sum of the remaining elements is divisible by p. If "want" is in last_seen, we update the minimum result length with the difference between the current index and the index where the "want" value was last seen in last_seen.

Finally, if the result length is still equal to the length of the array, it means it is impossible to get a subarray whose sum is divisible by p, so we return -1; otherwise, we return the result length.

## A solution in Javascript

```javascript
function minSubarray(nums, p) {
    const n = nums.length;
    let need = 0, cur = 0, res = n;
    const last_seen = new Map();

    for (const num of nums)
        need = (need + num) % p;

    if (need === 0)
        return 0;

    last_seen.set(cur, -1);
    for (let i = 0; i < n; ++i) {
        cur = (cur + nums[i]) % p;
        last_seen.set(cur, i);
        const want = (cur - need + p) % p;
        if (last_seen.has(want))
            res = Math.min(res, i - last_seen.get(want));
    }

    return res === n ? -1 : res;
}
```
The algorithm starts by calculating the sum modulo p of the entire array (called "need"). If the sum is already divisible by p (i.e., need is 0), it returns 0 as no elements need to be removed.

Next, we define an unordered_map (in C++), a HashMap (in Java), a dictionary (in Python), or a Map (in JavaScript) called "last_seen" which keeps track of the last_seen index where each "cur" value appears. "cur" represents the current accumulated sum modulo p.

While iterating through the array, we calculate the "cur" value and put it into the last_seen data structure with the corresponding index i as the value. We also calculate the "want" value, which is the value we need in last_seen to ensure the sum of the remaining elements is divisible by p. If "want" is in last_seen, we update the minimum result length with the difference between the current index and the index where the "want" value was last seen in last_seen.

Finally, if the result length is still equal to the length of the array, it means it is impossible to get a subarray whose sum is divisible by p, so we return -1; otherwise, we return the result length.