# Count Ways To Build Good Strings

- slug: count-ways-to-build-good-strings
- difficulty: Medium

Given the integers `zero`, `one`, `low`, and `high`, we can construct a string by starting with an empty string, and then at each step perform either of the following:

*   Append the character `'0'` `zero` times.
*   Append the character `'1'` `one` times.

This can be performed any number of times.

A **good** string is a string constructed by the above process having a **length** between `low` and `high` (**inclusive**).

Return _the number of **different** good strings that can be constructed satisfying these properties._ Since the answer can be large, return it **modulo** `109 + 7`.

**Example 1:**

**Input:** low = 3, high = 3, zero = 1, one = 1
**Output:** 8
**Explanation:**
One possible valid good string is  "011 ".
It can be constructed as follows:  " " ->  "0 " ->  "01 " ->  "011 ".
All binary strings from  "000 " to  "111 " are good strings in this example.

**Example 2:**

**Input:** low = 2, high = 3, zero = 1, one = 2
**Output:** 5
**Explanation:** The good strings are  "00 ",  "11 ",  "000 ",  "110 ", and  "011 ".

**Constraints:**

*   `1 <= low <= high <= 105`
*   `1 <= zero, one <= low`

## A solution in Java

```java
public int modPow(long x, int n, int mod) {
    long res = 1;
    while (n > 0) {
        if (n % 2 == 1) {
            res = (res * x) % mod;
        }
        x = (x * x) % mod;
        n /= 2;
    }
    return (int) res;
}

public int goodStrings(int low, int high, int zero, int one) {
    long mod = 1000000007;
    return (int) (((modPow(2, high, (int) mod) - modPow(2, low - 1, (int) mod) + 1) * (zero + 1)) % mod * (one + 1)) % mod;
}
```

    The algorithm first has a helper function called `modPow` to calculate the modular power x^n % mod. It's using exponentiation by squaring to compute the modular exponent in logarithmic time. With this helper function, the main function `goodStrings` is calculating the number of different good strings using the formula:

```
((2^high - 2^(low-1) + 1) * (zero + 1)) % mod * (one + 1)) % mod
```
In this formula, `2^high` is the number of binary strings up to length `high`, while `2^(low-1)` is the number of binary strings up to length `low - 1`. The difference between them gives the number of binary strings in the range `[low, high]`. We add 1 at the end of the difference `(2^high - 2^(low-1) + 1)` to make the formula correct in terms of the problem constraints.

The `(zero+1)*(one+1)` part considers all possible combinations of appending `zero` times '0' and '`one`' times '1'. Since we can append '0' and '1' for these many times, we need to multiply the combinations with our difference count. And finally, we take the result modulo 10^9+7 as required.

## A solution in C++

```cpp
int modPow(long x, int n, int mod) {
    long res = 1;
    while (n > 0) {
        if (n % 2 == 1) {
            res = (res * x) % mod;
        }
        x = (x * x) % mod;
        n /= 2;
    }
    return (int) res;
}

int goodStrings(int low, int high, int zero, int one) {
    long mod = 1000000007;
    return (((modPow(2, high, mod) - modPow(2, low - 1, mod) + 1) * (zero + 1)) % mod * (one + 1)) % mod;
}
```

    The algorithm first has a helper function called `modPow` to calculate the modular power x^n % mod. It's using exponentiation by squaring to compute the modular exponent in logarithmic time. With this helper function, the main function `goodStrings` is calculating the number of different good strings using the formula:

```
((2^high - 2^(low-1) + 1) * (zero + 1)) % mod * (one + 1)) % mod
```
In this formula, `2^high` is the number of binary strings up to length `high`, while `2^(low-1)` is the number of binary strings up to length `low - 1`. The difference between them gives the number of binary strings in the range `[low, high]`. We add 1 at the end of the difference `(2^high - 2^(low-1) + 1)` to make the formula correct in terms of the problem constraints.

The `(zero+1)*(one+1)` part considers all possible combinations of appending `zero` times '0' and '`one`' times '1'. Since we can append '0' and '1' for these many times, we need to multiply the combinations with our difference count. And finally, we take the result modulo 10^9+7 as required.

## A solution in Python

```python
def modPow(x, n, mod):
    res = 1
    while n > 0:
        if n % 2 == 1:
            res = (res * x) % mod
        x = (x * x) % mod
        n //= 2
    return res

def goodStrings(low, high, zero, one):
    mod = 1000000007
    good_strs = ((modPow(2, high, mod) - modPow(2, low - 1, mod) + 1) * (zero + 1)) % mod
    return (good_strs * (one + 1)) % mod
```

    The algorithm first has a helper function called `modPow` to calculate the modular power x^n % mod. It's using exponentiation by squaring to compute the modular exponent in logarithmic time. With this helper function, the main function `goodStrings` is calculating the number of different good strings using the formula:

```
((2^high - 2^(low-1) + 1) * (zero + 1)) % mod * (one + 1)) % mod
```
In this formula, `2^high` is the number of binary strings up to length `high`, while `2^(low-1)` is the number of binary strings up to length `low - 1`. The difference between them gives the number of binary strings in the range `[low, high]`. We add 1 at the end of the difference `(2^high - 2^(low-1) + 1)` to make the formula correct in terms of the problem constraints.

The `(zero+1)*(one+1)` part considers all possible combinations of appending `zero` times '0' and '`one`' times '1'. Since we can append '0' and '1' for these many times, we need to multiply the combinations with our difference count. And finally, we take the result modulo 10^9+7 as required.

## A solution in Javascript

```javascript
function modPow(x, n, mod) {
    let res = 1;
    while (n > 0) {
        if (n % 2 === 1) {
            res = (res * x) % mod;
        }
        x = (x * x) % mod;
        n = Math.floor(n / 2);
    }
    return res;
}

function goodStrings(low, high, zero, one) {
    const mod = 1000000007;
    const good_strs = ((modPow(2, high, mod) - modPow(2, low - 1, mod) + 1) * (zero + 1)) % mod;
    return (good_strs * (one + 1)) % mod;
}
```

    The algorithm first has a helper function called `modPow` to calculate the modular power x^n % mod. It's using exponentiation by squaring to compute the modular exponent in logarithmic time. With this helper function, the main function `goodStrings` is calculating the number of different good strings using the formula:

```
((2^high - 2^(low-1) + 1) * (zero + 1)) % mod * (one + 1)) % mod
```
In this formula, `2^high` is the number of binary strings up to length `high`, while `2^(low-1)` is the number of binary strings up to length `low - 1`. The difference between them gives the number of binary strings in the range `[low, high]`. We add 1 at the end of the difference `(2^high - 2^(low-1) + 1)` to make the formula correct in terms of the problem constraints.

The `(zero+1)*(one+1)` part considers all possible combinations of appending `zero` times '0' and '`one`' times '1'. Since we can append '0' and '1' for these many times, we need to multiply the combinations with our difference count. And finally, we take the result modulo 10^9+7 as required.


# Most Profitable Path in a Tree

- slug: most-profitable-path-in-a-tree
- difficulty: Medium

There is an undirected tree with `n` nodes labeled from `0` to `n - 1`, rooted at node `0`. You are given a 2D integer array `edges` of length `n - 1` where `edges[i] = [ai, bi]` indicates that there is an edge between nodes `ai` and `bi` in the tree.

At every node `i`, there is a gate. You are also given an array of even integers `amount`, where `amount[i]` represents:

*   the price needed to open the gate at node `i`, if `amount[i]` is negative, or,
*   the cash reward obtained on opening the gate at node `i`, otherwise.

The game goes on as follows:

*   Initially, Alice is at node `0` and Bob is at node `bob`.
*   At every second, Alice and Bob **each** move to an adjacent node. Alice moves towards some **leaf node**, while Bob moves towards node `0`.
*   For **every** node along their path, Alice and Bob either spend money to open the gate at that node, or accept the reward. Note that:
    *   If the gate is **already open**, no price will be required, nor will there be any cash reward.
    *   If Alice and Bob reach the node **simultaneously**, they share the price/reward for opening the gate there. In other words, if the price to open the gate is `c`, then both Alice and Bob pay `c / 2` each. Similarly, if the reward at the gate is `c`, both of them receive `c / 2` each.
*   If Alice reaches a leaf node, she stops moving. Similarly, if Bob reaches node `0`, he stops moving. Note that these events are **independent** of each other.

Return _the **maximum** net income Alice can have if she travels towards the optimal leaf node._

**Example 1:**

**Input:** edges = \[\[0,1\],\[1,2\],\[1,3\],\[3,4\]\], bob = 3, amount = \[-2,4,2,-4,6\]
**Output:** 6
**Explanation:**
The above diagram represents the given tree. The game goes as follows:
- Alice is initially on node 0, Bob on node 3. They open the gates of their respective nodes.
  Alice's net income is now -2.
- Both Alice and Bob move to node 1.
  Since they reach here simultaneously, they open the gate together and share the reward.
  Alice's net income becomes -2 + (4 / 2) = 0.
- Alice moves on to node 3. Since Bob already opened its gate, Alice's income remains unchanged.
  Bob moves on to node 0, and stops moving.
- Alice moves on to node 4 and opens the gate there. Her net income becomes 0 + 6 = 6.
Now, neither Alice nor Bob can make any further moves, and the game ends.
It is not possible for Alice to get a higher net income.

**Example 2:**

**Input:** edges = \[\[0,1\]\], bob = 1, amount = \[-7280,2350\]
**Output:** -7280
**Explanation:**
Alice follows the path 0->1 whereas Bob follows the path 1->0.
Thus, Alice opens the gate at node 0 only. Hence, her net income is -7280.

**Constraints:**

*   `2 <= n <= 105`
*   `edges.length == n - 1`
*   `edges[i].length == 2`
*   `0 <= ai, bi < n`
*   `ai != bi`
*   `edges` represents a valid tree.
*   `1 <= bob < n`
*   `amount.length == n`
*   `amount[i]` is an **even** integer in the range `[-104, 104]`.

## A solution in Java

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

public class Solution {
    private void dfs(int node, int parent, int bob, int time, int[] aliceIncome, int[] res, int[] amount, Map<Integer, List<Integer>> tree) {
        if (time < bob || amount[node] >= 0) {
            aliceIncome[0] += amount[node];
        } else {
            aliceIncome[0] += amount[node] / 2;
        }
        amount[node] = 0;
        boolean isLeaf = true;
        for (int child : tree.get(node)) {
            if (child != parent) {
                isLeaf = false;
                int[] tempIncome = {aliceIncome[0]};
                dfs(child, node, bob, time + 1, tempIncome, res, amount, tree);
            }
        }
        if (isLeaf) {
            res[0] = Math.max(res[0], aliceIncome[0]);
        }
    }

    public int maxNetIncome(int[][] edges, int bob, int[] amount) {
        Map<Integer, List<Integer>> tree = new HashMap<>();
        for (int[] edge : edges) {
            tree.putIfAbsent(edge[0], new ArrayList<>());
            tree.putIfAbsent(edge[1], new ArrayList<>());
            tree.get(edge[0]).add(edge[1]);
            tree.get(edge[1]).add(edge[0]);
        }
        int[] res = {-100000};
        int[] aliceIncome = {0};
        dfs(0, -1, bob, 0, aliceIncome, res, amount, tree);
        return res[0];
    }
}
```
We will use a depth-first search (DFS) to calculate the net income for Alice as she travels towards the optimal leaf node. We create a tree using the given edges, and then call our DFS function starting at node 0.

In the DFS function, we distinguish between whether Alice has reached the node before Bob or not. If Alice has reached the node before Bob or if the gate at node i gives a reward (amount[i] >= 0), we add the price needed / cash reward to Alice's net income. If Alice and Bob reach the node simultaneously, we add half of the price needed / cash reward to Alice's net income. We set amount[node] to be 0 after calculating Alice's net income.

We then recursively call the DFS function for all child nodes (except the parent node), with the current node acting as the parent. If we reach a leaf node, we update the maximum net income for Alice.

Finally, we return the maximum net income for Alice.

## A solution in C++

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

void dfs(int node, int parent, int bob, int time, int& aliceIncome, int& res, std::vector<int>& amount, std::unordered_map<int, std::vector<int>>& tree) {
    if (time < bob || amount[node] >= 0) {
        aliceIncome += amount[node];
    } else {
        aliceIncome += amount[node] / 2;
    }
    amount[node] = 0;
    bool isLeaf = true;
    for (int child : tree[node]) {
        if (child != parent) {
            isLeaf = false;
            int tempIncome = aliceIncome;
            dfs(child, node, bob, time + 1, tempIncome, res, amount, tree);
        }
    }
    if (isLeaf) {
        res = std::max(res, aliceIncome);
    }
}

int maxNetIncome(std::vector<std::vector<int>>& edges, int bob, std::vector<int>& amount) {
    std::unordered_map<int, std::vector<int>> tree;
    for (const auto& edge : edges) {
        tree[edge[0]].emplace_back(edge[1]);
        tree[edge[1]].emplace_back(edge[0]);
    }
    int res = -100000;
    int aliceIncome = 0;
    dfs(0, -1, bob, 0, aliceIncome, res, amount, tree);
    return res;
}
```
We will use a depth-first search (DFS) to calculate the net income for Alice as she travels towards the optimal leaf node. We create a tree using the given edges, and then call our DFS function starting at node 0.

In the DFS function, we distinguish between whether Alice has reached the node before Bob or not. If Alice has reached the node before Bob or if the gate at node i gives a reward (amount[i] >= 0), we add the price needed / cash reward to Alice's net income. If Alice and Bob reach the node simultaneously, we add half of the price needed / cash reward to Alice's net income. We set amount[node] to be 0 after calculating Alice's net income.

We then recursively call the DFS function for all child nodes (except the parent node), with the current node acting as the parent. If we reach a leaf node, we update the maximum net income for Alice.

Finally, we return the maximum net income for Alice.

## A solution in Python

```python
from collections import defaultdict

def dfs(node, parent, bob, time, alice_income, res, amount, tree):
    if time < bob or amount[node] >= 0:
        alice_income += amount[node]
    else:
        alice_income += amount[node] // 2
    amount[node] = 0
    is_leaf = True
    for child in tree[node]:
        if child != parent:
            is_leaf = False
            dfs(child, node, bob, time + 1, alice_income, res, amount, tree)
    if is_leaf:
        res[0] = max(res[0], alice_income)

def maxNetIncome(edges, bob, amount):
    tree = defaultdict(list)
    for edge in edges:
        tree[edge[0]].append(edge[1])
        tree[edge[1]].append(edge[0])
    res = [-100000]
    dfs(0, -1, bob, 0, 0, res, amount, tree)
    return res[0]
```
We will use a depth-first search (DFS) to calculate the net income for Alice as she travels towards the optimal leaf node. We create a tree using the given edges, and then call our DFS function starting at node 0.

In the DFS function, we distinguish between whether Alice has reached the node before Bob or not. If Alice has reached the node before Bob or if the gate at node i gives a reward (amount[i] >= 0), we add the price needed / cash reward to Alice's net income. If Alice and Bob reach the node simultaneously, we add half of the price needed / cash reward to Alice's net income. We set amount[node] to be 0 after calculating Alice's net income.

We then recursively call the DFS function for all child nodes (except the parent node), with the current node acting as the parent. If we reach a leaf node, we update the maximum net income for Alice.

Finally, we return the maximum net income for Alice.

## A solution in Javascript

```javascript
function dfs(node, parent, bob, time, aliceIncome, amount, tree) {
    if (time < bob || amount[node] >= 0) {
        aliceIncome.val += amount[node];
    } else {
        aliceIncome.val += amount[node] / 2;
    }
    amount[node] = 0;
    let isLeaf = true;
    for (let child of tree[node]) {
        if (child !== parent) {
            isLeaf = false;
            const tempIncome = {val: aliceIncome.val};
            dfs(child, node, bob, time + 1, tempIncome, amount, tree);
        }
    }
    if (isLeaf) {
        aliceIncome.max = Math.max(aliceIncome.max, aliceIncome.val);
    }
}

function maxNetIncome(edges, bob, amount) {
    const tree = new Map();
    for (let edge of edges) {
        if (!tree.has(edge[0])) tree.set(edge[0], []);
        if (!tree.has(edge[1])) tree.set(edge[1], []);
        tree.get(edge[0]).push(edge[1]);
        tree.get(edge[1]).push(edge[0]);
    }
    const aliceIncome = {val: 0, max: -100000};
    dfs(0, -1, bob, 0, aliceIncome, amount, tree);
    return aliceIncome.max;
}
```
We will use a depth-first search (DFS) to calculate the net income for Alice as she travels towards the optimal leaf node. We create a tree using the given edges, and then call our DFS function starting at node 0.

In the DFS function, we distinguish between whether Alice has reached the node before Bob or not. If Alice has reached the node before Bob or if the gate at node i gives a reward (amount[i] >= 0), we add the price needed / cash reward to Alice's net income. If Alice and Bob reach the node simultaneously, we add half of the price needed / cash reward to Alice's net income. We set amount[node] to be 0 after calculating Alice's net income.

We then recursively call the DFS function for all child nodes (except the parent node), with the current node acting as the parent. If we reach a leaf node, we update the maximum net income for Alice.

Finally, we return the maximum net income for Alice.


# Split Message Based on Limit

- slug: split-message-based-on-limit
- difficulty: Hard

You are given a string, `message`, and a positive integer, `limit`.

You must **split** `message` into one or more **parts** based on `limit`. Each resulting part should have the suffix `" "`, where `"b "` is to be **replaced** with the total number of parts and `"a "` is to be **replaced** with the index of the part, starting from `1` and going up to `b`. Additionally, the length of each resulting part (including its suffix) should be **equal** to `limit`, except for the last part whose length can be **at most** `limit`.

The resulting parts should be formed such that when their suffixes are removed and they are all concatenated **in order**, they should be equal to `message`. Also, the result should contain as few parts as possible.

Return _the parts_ `message` _would be split into as an array of strings_. If it is impossible to split `message` as required, return _an empty array_.

**Example 1:**

**Input:** message =  "this is really a very awesome message ", limit = 9
**Output:** \[ "thi<1/14> ", "s i<2/14> ", "s r<3/14> ", "eal<4/14> ", "ly <5/14> ", "a v<6/14> ", "ery<7/14> ", " aw<8/14> ", "eso<9/14> ", "me<10/14> ", " m<11/14> ", "es<12/14> ", "sa<13/14> ", "ge<14/14> "\]
**Explanation:**
The first 9 parts take 3 characters each from the beginning of message.
The next 5 parts take 2 characters each to finish splitting message.
In this example, each part, including the last, has length 9.
It can be shown it is not possible to split message into less than 14 parts.

**Example 2:**

**Input:** message =  "short message ", limit = 15
**Output:** \[ "short mess<1/2> ", "age<2/2> "\]
**Explanation:**
Under the given constraints, the string can be split into two parts:
- The first part comprises of the first 10 characters, and has a length 15.
- The next part comprises of the last 3 characters, and has a length 8.

**Constraints:**

*   `1 <= message.length <= 104`
*   `message` consists only of lowercase English letters and `' '`.
*   `1 <= limit <= 104`

## A solution in Java

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

public List<String> splitMessage(String message, int limit) {
    int n = message.length();
    int a = (limit - 3) * (n / (limit - 3)) - n;
    int b = n / (limit - 3);
    if ((n + b + a) % (limit - 2) != 0)
        return new ArrayList<>();
    int num_parts = (n + b + a) / (limit - 2);
    List<String> result = new ArrayList<>();
    for (int i = 0, k = 1, cnt = 0; i < n || k <= num_parts;) {
        StringBuilder temp = new StringBuilder();
        while (cnt < limit - 3) {
            cnt++;
            temp.append(message.charAt(i++));
            if (i == n) break;
        }
        cnt = 0;
        temp.append(k).append("/").append(num_parts).append(" ");
        k++;
        result.add(temp.toString());
    }
    return result;
}
```
The algorithm first calculates the number of parts (`num_parts`) that the message would be divided into. It does so by calculating:
* `a`: The number of extra characters needed for each part to be of length `limit` (except the last one).
* `b`: The estimated number of parts calculated as the length of the message divided by `limit - 3`. The `-3` is because of the `<a/b> ` suffix.
* If `(n + a + b) % (limit - 2) != 0`, it means it is not possible to split the message according to the given condition, so it returns an empty array.
* Now, it calculates the actual `num_parts` by dividing `(n + a + b)` by `(limit - 2)`.

Then it iterates through the message while keeping track of the current index `i`, current part index `k`, and a counter `cnt`. In each iteration, it creates a temporary string `temp` and fills it with at most `limit - 3` characters from the message. Then it appends the suffix with the current part index and the total number of parts. Finally, it adds the constructed part to the result array.

This algorithm ensures the message is divided into a minimum number of parts while keeping the length of the parts equal to `limit` except for the last one, which can be at most `limit`.

## A solution in C++

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

vector<string> splitMessage(string message, int limit) {
    int n = message.size();
    int a = (limit - 3) * (n / (limit - 3)) - n;
    int b = n / (limit - 3);
    if ((n + b + a) % (limit - 2) != 0)
        return {};
    int num_parts = (n + b + a) / (limit - 2);
    vector<string> result;
    for (int i = 0, k = 1, cnt = 0; i < n || k <= num_parts;) {
        string temp;
        while (cnt < limit - 3) {
            cnt++;
            temp += message[i++];
            if (i == n) break;
        }
        cnt = 0;
        temp += to_string(k) + "/" + to_string(num_parts) + " ";
        k++;
        result.push_back(temp);
    }
    return result;
}
```
The algorithm first calculates the number of parts (`num_parts`) that the message would be divided into. It does so by calculating:
* `a`: The number of extra characters needed for each part to be of length `limit` (except the last one).
* `b`: The estimated number of parts calculated as the length of the message divided by `limit - 3`. The `-3` is because of the `<a/b> ` suffix.
* If `(n + a + b) % (limit - 2) != 0`, it means it is not possible to split the message according to the given condition, so it returns an empty array.
* Now, it calculates the actual `num_parts` by dividing `(n + a + b)` by `(limit - 2)`.

Then it iterates through the message while keeping track of the current index `i`, current part index `k`, and a counter `cnt`. In each iteration, it creates a temporary string `temp` and fills it with at most `limit - 3` characters from the message. Then it appends the suffix with the current part index and the total number of parts. Finally, it adds the constructed part to the result array.

This algorithm ensures the message is divided into a minimum number of parts while keeping the length of the parts equal to `limit` except for the last one, which can be at most `limit`.

## A solution in Python

```python
def split_message(message: str, limit: int) -> list[str]:
    n = len(message)
    a = (limit - 3) * (n // (limit - 3)) - n
    b = n // (limit - 3)
    if (n + b + a) % (limit - 2) != 0:
        return []
    num_parts = (n + b + a) // (limit - 2)
    result = []
    i = k = cnt = 0
    while i < n or k < num_parts:
        temp = []
        while cnt < limit - 3:
            cnt += 1
            temp.append(message[i])
            i += 1
            if i == n: break
        cnt = 0
        temp.append(str(k+1) + "/" + str(num_parts) + " ")
        k += 1
        result.append("".join(temp))
    return result
```
The algorithm first calculates the number of parts (`num_parts`) that the message would be divided into. It does so by calculating:
* `a`: The number of extra characters needed for each part to be of length `limit` (except the last one).
* `b`: The estimated number of parts calculated as the length of the message divided by `limit - 3`. The `-3` is because of the `<a/b> ` suffix.
* If `(n + a + b) % (limit - 2) != 0`, it means it is not possible to split the message according to the given condition, so it returns an empty array.
* Now, it calculates the actual `num_parts` by dividing `(n + a + b)` by `(limit - 2)`.

Then it iterates through the message while keeping track of the current index `i`, current part index `k`, and a counter `cnt`. In each iteration, it creates a temporary string `temp` and fills it with at most `limit - 3` characters from the message. Then it appends the suffix with the current part index and the total number of parts. Finally, it adds the constructed part to the result array.

This algorithm ensures the message is divided into a minimum number of parts while keeping the length of the parts equal to `limit` except for the last one, which can be at most `limit`.

## A solution in Javascript

```javascript
function splitMessage(message, limit) {
    let n = message.length;
    let a = (limit - 3) * (n / (limit - 3)) - n;
    let b = n / (limit - 3);
    if ((n + b + a) % (limit - 2) !== 0)
        return [];
    let num_parts = (n + b + a) / (limit - 2);
    let result = [];
    for (let i = 0, k = 1, cnt = 0; i < n || k <= num_parts;) {
        let temp = "";
        while (cnt < limit - 3) {
            cnt++;
            temp += message[i++];
            if (i === n) break;
        }
        cnt = 0;
        temp += `${k}/${num_parts} `;
        k++;
        result.push(temp);
    }
    return result;
}
```
The algorithm first calculates the number of parts (`num_parts`) that the message would be divided into. It does so by calculating:
* `a`: The number of extra characters needed for each part to be of length `limit` (except the last one).
* `b`: The estimated number of parts calculated as the length of the message divided by `limit - 3`. The `-3` is because of the `<a/b> ` suffix.
* If `(n + a + b) % (limit - 2) != 0`, it means it is not possible to split the message according to the given condition, so it returns an empty array.
* Now, it calculates the actual `num_parts` by dividing `(n + a + b)` by `(limit - 2)`.

Then it iterates through the message while keeping track of the current index `i`, current part index `k`, and a counter `cnt`. In each iteration, it creates a temporary string `temp` and fills it with at most `limit - 3` characters from the message. Then it appends the suffix with the current part index and the total number of parts. Finally, it adds the constructed part to the result array.

This algorithm ensures the message is divided into a minimum number of parts while keeping the length of the parts equal to `limit` except for the last one, which can be at most `limit`.


# Convert the Temperature

- slug: convert-the-temperature
- difficulty: Easy

You are given a non-negative floating point number rounded to two decimal places `celsius`, that denotes the **temperature in Celsius**.

You should convert Celsius into **Kelvin** and **Fahrenheit** and return it as an array `ans = [kelvin, fahrenheit]`.

Return _the array `ans`._ Answers within `10-5` of the actual answer will be accepted.

**Note that:**

*   `Kelvin = Celsius + 273.15`
*   `Fahrenheit = Celsius * 1.80 + 32.00`

**Example 1:**

**Input:** celsius = 36.50
**Output:** \[309.65000,97.70000\]
**Explanation:** Temperature at 36.50 Celsius converted in Kelvin is 309.65 and converted in Fahrenheit is 97.70.

**Example 2:**

**Input:** celsius = 122.11
**Output:** \[395.26000,251.79800\]
**Explanation:** Temperature at 122.11 Celsius converted in Kelvin is 395.26 and converted in Fahrenheit is 251.798.

**Constraints:**

*   `0 <= celsius <= 1000`

## A solution in Java

```java
public double[] convertTemperature(double celsius) {
    double kelvin = celsius + 273.15;
    double fahrenheit = celsius * 1.80 + 32.00;
    return new double[]{kelvin, fahrenheit};
}
```
The algorithm is quite simple. First, we calculate and store the temperature value in Kelvin by adding 273.15 to the given Celsius value. Next, we calculate the Fahrenheit value by multiplying the Celsius value by 1.8 and adding 32. Finally, we return an array with the calculated Kelvin and Fahrenheit values.

## A solution in C++

```cpp
#include <vector>

std::vector<double> convertTemperature(double celsius) {
    double kelvin = celsius + 273.15;
    double fahrenheit = celsius * 1.80 + 32.00;
    return {kelvin, fahrenheit};
}
```
The algorithm is quite simple. First, we calculate and store the temperature value in Kelvin by adding 273.15 to the given Celsius value. Next, we calculate the Fahrenheit value by multiplying the Celsius value by 1.8 and adding 32. Finally, we return an array with the calculated Kelvin and Fahrenheit values.

## A solution in Python

```python
def convert_temperature(celsius):
    kelvin = celsius + 273.15
    fahrenheit = celsius * 1.8 + 32
    return [kelvin, fahrenheit]
```
The algorithm is quite simple. First, we calculate and store the temperature value in Kelvin by adding 273.15 to the given Celsius value. Next, we calculate the Fahrenheit value by multiplying the Celsius value by 1.8 and adding 32. Finally, we return an array with the calculated Kelvin and Fahrenheit values.

## A solution in Javascript

```javascript
function convertTemperature(celsius) {
    const kelvin = celsius + 273.15;
    const fahrenheit = celsius * 1.80 + 32.00;
    return [kelvin, fahrenheit];
}
```
The algorithm is quite simple. First, we calculate and store the temperature value in Kelvin by adding 273.15 to the given Celsius value. Next, we calculate the Fahrenheit value by multiplying the Celsius value by 1.8 and adding 32. Finally, we return an array with the calculated Kelvin and Fahrenheit values.


# Number of Subarrays With LCM Equal to K

- slug: number-of-subarrays-with-lcm-equal-to-k
- difficulty: Medium

Given an integer array `nums` and an integer `k`, return _the number of **subarrays** of_ `nums` _where the least common multiple of the subarray's elements is_ `k`.

A **subarray** is a contiguous non-empty sequence of elements within an array.

The **least common multiple of an array** is the smallest positive integer that is divisible by all the array elements.

**Example 1:**

**Input:** nums = \[3,6,2,7,1\], k = 6
**Output:** 4
**Explanation:** The subarrays of nums where 6 is the least common multiple of all the subarray's elements are:
- \[**3**,**6**,2,7,1\]
- \[**3**,**6**,**2**,7,1\]
- \[3,**6**,2,7,1\]
- \[3,**6**,**2**,7,1\]

**Example 2:**

**Input:** nums = \[3\], k = 2
**Output:** 0
**Explanation:** There are no subarrays of nums where 2 is the least common multiple of all the subarray's elements.

**Constraints:**

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

## A solution in Java

```java
public int countLCMSubarrays(int[] nums, int k) {
    int count = 0;
    for (int i = 0; i < nums.length; i++) {
        int curr_lcm = nums[i];
        for (int j = i; j < nums.length; j++) {
            curr_lcm = lcm(curr_lcm, nums[j]);
            if (curr_lcm == k) {
                count++;
            }
        }
    }
    return count;
}

private int lcm(int a, int b) {
    int temp = a;
    while ((temp % b) != 0) {
        temp += a;
    }
    return temp;
}
```
1. Create a function `lcm` that takes two arguments, `a` and `b`, and returns the Least Common Multiple of both.
2. Initialize a counter `count` to zero.
3. Iterate through the input array `nums`. For each element, set the current element as the current Least Common Multiple `curr_lcm`.
4. Iterate from the current element to the end of the array.
   - Update the current LCM using the `lcm` function, providing the current LCM and the current element from the inner iteration as arguments.
   - If the LCM is equal to `k`, increment the counter `count`.
5. Return the counter `count`.

## A solution in C++

```cpp
#include <vector>

int lcm(int a, int b) {
    int temp = a;
    while ((temp % b) != 0) {
        temp += a;
    }
    return temp;
}

int countLCMSubarrays(std::vector<int>& nums, int k) {
    int count = 0;
    for (int i = 0; i < nums.size(); i++) {
        int curr_lcm = nums[i];
        for (int j = i; j < nums.size(); j++) {
            curr_lcm = lcm(curr_lcm, nums[j]);
            if (curr_lcm == k) {
                count++;
            }
        }
    }
    return count;
}
```
1. Create a function `lcm` that takes two arguments, `a` and `b`, and returns the Least Common Multiple of both.
2. Initialize a counter `count` to zero.
3. Iterate through the input array `nums`. For each element, set the current element as the current Least Common Multiple `curr_lcm`.
4. Iterate from the current element to the end of the array.
   - Update the current LCM using the `lcm` function, providing the current LCM and the current element from the inner iteration as arguments.
   - If the LCM is equal to `k`, increment the counter `count`.
5. Return the counter `count`.

## A solution in Python

```python
def count_lcm_subarrays(nums: List[int], k: int) -> int:
    def lcm(a, b):
        temp = a
        while temp % b != 0:
            temp += a
        return temp

    count = 0
    for i in range(len(nums)):
        curr_lcm = nums[i]
        for j in range(i, len(nums)):
            curr_lcm = lcm(curr_lcm, nums[j])
            if curr_lcm == k:
                count += 1

    return count
```
1. Create a function `lcm` that takes two arguments, `a` and `b`, and returns the Least Common Multiple of both.
2. Initialize a counter `count` to zero.
3. Iterate through the input array `nums`. For each element, set the current element as the current Least Common Multiple `curr_lcm`.
4. Iterate from the current element to the end of the array.
   - Update the current LCM using the `lcm` function, providing the current LCM and the current element from the inner iteration as arguments.
   - If the LCM is equal to `k`, increment the counter `count`.
5. Return the counter `count`.

## A solution in Javascript

```javascript
function countLCMSubarrays(nums, k) {
    function lcm(a, b) {
        let temp = a;
        while (temp % b !== 0) {
            temp += a;
        }
        return temp;
    }

    let count = 0;
    for (let i = 0; i < nums.length; i++) {
        let curr_lcm = nums[i];
        for (let j = i; j < nums.length; j++) {
            curr_lcm = lcm(curr_lcm, nums[j]);
            if (curr_lcm === k) {
                count++;
            }
        }
    }
    return count;
}
```
1. Create a function `lcm` that takes two arguments, `a` and `b`, and returns the Least Common Multiple of both.
2. Initialize a counter `count` to zero.
3. Iterate through the input array `nums`. For each element, set the current element as the current Least Common Multiple `curr_lcm`.
4. Iterate from the current element to the end of the array.
   - Update the current LCM using the `lcm` function, providing the current LCM and the current element from the inner iteration as arguments.
   - If the LCM is equal to `k`, increment the counter `count`.
5. Return the counter `count`.


# Minimum Number of Operations to Sort a Binary Tree by Level

- slug: minimum-number-of-operations-to-sort-a-binary-tree-by-level
- difficulty: Medium

You are given the `root` of a binary tree with **unique values**.

In one operation, you can choose any two nodes **at the same level** and swap their values.

Return _the minimum number of operations needed to make the values at each level sorted in a **strictly increasing order**_.

The **level** of a node is the number of edges along the path between it and the root node_._

**Example 1:**

**Input:** root = \[1,4,3,7,6,8,5,null,null,null,null,9,null,10\]
**Output:** 3
**Explanation:**
- Swap 4 and 3. The 2nd level becomes \[3,4\].
- Swap 7 and 5. The 3rd level becomes \[5,6,8,7\].
- Swap 8 and 7. The 3rd level becomes \[5,6,7,8\].
We used 3 operations so return 3.
It can be proven that 3 is the minimum number of operations needed.

**Example 2:**

**Input:** root = \[1,3,2,7,6,5,4\]
**Output:** 3
**Explanation:**
- Swap 3 and 2. The 2nd level becomes \[2,3\].
- Swap 7 and 4. The 3rd level becomes \[4,6,5,7\].
- Swap 6 and 5. The 3rd level becomes \[4,5,6,7\].
We used 3 operations so return 3.
It can be proven that 3 is the minimum number of operations needed.

**Example 3:**

**Input:** root = \[1,2,3,4,5,6\]
**Output:** 0
**Explanation:** Each level is already sorted in increasing order so return 0.

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 105]`.
*   `1 <= Node.val <= 105`
*   All the values of the tree are **unique**.

## A solution in Java

```java
import java.util.*;

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

class Solution {
    public int minSwaps(TreeNode root) {
        int count = 0;
        Queue<Pair<TreeNode, Integer>> que = new LinkedList<>();
        que.add(new Pair<>(root, 0));

        List<Integer> levelVals = new ArrayList<>();
        int prevDepth = -1;

        while (!que.isEmpty()) {
            Pair<TreeNode, Integer> curr = que.remove();
            TreeNode node = curr.getKey();
            int depth = curr.getValue();

            if (prevDepth != depth) {
                Collections.sort(levelVals);
                for (int i = 1; i < levelVals.size(); ++i) {
                    count += Math.abs(levelVals.get(i) - levelVals.get(i-1)) - 1;
                }
                prevDepth = depth;
                levelVals.clear();
            }
            levelVals.add(node.val);

            if (node.left != null) que.add(new Pair<>(node.left, depth + 1));
            if (node.right != null) que.add(new Pair<>(node.right, depth + 1));
        }

        Collections.sort(levelVals);
        for (int i = 1; i < levelVals.size(); ++i) {
            count += Math.abs(levelVals.get(i) - levelVals.get(i-1)) - 1;
        }

        return count;
    }
}
```
The algorithm uses a breadth-first search to traverse through each level of the binary tree. It keeps track of the current level of nodes by using a queue and the depth of the current node. At each level, we store the node values into a list (called `levelVals`).

Once we have reached a new level or finished traversal, we sort the list of the previous level's node values and calculate the total number of swaps needed to make the previous level sorted in increasing order. Let `a` and `b` be the sorted values of the previous and the next element in that level. The swaps at each step are calculated as `abs(a - b) - 1`, and we update the `count` variable.

After the last level, we perform the same calculation for swaps, and finally return the `count` as the result.

## A solution in C++

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

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

int minSwaps(TreeNode* root) {
    int count = 0;
    queue<pair<TreeNode*, int>> que;
    que.push({root, 0});

    vector<int> levelVals;
    int prevDepth = -1;

    while (!que.empty()) {
        auto curr = que.front();
        que.pop();
        TreeNode* node = curr.first;
        int depth = curr.second;

        if (prevDepth != depth) {
            sort(levelVals.begin(), levelVals.end());
            for (int i = 1; i < levelVals.size(); ++i) {
                count += abs(levelVals[i] - levelVals[i-1]) - 1;
            }
            prevDepth = depth;
            levelVals.clear();
        }
        levelVals.push_back(node->val);

        if (node->left) que.push({node->left, depth + 1});
        if (node->right) que.push({node->right, depth + 1});
    }

    sort(levelVals.begin(), levelVals.end());
    for (int i = 1; i < levelVals.size(); ++i) {
        count += abs(levelVals[i] - levelVals[i-1]) - 1;
    }

    return count;
}
```
The algorithm uses a breadth-first search to traverse through each level of the binary tree. It keeps track of the current level of nodes by using a queue and the depth of the current node. At each level, we store the node values into a list (called `levelVals`).

Once we have reached a new level or finished traversal, we sort the list of the previous level's node values and calculate the total number of swaps needed to make the previous level sorted in increasing order. Let `a` and `b` be the sorted values of the previous and the next element in that level. The swaps at each step are calculated as `abs(a - b) - 1`, and we update the `count` variable.

After the last level, we perform the same calculation for swaps, and finally return the `count` as the result.

## A solution in Python

```python
from collections import deque

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

def minSwaps(root: TreeNode) -> int:
    count = 0
    que = deque([(root, 0)])

    level_vals = []
    prev_depth = -1

    while que:
        node, depth = que.popleft()

        if prev_depth != depth:
            level_vals.sort()
            for i in range(1, len(level_vals)):
                count += abs(level_vals[i] - level_vals[i-1]) - 1
            prev_depth = depth
            level_vals.clear()
        level_vals.append(node.val)

        if node.left:
            que.append((node.left, depth + 1))
        if node.right:
            que.append((node.right, depth + 1))

    level_vals.sort()
    for i in range(1, len(level_vals)):
        count += abs(level_vals[i] - level_vals[i-1]) - 1

    return count
```
The algorithm uses a breadth-first search to traverse through each level of the binary tree. It keeps track of the current level of nodes by using a queue and the depth of the current node. At each level, we store the node values into a list (called `levelVals`).

Once we have reached a new level or finished traversal, we sort the list of the previous level's node values and calculate the total number of swaps needed to make the previous level sorted in increasing order. Let `a` and `b` be the sorted values of the previous and the next element in that level. The swaps at each step are calculated as `abs(a - b) - 1`, and we update the `count` variable.

After the last level, we perform the same calculation for swaps, and finally return the `count` as the result.

## A solution in Javascript

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

function minSwaps(root) {
    let count = 0;
    let que = [{ node: root, depth: 0 }];

    let levelVals = [];
    let prevDepth = -1;

    while (que.length > 0) {
        const { node, depth } = que.shift();

        if (prevDepth !== depth) {
            levelVals.sort((a, b) => a - b);
            for (let i = 1; i < levelVals.length; ++i) {
                count += Math.abs(levelVals[i] - levelVals[i-1]) - 1;
            }
            prevDepth = depth;
            levelVals = [];
        }
        levelVals.push(node.val);

        if (node.left) que.push({ node: node.left, depth: depth + 1 });
        if (node.right) que.push({ node: node.right, depth: depth + 1 });
    }

    levelVals.sort((a, b) => a - b);
    for (let i = 1; i < levelVals.length; ++i) {
        count += Math.abs(levelVals[i] - levelVals[i-1]) - 1;
    }

    return count;
}
```
The algorithm uses a breadth-first search to traverse through each level of the binary tree. It keeps track of the current level of nodes by using a queue and the depth of the current node. At each level, we store the node values into a list (called `levelVals`).

Once we have reached a new level or finished traversal, we sort the list of the previous level's node values and calculate the total number of swaps needed to make the previous level sorted in increasing order. Let `a` and `b` be the sorted values of the previous and the next element in that level. The swaps at each step are calculated as `abs(a - b) - 1`, and we update the `count` variable.

After the last level, we perform the same calculation for swaps, and finally return the `count` as the result.


# Maximum Number of Non-overlapping Palindrome Substrings

- slug: maximum-number-of-non-overlapping-palindrome-substrings
- difficulty: Hard

You are given a string `s` and a **positive** integer `k`.

Select a set of **non-overlapping** substrings from the string `s` that satisfy the following conditions:

*   The **length** of each substring is **at least** `k`.
*   Each substring is a **palindrome**.

Return _the **maximum** number of substrings in an optimal selection_.

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

**Example 1:**

**Input:** s =  "abaccdbbd ", k = 3
**Output:** 2
**Explanation:** We can select the substrings underlined in s =  "**aba**cc**dbbd** ". Both  "aba " and  "dbbd " are palindromes and have a length of at least k = 3.
It can be shown that we cannot find a selection with more than two valid substrings.

**Example 2:**

**Input:** s =  "adbcda ", k = 2
**Output:** 0
**Explanation:** There is no palindrome substring of length at least 2 in the string.

**Constraints:**

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

## A solution in Java

```java
public int maxPalindromesSubstrings(String s, int k) {
    int n = s.length();
    if (n < k) {
        return 0;
    }
    int count = 0;
    boolean[][] dp = new boolean[n][n];
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i; j < n; j++) {
            if (i == j) {
                dp[i][j] = true;
            } else if (s.charAt(i) == s.charAt(j)) {
                dp[i][j] = i + 1 > j - 1 || dp[i + 1][j - 1];
            } else {
                dp[i][j] = false;
            }
            if (j - i + 1 >= k && dp[i][j]) {
                count++;
                i = j;
                break;
            }
        }
    }
    return count;
}
```
To solve this problem, we can use dynamic programming. We use a 2D boolean array `dp`, where `dp[i][j]` will be `true` if the string from index `i` to `j` is a palindrome.

The main idea of the algorithm is to iterate through the string 's' and for each position, we find the longest palindrome substring starting at that position. If it is longer than or equal to length 'k' we count it and move to the next non-overlapping position. Otherwise, we continue to check the next position.

Here is the procedure for each programming language:

1. If `s.length < k`, there cannot be a palindrome substring of length at least k, and we return 0.
2. Initialize a 2D boolean `dp` array with dimensions `n x n`.
3. Loop through the string `s` in reverse order (from end to start) using index `i`. This allows us to find the longest palindrome substring starting at the current position.
4. For each `i`, find the longest palindrome substring starting at that position using another loop with an index `j`. Here, we continuously check if the substring from position `i` to `j` is a palindrome using our `dp` array.
5. If the current palindrome substring length (`j - i + 1`) is at least `k` and `dp[i][j]` is `true`, increment the count, and update i to j to avoid overlapping substrings.
6. Return count.

This approach has a time complexity of O(n^2) and space complexity of O(n^2), where n is the length of string s.

## A solution in C++

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

int maxPalindromesSubstrings(std::string s, int k) {
    int n = s.size();
    if (n < k) {
        return 0;
    }
    int count = 0;
    std::vector<std::vector<bool>> dp(n, std::vector<bool>(n, false));
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i; j < n; j++) {
            if (i == j) {
                dp[i][j] = true;
            } else if (s[i] == s[j]) {
                dp[i][j] = i + 1 > j - 1 || dp[i + 1][j - 1];
            } else {
                dp[i][j] = false;
            }
            if (j - i + 1 >= k && dp[i][j]) {
                count++;
                i = j;
                break;
            }
        }
    }
    return count;
}
```
To solve this problem, we can use dynamic programming. We use a 2D boolean array `dp`, where `dp[i][j]` will be `true` if the string from index `i` to `j` is a palindrome.

The main idea of the algorithm is to iterate through the string 's' and for each position, we find the longest palindrome substring starting at that position. If it is longer than or equal to length 'k' we count it and move to the next non-overlapping position. Otherwise, we continue to check the next position.

Here is the procedure for each programming language:

1. If `s.length < k`, there cannot be a palindrome substring of length at least k, and we return 0.
2. Initialize a 2D boolean `dp` array with dimensions `n x n`.
3. Loop through the string `s` in reverse order (from end to start) using index `i`. This allows us to find the longest palindrome substring starting at the current position.
4. For each `i`, find the longest palindrome substring starting at that position using another loop with an index `j`. Here, we continuously check if the substring from position `i` to `j` is a palindrome using our `dp` array.
5. If the current palindrome substring length (`j - i + 1`) is at least `k` and `dp[i][j]` is `true`, increment the count, and update i to j to avoid overlapping substrings.
6. Return count.

This approach has a time complexity of O(n^2) and space complexity of O(n^2), where n is the length of string s.

## A solution in Python

```python
def maxPalindromesSubstrings(s, k):
    n = len(s)
    if n < k:
        return 0
    count = 0
    dp = [[False] * n for _ in range(n)]
    for i in range(n - 1, -1, -1):
        for j in range(i, n):
            if i == j:
                dp[i][j] = True
            elif s[i] == s[j]:
                dp[i][j] = i + 1 > j - 1 or dp[i + 1][j - 1]
            else:
                dp[i][j] = False
            if j - i + 1 >= k and dp[i][j]:
                count += 1
                i = j
                break
    return count
```
To solve this problem, we can use dynamic programming. We use a 2D boolean array `dp`, where `dp[i][j]` will be `true` if the string from index `i` to `j` is a palindrome.

The main idea of the algorithm is to iterate through the string 's' and for each position, we find the longest palindrome substring starting at that position. If it is longer than or equal to length 'k' we count it and move to the next non-overlapping position. Otherwise, we continue to check the next position.

Here is the procedure for each programming language:

1. If `s.length < k`, there cannot be a palindrome substring of length at least k, and we return 0.
2. Initialize a 2D boolean `dp` array with dimensions `n x n`.
3. Loop through the string `s` in reverse order (from end to start) using index `i`. This allows us to find the longest palindrome substring starting at the current position.
4. For each `i`, find the longest palindrome substring starting at that position using another loop with an index `j`. Here, we continuously check if the substring from position `i` to `j` is a palindrome using our `dp` array.
5. If the current palindrome substring length (`j - i + 1`) is at least `k` and `dp[i][j]` is `true`, increment the count, and update i to j to avoid overlapping substrings.
6. Return count.

This approach has a time complexity of O(n^2) and space complexity of O(n^2), where n is the length of string s.

## A solution in Javascript

```javascript
function maxPalindromesSubstrings(s, k) {
    const n = s.length;
    if (n < k) {
        return 0;
    }
    let count = 0;
    const dp = new Array(n).fill(null).map(() => new Array(n).fill(false));
    for (let i = n - 1; i >= 0; i--) {
        for (let j = i; j < n; j++) {
            if (i === j) {
                dp[i][j] = true;
            } else if (s[i] === s[j]) {
                dp[i][j] = i + 1 > j - 1 || dp[i + 1][j - 1];
            } else {
                dp[i][j] = false;
            }
            if (j - i + 1 >= k && dp[i][j]) {
                count++;
                i = j;
                break;
            }
        }
    }
    return count;
}
```
To solve this problem, we can use dynamic programming. We use a 2D boolean array `dp`, where `dp[i][j]` will be `true` if the string from index `i` to `j` is a palindrome.

The main idea of the algorithm is to iterate through the string 's' and for each position, we find the longest palindrome substring starting at that position. If it is longer than or equal to length 'k' we count it and move to the next non-overlapping position. Otherwise, we continue to check the next position.

Here is the procedure for each programming language:

1. If `s.length < k`, there cannot be a palindrome substring of length at least k, and we return 0.
2. Initialize a 2D boolean `dp` array with dimensions `n x n`.
3. Loop through the string `s` in reverse order (from end to start) using index `i`. This allows us to find the longest palindrome substring starting at the current position.
4. For each `i`, find the longest palindrome substring starting at that position using another loop with an index `j`. Here, we continuously check if the substring from position `i` to `j` is a palindrome using our `dp` array.
5. If the current palindrome substring length (`j - i + 1`) is at least `k` and `dp[i][j]` is `true`, increment the count, and update i to j to avoid overlapping substrings.
6. Return count.

This approach has a time complexity of O(n^2) and space complexity of O(n^2), where n is the length of string s.


# Minimum Cost to Buy Apples

- slug: minimum-cost-to-buy-apples
- difficulty: Medium

You are given a positive integer `n` representing `n` cities numbered from `1` to `n`. You are also given a **2D** array `roads`, where `roads[i] = [ai, bi, costi]` indicates that there is a **bidirectional** road between cities `ai` and `bi` with a cost of traveling equal to `costi`.

You can buy apples in **any** city you want, but some cities have different costs to buy apples. You are given the array `appleCost` where `appleCost[i]` is the cost of buying one apple from city `i`.

You start at some city, traverse through various roads, and eventually buy **exactly** one apple from **any** city. After you buy that apple, you have to return back to the city you **started** at, but now the cost of all the roads will be **multiplied** by a given factor `k`.

Given the integer `k`, return _an array_ `answer` _of size_ `n` _where_ `answer[i]` _is the **minimum** total cost to buy an apple if you start at city_ `i`.

**Example 1:**

**Input:** n = 4, roads = \[\[1,2,4\],\[2,3,2\],\[2,4,5\],\[3,4,1\],\[1,3,4\]\], appleCost = \[56,42,102,301\], k = 2
**Output:** \[54,42,48,51\]
**Explanation:** The minimum cost for each starting city is the following:
- Starting at city 1: You take the path 1 -> 2, buy an apple at city 2, and finally take the path 2 -> 1. The total cost is 4 + 42 + 4 \* 2 = 54.
- Starting at city 2: You directly buy an apple at city 2. The total cost is 42.
- Starting at city 3: You take the path 3 -> 2, buy an apple at city 2, and finally take the path 2 -> 3. The total cost is 2 + 42 + 2 \* 2 = 48.
- Starting at city 4: You take the path 4 -> 3 -> 2 then you buy at city 2, and finally take the path 2 -> 3 -> 4. The total cost is 1 + 2 + 42 + 1 \* 2 + 2 \* 2 = 51.

**Example 2:**

**Input:** n = 3, roads = \[\[1,2,5\],\[2,3,1\],\[3,1,2\]\], appleCost = \[2,3,1\], k = 3
**Output:** \[2,3,1\]
**Explanation:** It is always optimal to buy the apple in the starting city.

**Constraints:**

*   `2 <= n <= 1000`
*   `1 <= roads.length <= 1000`
*   `1 <= ai, bi <= n`
*   `ai != bi`
*   `1 <= costi <= 105`
*   `appleCost.length == n`
*   `1 <= appleCost[i] <= 105`
*   `1 <= k <= 100`
*   There are no repeated edges.

## A solution in Java

```java
import java.util.*;

class Solution {
    public static int[] minTotalCost(int n, int[][] roads, int[] appleCost, int k) {
        List<List<int[]>> graph = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] road : roads) {
            graph.get(road[0]).add(new int[]{road[1], road[2]});
            graph.get(road[1]).add(new int[]{road[0], road[2]});
        }

        int[] answer = new int[n];
        for (int start = 1; start <= n; start++) {
            PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
            int[] dist = new int[n + 1];
            Arrays.fill(dist, 1_000_000_007);
            dist[start] = 0;
            pq.add(new int[]{0, start});
            while (!pq.isEmpty()) {
                int u = pq.peek()[1];
                int d = pq.peek()[0];
                pq.poll();

                if (d > dist[u]) continue;

                for (int[] edge : graph.get(u)) {
                    int v = edge[0];
                    int c = d + edge[1] + (u != start ? edge[1] * k : 0) + appleCost[v - 1];
                    if (c < dist[v]) {
                        dist[v] = c;
                        pq.add(new int[]{c, v});
                    }
                }
            }

            answer[start - 1] = dist[start];
        }
        return answer;
    }
}
```
The problem can be solved using Dijkstra's algorithm. It is important to always choose the road with the lowest cost possible to buy apples or back to the original city. The approach is to create a graph and use a priority queue that is sorted from the lowest to the highest cost in each step.

1. Create the graph from the input roads.
2. Loop through each city as a starting point.
3. For each start city, initialize a priority queue and the distance array.
4. Using Dijkstra's algorithm, calculate the costs for buying apples in each city from the current start city and the costs back to the start city after buying apples. Note that the cost of the roads back to the start city will be the road cost multiplied by k.
5. Store the calculated cost in the answer array for each start city.
6. Return the answer array.

## A solution in C++

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

vector<int> minTotalCost(int n, vector<vector<int>>& roads, vector<int>& appleCost, int k) {
    vector<vector<pair<int, int>>> graph(n+1);
    for (auto& road : roads) {
        graph[road[0]].push_back({road[1], road[2]});
        graph[road[1]].push_back({road[0], road[2]});
    }

    vector<int> answer(n);
    for (int start = 1; start <= n; ++start) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        vector<int> dist(n + 1, 1e9);
        dist[start] = 0;
        pq.push({0, start});
        while (!pq.empty()) {
            int u = pq.top().second;
            int d = pq.top().first;
            pq.pop();

            if (d > dist[u]) continue;

            for (auto& edge : graph[u]) {
                int v = edge.first;
                int c = d + edge.second + (u != start ? edge.second * k : 0) + appleCost[v - 1];

                if (c < dist[v]) {
                    dist[v] = c;
                    pq.push({c, v});
                }
            }
        }

        answer[start-1] = dist[start];
    }
    return answer;
}
```
The problem can be solved using Dijkstra's algorithm. It is important to always choose the road with the lowest cost possible to buy apples or back to the original city. The approach is to create a graph and use a priority queue that is sorted from the lowest to the highest cost in each step.

1. Create the graph from the input roads.
2. Loop through each city as a starting point.
3. For each start city, initialize a priority queue and the distance array.
4. Using Dijkstra's algorithm, calculate the costs for buying apples in each city from the current start city and the costs back to the start city after buying apples. Note that the cost of the roads back to the start city will be the road cost multiplied by k.
5. Store the calculated cost in the answer array for each start city.
6. Return the answer array.

## A solution in Python

```python
from heapq import heappush, heappop

def minTotalCost(n, roads, appleCost, k):
    graph = [[] for _ in range(n+1)]
    for u, v, cost in roads:
        graph[u].append((v, cost))
        graph[v].append((u, cost))

    answer = [0] * n
    for start in range(1, n+1):
        pq = [(0, start)]
        dist = [float('inf')] * (n + 1)
        dist[start] = 0

        while pq:
            d, u = heappop(pq)

            if d > dist[u]:
                continue

            for v, cost in graph[u]:
                c = d + cost + (0 if u == start else cost * k) + appleCost[v - 1]
                if c < dist[v]:
                    dist[v] = c
                    heappush(pq, (c, v))

        answer[start-1] = dist[start]
    return answer
```
The problem can be solved using Dijkstra's algorithm. It is important to always choose the road with the lowest cost possible to buy apples or back to the original city. The approach is to create a graph and use a priority queue that is sorted from the lowest to the highest cost in each step.

1. Create the graph from the input roads.
2. Loop through each city as a starting point.
3. For each start city, initialize a priority queue and the distance array.
4. Using Dijkstra's algorithm, calculate the costs for buying apples in each city from the current start city and the costs back to the start city after buying apples. Note that the cost of the roads back to the start city will be the road cost multiplied by k.
5. Store the calculated cost in the answer array for each start city.
6. Return the answer array.

## A solution in Javascript

```javascript
function minTotalCost(n, roads, appleCost, k) {
    const graph = Array.from({ length: n + 1 }, () => []);
    for (const [u, v, cost] of roads) {
        graph[u].push([v, cost]);
        graph[v].push([u, cost]);
    }

    const answer = Array(n).fill(0);
    for (let start = 1; start <= n; start++) {
        const pq = [[0, start]];
        const dist = Array(n + 1).fill(Infinity);
        dist[start] = 0;

        while (pq.length) {
            const [d, u] = pq.shift();
            if (d > dist[u]) continue;

            for (const [v, cost] of graph[u]) {
                const c = d + cost + (u !== start ? cost * k : 0) + appleCost[v - 1];
                if (c < dist[v]) {
                    dist[v] = c;
                    pq.push([c, v]);
                    pq.sort((a, b) => a[0] - b[0]);
                }
            }
        }

        answer[start - 1] = dist[start];
    }
    return answer;
}
```
The problem can be solved using Dijkstra's algorithm. It is important to always choose the road with the lowest cost possible to buy apples or back to the original city. The approach is to create a graph and use a priority queue that is sorted from the lowest to the highest cost in each step.

1. Create the graph from the input roads.
2. Loop through each city as a starting point.
3. For each start city, initialize a priority queue and the distance array.
4. Using Dijkstra's algorithm, calculate the costs for buying apples in each city from the current start city and the costs back to the start city after buying apples. Note that the cost of the roads back to the start city will be the road cost multiplied by k.
5. Store the calculated cost in the answer array for each start city.
6. Return the answer array.


# Number of Unequal Triplets in Array

- slug: number-of-unequal-triplets-in-array
- difficulty: Easy

You are given a **0-indexed** array of positive integers `nums`. Find the number of triplets `(i, j, k)` that meet the following conditions:

*   `0 <= i < j < k < nums.length`
*   `nums[i]`, `nums[j]`, and `nums[k]` are **pairwise distinct**.
    *   In other words, `nums[i] != nums[j]`, `nums[i] != nums[k]`, and `nums[j] != nums[k]`.

Return _the number of triplets that meet the conditions._

**Example 1:**

**Input:** nums = \[4,4,2,4,3\]
**Output:** 3
**Explanation:** The following triplets meet the conditions:
- (0, 2, 4) because 4 != 2 != 3
- (1, 2, 4) because 4 != 2 != 3
- (2, 3, 4) because 2 != 4 != 3
Since there are 3 triplets, we return 3.
Note that (2, 0, 4) is not a valid triplet because 2 > 0.

**Example 2:**

**Input:** nums = \[1,1,1,1,1\]
**Output:** 0
**Explanation:** No triplets meet the conditions so we return 0.

**Constraints:**

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

## A solution in Java

```java
public int countTriplets(int[] nums) {
    int count = 0;
    int n = nums.length;

    for(int i = 0; i < n; i++) {
        for(int j = i + 1; j < n; j++) {
            for(int k = j + 1; k < n; k++) {
                if(nums[i] != nums[j] && nums[i] != nums[k] && nums[j] != nums[k]) {
                    count++;
                }
            }
        }
    }

    return count;
}
```
The given problem can be solved by iterating over each possible triplet (i, j, k), with the range 0 <= i < j < k < nums.length, and checking if the elements at indices i, j, and k are distinct. The algorithm runs in O(n^3) time due to the nested loops, where n is the size of the input array. If the elements at i, j, and k are distinct, we increment the count by 1. Finally, we return the total count of the triplets after iterating through all possible combinations.

The algorithm remains the same across all languages; the only difference is the syntax in each language.

## A solution in C++

```cpp
int countTriplets(vector<int>& nums) {
    int count = 0;
    int n = nums.size();

    for(int i = 0; i < n; i++) {
        for(int j = i + 1; j < n; j++) {
            for(int k = j + 1; k < n; k++) {
                if(nums[i] != nums[j] && nums[i] != nums[k] && nums[j] != nums[k]) {
                    count++;
                }
            }
        }
    }

    return count;
}
```
The given problem can be solved by iterating over each possible triplet (i, j, k), with the range 0 <= i < j < k < nums.length, and checking if the elements at indices i, j, and k are distinct. The algorithm runs in O(n^3) time due to the nested loops, where n is the size of the input array. If the elements at i, j, and k are distinct, we increment the count by 1. Finally, we return the total count of the triplets after iterating through all possible combinations.

The algorithm remains the same across all languages; the only difference is the syntax in each language.

## A solution in Python

```python
def countTriplets(nums):
    count = 0
    n = len(nums)

    for i in range(n):
        for j in range(i + 1, n):
            for k in range(j + 1, n):
                if nums[i] != nums[j] and nums[i] != nums[k] and nums[j] != nums[k]:
                    count += 1

    return count
```
The given problem can be solved by iterating over each possible triplet (i, j, k), with the range 0 <= i < j < k < nums.length, and checking if the elements at indices i, j, and k are distinct. The algorithm runs in O(n^3) time due to the nested loops, where n is the size of the input array. If the elements at i, j, and k are distinct, we increment the count by 1. Finally, we return the total count of the triplets after iterating through all possible combinations.

The algorithm remains the same across all languages; the only difference is the syntax in each language.

## A solution in Javascript

```javascript
function countTriplets(nums) {
    let count = 0;
    let n = nums.length;

    for(let i = 0; i < n; i++) {
        for(let j = i + 1; j < n; j++) {
            for(let k = j + 1; k < n; k++) {
                if(nums[i] !== nums[j] && nums[i] !== nums[k] && nums[j] !== nums[k]) {
                    count++;
                }
            }
        }
    }

    return count;
}
```
The given problem can be solved by iterating over each possible triplet (i, j, k), with the range 0 <= i < j < k < nums.length, and checking if the elements at indices i, j, and k are distinct. The algorithm runs in O(n^3) time due to the nested loops, where n is the size of the input array. If the elements at i, j, and k are distinct, we increment the count by 1. Finally, we return the total count of the triplets after iterating through all possible combinations.

The algorithm remains the same across all languages; the only difference is the syntax in each language.


# Closest Nodes Queries in a Binary Search Tree

- slug: closest-nodes-queries-in-a-binary-search-tree
- difficulty: Medium

You are given the `root` of a **binary search tree** and an array `queries` of size `n` consisting of positive integers.

Find a **2D** array `answer` of size `n` where `answer[i] = [mini, maxi]`:

*   `mini` is the **largest** value in the tree that is smaller than or equal to `queries[i]`. If a such value does not exist, add `-1` instead.
*   `maxi` is the **smallest** value in the tree that is greater than or equal to `queries[i]`. If a such value does not exist, add `-1` instead.

Return _the array_ `answer`.

**Example 1:**

**Input:** root = \[6,2,13,1,4,9,15,null,null,null,null,null,null,14\], queries = \[2,5,16\]
**Output:** \[\[2,2\],\[4,6\],\[15,-1\]\]
**Explanation:** We answer the queries in the following way:
- The largest number that is smaller or equal than 2 in the tree is 2, and the smallest number that is greater or equal than 2 is still 2. So the answer for the first query is \[2,2\].
- The largest number that is smaller or equal than 5 in the tree is 4, and the smallest number that is greater or equal than 5 is 6. So the answer for the second query is \[4,6\].
- The largest number that is smaller or equal than 16 in the tree is 15, and the smallest number that is greater or equal than 16 does not exist. So the answer for the third query is \[15,-1\].

**Example 2:**

**Input:** root = \[4,null,9\], queries = \[3\]
**Output:** \[\[-1,4\]\]
**Explanation:** The largest number that is smaller or equal to 3 in the tree does not exist, and the smallest number that is greater or equal to 3 is 4. So the answer for the query is \[-1,4\].

**Constraints:**

*   The number of nodes in the tree is in the range `[2, 105]`.
*   `1 <= Node.val <= 106`
*   `n == queries.length`
*   `1 <= n <= 105`
*   `1 <= queries[i] <= 106`

## A solution in Java

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

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

public List<List<Integer>> findMinMax(TreeNode root, int[] queries) {
    if (root == null) {
        return new ArrayList<>();
    }

    List<List<Integer>> ans = new ArrayList<>();
    for (int query : queries) {
        TreeNode node = root;
        List<Integer> currentList = Arrays.asList(-1, -1);
        while (node != null) {
            if (node.val < query) {
                currentList.set(0, node.val);
                node = node.right;
            } else {
                currentList.set(1, node.val);
                if (node.val == query) {
                    currentList.set(0, query);
                    break;
                }
                node = node.left;
            }
        }
        ans.add(currentList);
    }
    return ans;
}
```
For every query, start from the root of the binary search tree. If the node's value is less than the query, update the minValue in answer for that query and move to the right child. If the node's value is equal or greater than the query, update the maxValue and, if it is equal, update the minValue as well; then move to the left child. Keep doing this until the node becomes null.

## A solution in C++

```cpp
#include<vector>

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

std::vector<std::vector<int>> findMinMax(TreeNode* root, std::vector<int>& queries) {
    if (!root) {
        return {};
    }

    std::vector<std::vector<int>> ans(queries.size(), std::vector<int>{-1, -1});
    for (size_t i = 0; i < queries.size(); i++) {
        TreeNode* node = root;
        int query = queries[i];
        while (node) {
            if (node->val < query) {
                ans[i][0] = node->val;
                node = node->right;
            } else {
                ans[i][1] = node->val;
                if (node->val == query) {
                    ans[i][0] = query;
                    break;
                }
                node = node->left;
            }
        }
    }
    return ans;
}
```
For every query, start from the root of the binary search tree. If the node's value is less than the query, update the minValue in answer for that query and move to the right child. If the node's value is equal or greater than the query, update the maxValue and, if it is equal, update the minValue as well; then move to the left child. Keep doing this until the node becomes null.

## 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 findMinMax(root, queries):
    if not root:
        return []

    ans = [[-1, -1] for _ in range(len(queries))]
    for i in range(len(queries)):
        node = root
        query = queries[i]
        while node:
            if node.val < query:
                ans[i][0] = node.val
                node = node.right
            else:
                ans[i][1] = node.val
                if node.val == query:
                    ans[i][0] = query
                    break
                node = node.left
    return ans
```
For every query, start from the root of the binary search tree. If the node's value is less than the query, update the minValue in answer for that query and move to the right child. If the node's value is equal or greater than the query, update the maxValue and, if it is equal, update the minValue as well; then move to the left child. Keep doing this until the node becomes null.

## A solution in Javascript

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

function findMinMax(root, queries) {
    if (!root) {
        return [];
    }

    const ans = new Array(queries.length).fill().map(() => [-1, -1]);
    for (let i = 0; i < queries.length; i++) {
        let node = root;
        const query = queries[i];
        while (node) {
            if (node.val < query) {
                ans[i][0] = node.val;
                node = node.right;
            } else {
                ans[i][1] = node.val;
                if (node.val === query) {
                    ans[i][0] = query;
                    break;
                }
                node = node.left;
            }
        }
    }
    return ans;
}
```
For every query, start from the root of the binary search tree. If the node's value is less than the query, update the minValue in answer for that query and move to the right child. If the node's value is equal or greater than the query, update the maxValue and, if it is equal, update the minValue as well; then move to the left child. Keep doing this until the node becomes null.


# Minimum Fuel Cost to Report to the Capital

- slug: minimum-fuel-cost-to-report-to-the-capital
- difficulty: Medium

There is a tree (i.e., a connected, undirected graph with no cycles) structure country network consisting of `n` cities numbered from `0` to `n - 1` and exactly `n - 1` roads. The capital city is city `0`. You are given a 2D integer array `roads` where `roads[i] = [ai, bi]` denotes that there exists a **bidirectional road** connecting cities `ai` and `bi`.

There is a meeting for the representatives of each city. The meeting is in the capital city.

There is a car in each city. You are given an integer `seats` that indicates the number of seats in each car.

A representative can use the car in their city to travel or change the car and ride with another representative. The cost of traveling between two cities is one liter of fuel.

Return _the minimum number of liters of fuel to reach the capital city_.

**Example 1:**

**Input:** roads = \[\[0,1\],\[0,2\],\[0,3\]\], seats = 5
**Output:** 3
**Explanation:**
- Representative1 goes directly to the capital with 1 liter of fuel.
- Representative2 goes directly to the capital with 1 liter of fuel.
- Representative3 goes directly to the capital with 1 liter of fuel.
It costs 3 liters of fuel at minimum.
It can be proven that 3 is the minimum number of liters of fuel needed.

**Example 2:**

**Input:** roads = \[\[3,1\],\[3,2\],\[1,0\],\[0,4\],\[0,5\],\[4,6\]\], seats = 2
**Output:** 7
**Explanation:**
- Representative2 goes directly to city 3 with 1 liter of fuel.
- Representative2 and representative3 go together to city 1 with 1 liter of fuel.
- Representative2 and representative3 go together to the capital with 1 liter of fuel.
- Representative1 goes directly to the capital with 1 liter of fuel.
- Representative5 goes directly to the capital with 1 liter of fuel.
- Representative6 goes directly to city 4 with 1 liter of fuel.
- Representative4 and representative6 go together to the capital with 1 liter of fuel.
It costs 7 liters of fuel at minimum.
It can be proven that 7 is the minimum number of liters of fuel needed.

**Example 3:**

**Input:** roads = \[\], seats = 1
**Output:** 0
**Explanation:** No representatives need to travel to the capital city.

**Constraints:**

*   `1 <= n <= 105`
*   `roads.length == n - 1`
*   `roads[i].length == 2`
*   `0 <= ai, bi < n`
*   `ai != bi`
*   `roads` represents a valid tree.
*   `1 <= seats <= 105`

## A solution in Java

```java
import java.util.*;

class Solution {
    public int minFuel(int[][] roads, int seats) {
        int n = roads.length + 1;
        List<List<Integer>> graph = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] road : roads) {
            graph.get(road[0]).add(road[1]);
            graph.get(road[1]).add(road[0]);
        }

        int[] distance = new int[n];
        Arrays.fill(distance, -1);
        Queue<Integer> queue = new LinkedList<>();
        queue.add(0);
        distance[0] = 0;

        while (!queue.isEmpty()) {
            int city = queue.poll();
            for (int neighbor : graph.get(city)) {
                if (distance[neighbor] == -1) {
                    distance[neighbor] = distance[city] + 1;
                    queue.add(neighbor);
                }
            }
        }

        int totalFuel = 0;
        for (int city = 1; city < n; city++) {
            totalFuel += (distance[city] - 1) / (seats - 1) + 1;
        }
        return totalFuel;
    }
}
```
The algorithm starts by building the graph representation of the roads from the given input. This is done by creating an adjacency list for each city in the graph.

After the graph is constructed, a breadth-first search (BFS) is performed to find the distances from the capital city (city 0) to each of the other cities. This is done by maintaining a queue of cities to visit and initializing the distances with -1 (not visited). The source city distance is set to 0 as that is the capital city. The BFS traversal continues until the queue becomes empty.

Once the BFS traversal is completed, the minimum number of liters of fuel needed for each city is calculated by dividing the distance from the city to the capital city by the maximum number of cities a representative can travel in a single car (seats - 1), and then summing up the results.

The algorithm returns the total number of liters of fuel needed to reach the capital city from all the other cities.

## A solution in C++

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

int minFuel(std::vector<std::vector<int>>& roads, int seats) {
    int n = roads.size() + 1;
    std::vector<std::vector<int>> graph(n);
    for (auto& road : roads) {
        graph[road[0]].push_back(road[1]);
        graph[road[1]].push_back(road[0]);
    }

    std::vector<int> distance(n, -1);
    std::queue<int> q;
    q.push(0);
    distance[0] = 0;

    while (!q.empty()) {
        int city = q.front();
        q.pop();
        for (int neighbor : graph[city]) {
            if (distance[neighbor] == -1) {
                distance[neighbor] = distance[city] + 1;
                q.push(neighbor);
            }
        }
    }

    int totalFuel = 0;
    for (int city = 1; city < n; city++) {
        totalFuel += (distance[city] - 1) / (seats - 1) + 1;
    }
    return totalFuel;
}
```
The algorithm starts by building the graph representation of the roads from the given input. This is done by creating an adjacency list for each city in the graph.

After the graph is constructed, a breadth-first search (BFS) is performed to find the distances from the capital city (city 0) to each of the other cities. This is done by maintaining a queue of cities to visit and initializing the distances with -1 (not visited). The source city distance is set to 0 as that is the capital city. The BFS traversal continues until the queue becomes empty.

Once the BFS traversal is completed, the minimum number of liters of fuel needed for each city is calculated by dividing the distance from the city to the capital city by the maximum number of cities a representative can travel in a single car (seats - 1), and then summing up the results.

The algorithm returns the total number of liters of fuel needed to reach the capital city from all the other cities.

## A solution in Python

```python
from collections import defaultdict, deque

def min_fuel(roads, seats):
    n = len(roads) + 1
    graph = defaultdict(list)
    for road in roads:
        graph[road[0]].append(road[1])
        graph[road[1]].append(road[0])

    distance = [-1] * n
    q = deque([0])
    distance[0] = 0

    while q:
        city = q.popleft()
        for neighbor in graph[city]:
            if distance[neighbor] == -1:
                distance[neighbor] = distance[city] + 1
                q.append(neighbor)

    total_fuel = 0
    for city in range(1, n):
        total_fuel += (distance[city] - 1) // (seats - 1) + 1
    return total_fuel
```
The algorithm starts by building the graph representation of the roads from the given input. This is done by creating an adjacency list for each city in the graph.

After the graph is constructed, a breadth-first search (BFS) is performed to find the distances from the capital city (city 0) to each of the other cities. This is done by maintaining a queue of cities to visit and initializing the distances with -1 (not visited). The source city distance is set to 0 as that is the capital city. The BFS traversal continues until the queue becomes empty.

Once the BFS traversal is completed, the minimum number of liters of fuel needed for each city is calculated by dividing the distance from the city to the capital city by the maximum number of cities a representative can travel in a single car (seats - 1), and then summing up the results.

The algorithm returns the total number of liters of fuel needed to reach the capital city from all the other cities.

## A solution in Javascript

```javascript
function minFuel(roads, seats) {
    const n = roads.length + 1;
    const graph = new Array(n).fill(null).map(() => []);
    roads.forEach((road) => {
        graph[road[0]].push(road[1]);
        graph[road[1]].push(road[0]);
    });

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

    while (queue.length > 0) {
        const city = queue.shift();
        graph[city].forEach((neighbor) => {
            if (distance[neighbor] === -1) {
                distance[neighbor] = distance[city] + 1;
                queue.push(neighbor);
            }
        });
    }

    let totalFuel = 0;
    for (let city = 1; city < n; city++) {
        totalFuel += Math.floor((distance[city] - 1) / (seats - 1)) + 1;
    }
    return totalFuel;
}
```
The algorithm starts by building the graph representation of the roads from the given input. This is done by creating an adjacency list for each city in the graph.

After the graph is constructed, a breadth-first search (BFS) is performed to find the distances from the capital city (city 0) to each of the other cities. This is done by maintaining a queue of cities to visit and initializing the distances with -1 (not visited). The source city distance is set to 0 as that is the capital city. The BFS traversal continues until the queue becomes empty.

Once the BFS traversal is completed, the minimum number of liters of fuel needed for each city is calculated by dividing the distance from the city to the capital city by the maximum number of cities a representative can travel in a single car (seats - 1), and then summing up the results.

The algorithm returns the total number of liters of fuel needed to reach the capital city from all the other cities.


# Number of Beautiful Partitions

- slug: number-of-beautiful-partitions
- difficulty: Hard

You are given a string `s` that consists of the digits `'1'` to `'9'` and two integers `k` and `minLength`.

A partition of `s` is called **beautiful** if:

*   `s` is partitioned into `k` non-intersecting substrings.
*   Each substring has a length of **at least** `minLength`.
*   Each substring starts with a **prime** digit and ends with a **non-prime** digit. Prime digits are `'2'`, `'3'`, `'5'`, and `'7'`, and the rest of the digits are non-prime.

Return _the number of **beautiful** partitions of_ `s`. Since the answer may be very large, return it **modulo** `109 + 7`.

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

**Example 1:**

**Input:** s =  "23542185131 ", k = 3, minLength = 2
**Output:** 3
**Explanation:** There exists three ways to create a beautiful partition:
 "2354 | 218 | 5131 "
 "2354 | 21851 | 31 "
 "2354218 | 51 | 31 "

**Example 2:**

**Input:** s =  "23542185131 ", k = 3, minLength = 3
**Output:** 1
**Explanation:** There exists one way to create a beautiful partition:  "2354 | 218 | 5131 ".

**Example 3:**

**Input:** s =  "3312958 ", k = 3, minLength = 1
**Output:** 1
**Explanation:** There exists one way to create a beautiful partition:  "331 | 29 | 58 ".

**Constraints:**

*   `1 <= k, minLength <= s.length <= 1000`
*   `s` consists of the digits `'1'` to `'9'`.

## A solution in Java

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

public class Solution {
    public int numBeautifulPartitions(String s, int k, int minLength) {
        final int MOD = 1000000007;
        Set<Character> primes = new HashSet<>();
        primes.add('2');
        primes.add('3');
        primes.add('5');
        primes.add('7');

        int n = s.length();
        int[][] dp = new int[n + 1][k + 1];
        dp[0][0] = 1;

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= k; ++j) {
                for (int l = minLength; l <= i && i - l >= j - 1; ++l) {
                    if (primes.contains(s.charAt(i - l)) && !primes.contains(s.charAt(i - 1))) {
                        dp[i][j] += dp[i - l][j - 1];
                        if (dp[i][j] >= MOD) dp[i][j] -= MOD;
                    }
                }
            }
        }

        return dp[n][k];
    }
}
```
We use a dynamic programming approach to solve this problem. We have `dp[i][j]` representing the number of beautiful partitions for the first `i` characters of the string `s` into `j` substrings. From there, we iterate through the string and its possible partitions. For each partition, we check if the current and the previous characters meet the prime and non-prime requirements.

If the current partition is valid, we add the number of ways to create a beautiful partition using the previous partition (dp[i - l][j - 1]) to the current partition count (dp[i][j]). We also apply the modulo operation to keep the result within the range.

At the end, `dp[n][k]` will store the number of beautiful partitions for the entire string with `k` substrings.

## A solution in C++

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

using namespace std;

int numBeautifulPartitions(const string& s, int k, int minLength) {
    const int MOD = 1e9 + 7;
    unordered_set<char> primes = {'2', '3', '5', '7'};
    int n = s.length();
    vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
    dp[0][0] = 1;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= k; ++j) {
            for (int l = minLength; l <= i && i - l >= j - 1; ++l) {
                if (primes.count(s[i - l]) && !primes.count(s[i - 1])) {
                    dp[i][j] += dp[i - l][j - 1];
                    if (dp[i][j] >= MOD) dp[i][j] -= MOD;
                }
            }
        }
    }

    return dp[n][k];
}
```
We use a dynamic programming approach to solve this problem. We have `dp[i][j]` representing the number of beautiful partitions for the first `i` characters of the string `s` into `j` substrings. From there, we iterate through the string and its possible partitions. For each partition, we check if the current and the previous characters meet the prime and non-prime requirements.

If the current partition is valid, we add the number of ways to create a beautiful partition using the previous partition (dp[i - l][j - 1]) to the current partition count (dp[i][j]). We also apply the modulo operation to keep the result within the range.

At the end, `dp[n][k]` will store the number of beautiful partitions for the entire string with `k` substrings.

## A solution in Python

```python
def numBeautifulPartitions(s: str, k: int, minLength: int) -> int:
    MOD = 10**9 + 7
    primes = {'2', '3', '5', '7'}
    n = len(s)
    dp = [[0] * (k + 1) for _ in range(n + 1)]
    dp[0][0] = 1

    for i in range(1, n + 1):
        for j in range(1, k + 1):
            for l in range(minLength, i + 1):
                if i - l >= j - 1 and s[i - l] in primes and s[i - 1] not in primes:
                    dp[i][j] += dp[i - l][j - 1]
                    if dp[i][j] >= MOD:
                        dp[i][j] -= MOD

    return dp[n][k]
```
We use a dynamic programming approach to solve this problem. We have `dp[i][j]` representing the number of beautiful partitions for the first `i` characters of the string `s` into `j` substrings. From there, we iterate through the string and its possible partitions. For each partition, we check if the current and the previous characters meet the prime and non-prime requirements.

If the current partition is valid, we add the number of ways to create a beautiful partition using the previous partition (dp[i - l][j - 1]) to the current partition count (dp[i][j]). We also apply the modulo operation to keep the result within the range.

At the end, `dp[n][k]` will store the number of beautiful partitions for the entire string with `k` substrings.

## A solution in Javascript

```javascript
function numBeautifulPartitions(s, k, minLength) {
    const MOD = 1e9 + 7;
    const primes = new Set(['2', '3', '5', '7']);
    const n = s.length;
    const dp = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0));
    dp[0][0] = 1;

    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= k; j++) {
            for (let l = minLength; l <= i && i - l >= j - 1; l++) {
                if (primes.has(s[i - l]) && !primes.has(s[i - 1])) {
                    dp[i][j] += dp[i - l][j - 1];
                    if (dp[i][j] >= MOD) dp[i][j] -= MOD;
                }
            }
        }
    }

    return dp[n][k];
}
```
We use a dynamic programming approach to solve this problem. We have `dp[i][j]` representing the number of beautiful partitions for the first `i` characters of the string `s` into `j` substrings. From there, we iterate through the string and its possible partitions. For each partition, we check if the current and the previous characters meet the prime and non-prime requirements.

If the current partition is valid, we add the number of ways to create a beautiful partition using the previous partition (dp[i - l][j - 1]) to the current partition count (dp[i][j]). We also apply the modulo operation to keep the result within the range.

At the end, `dp[n][k]` will store the number of beautiful partitions for the entire string with `k` substrings.