# Maximum Profit in Job Scheduling

- slug: maximum-profit-in-job-scheduling
- difficulty: Hard

We have `n` jobs, where every job is scheduled to be done from `startTime[i]` to `endTime[i]`, obtaining a profit of `profit[i]`.

You're given the `startTime`, `endTime` and `profit` arrays, return the maximum profit you can take such that there are no two jobs in the subset with overlapping time range.

If you choose a job that ends at time `X` you will be able to start another job that starts at time `X`.

**Example 1:**

**Input:** startTime = \[1,2,3,3\], endTime = \[3,4,5,6\], profit = \[50,10,40,70\]
**Output:** 120
**Explanation:** The subset chosen is the first and fourth job.
Time range \[1-3\]+\[3-6\] , we get profit of 120 = 50 + 70.

**Example 2:**

**Input:** startTime = \[1,2,3,4,6\], endTime = \[3,5,10,6,9\], profit = \[20,20,100,70,60\]
**Output:** 150
**Explanation:** The subset chosen is the first, fourth and fifth job.
Profit obtained 150 = 20 + 70 + 60.

**Example 3:**

**Input:** startTime = \[1,1,1\], endTime = \[2,3,4\], profit = \[5,6,4\]
**Output:** 6

**Constraints:**

*   `1 <= startTime.length == endTime.length == profit.length <= 5 * 104`
*   `1 <= startTime[i] < endTime[i] <= 109`
*   `1 <= profit[i] <= 104`

## A solution in Java

```java
import java.util.Arrays;

public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
    int n = startTime.length;
    int[][] jobs = new int[n][3];

    for (int i = 0; i < n; i++) {
        jobs[i] = new int[] {endTime[i], startTime[i], profit[i]};
    }

    Arrays.sort(jobs, (a, b) -> a[0] - b[0]);
    int[] dp = new int[n];
    dp[0] = jobs[0][2];

    for (int i = 1; i < n; i++) {
        int L = -1;
        for (int j = i - 1; j >= 0; j--) {
            if (jobs[j][1] >= jobs[L == -1 ? i : L][0]) {
                L = j;
            }
        }
        dp[i] = Math.max(dp[i - 1], (L == -1 ? 0 : dp[L]) + jobs[i][2]);
    }

    return dp[n - 1];
}
```
1. Create an array of jobs containing tuples (endTime, startTime, profit)
2. Sort the jobs in increasing order of their end times
3. Initialize a dynamic programming array, `dp`. Set `dp[0]` to the profit of the first job in the sorted jobs array
4. Iterate over the sorted jobs array, and for each job, find the index `L` of the latest non-conflicting job in the array (i.e., a job whose end time is less than or equal to the start time of the current job)
5. Update `dp[i]` to the maximum of the profit of the previous job `dp[i - 1]`, and the sum of the profit of the current job and the profit of the latest non-conflicting job `(0 if L == -1 else dp[L]) + jobs[i][2]`
6. Return the last element of the `dp` array, which represents the maximum profit that can be obtained considering all non-overlapping scheduled jobs

## A solution in C++

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

int jobScheduling(std::vector<int>& startTime, std::vector<int>& endTime, std::vector<int>& profit) {
    int n = startTime.size();
    std::vector<std::tuple<int, int, int>> jobs(n);

    for (int i = 0; i < n; ++i) {
        jobs[i] = {endTime[i], startTime[i], profit[i]};
    }

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

    std::vector<int> dp(n);
    dp[0] = std::get<2>(jobs[0]);

    for (int i = 1; i < n; ++i) {
        int L = -1;
        for (int j = i - 1; j >= 0; --j) {
            if (std::get<1>(jobs[j]) >= std::get<0>(jobs[L == -1 ? i : L])) {
                L = j;
            }
        }
        dp[i] = std::max(dp[i - 1], (L == -1 ? 0 : dp[L]) + std::get<2>(jobs[i]));
    }

    return dp[n - 1];
}
```
1. Create an array of jobs containing tuples (endTime, startTime, profit)
2. Sort the jobs in increasing order of their end times
3. Initialize a dynamic programming array, `dp`. Set `dp[0]` to the profit of the first job in the sorted jobs array
4. Iterate over the sorted jobs array, and for each job, find the index `L` of the latest non-conflicting job in the array (i.e., a job whose end time is less than or equal to the start time of the current job)
5. Update `dp[i]` to the maximum of the profit of the previous job `dp[i - 1]`, and the sum of the profit of the current job and the profit of the latest non-conflicting job `(0 if L == -1 else dp[L]) + jobs[i][2]`
6. Return the last element of the `dp` array, which represents the maximum profit that can be obtained considering all non-overlapping scheduled jobs

## A solution in Python

```python
from bisect import bisect_left

def jobScheduling(startTime, endTime, profit):
    jobs = sorted(zip(endTime, startTime, profit))
    dp = [jobs[0][2]]

    def latestNonConflict(index):
        startTimeToFind = jobs[index][1]
        index = bisect_left([job[0] for job in jobs], startTimeToFind)
        if index:
            return index - 1
        return -1

    for i in range(1, len(jobs)):
        L = latestNonConflict(i)
        dp.append(max(dp[-1], (0 if L == -1 else dp[L]) + jobs[i][2]))

    return dp[-1]
```
1. Create an array of jobs containing tuples (endTime, startTime, profit)
2. Sort the jobs in increasing order of their end times
3. Initialize a dynamic programming array, `dp`. Set `dp[0]` to the profit of the first job in the sorted jobs array
4. Iterate over the sorted jobs array, and for each job, find the index `L` of the latest non-conflicting job in the array (i.e., a job whose end time is less than or equal to the start time of the current job)
5. Update `dp[i]` to the maximum of the profit of the previous job `dp[i - 1]`, and the sum of the profit of the current job and the profit of the latest non-conflicting job `(0 if L == -1 else dp[L]) + jobs[i][2]`
6. Return the last element of the `dp` array, which represents the maximum profit that can be obtained considering all non-overlapping scheduled jobs

## A solution in Javascript

```javascript
function jobScheduling(startTime, endTime, profit) {
    const n = startTime.length;
    const jobs = [];

    for (let i = 0; i < n; i++) {
        jobs.push([endTime[i], startTime[i], profit[i]]);
    }

    jobs.sort((a, b) => a[0] - b[0]);
    const dp = new Array(n);
    dp[0] = jobs[0][2];

    for (let i = 1; i < n; i++) {
        let L = -1;
        for (let j = i - 1; j >= 0; j--) {
            if (jobs[j][1] >= jobs[L === -1 ? i : L][0]) {
                L = j;
            }
        }
        dp[i] = Math.max(dp[i - 1], (L === -1 ? 0 : dp[L]) + jobs[i][2]);
    }

    return dp[n - 1];
}
```
1. Create an array of jobs containing tuples (endTime, startTime, profit)
2. Sort the jobs in increasing order of their end times
3. Initialize a dynamic programming array, `dp`. Set `dp[0]` to the profit of the first job in the sorted jobs array
4. Iterate over the sorted jobs array, and for each job, find the index `L` of the latest non-conflicting job in the array (i.e., a job whose end time is less than or equal to the start time of the current job)
5. Update `dp[i]` to the maximum of the profit of the previous job `dp[i - 1]`, and the sum of the profit of the current job and the profit of the latest non-conflicting job `(0 if L == -1 else dp[L]) + jobs[i][2]`
6. Return the last element of the `dp` array, which represents the maximum profit that can be obtained considering all non-overlapping scheduled jobs


# Web Crawler

- slug: web-crawler
- difficulty: Medium

Given a url `startUrl` and an interface `HtmlParser`, implement a web crawler to crawl all links that are under the **same hostname** as `startUrl`.

Return all urls obtained by your web crawler in **any** order.

Your crawler should:

*   Start from the page: `startUrl`
*   Call `HtmlParser.getUrls(url)` to get all urls from a webpage of given url.
*   Do not crawl the same link twice.
*   Explore only the links that are under the **same hostname** as `startUrl`.

As shown in the example url above, the hostname is `example.org`. For simplicity sake, you may assume all urls use **http protocol** without any **port** specified. For example, the urls `http://leetcode.com/problems` and `http://leetcode.com/contest` are under the same hostname, while urls `http://example.org/test` and `http://example.com/abc` are not under the same hostname.

The `HtmlParser` interface is defined as such:

interface HtmlParser {
  // Return a list of all urls from a webpage of given _url_.
  public List getUrls(String url);
}

Below are two examples explaining the functionality of the problem, for custom testing purposes you'll have three variables `urls`, `edges` and `startUrl`. Notice that you will only have access to `startUrl` in your code, while `urls` and `edges` are not directly accessible to you in code.

Note: Consider the same URL with the trailing slash "/ " as a different URL. For example, "http://news.yahoo.com ", and "http://news.yahoo.com/ " are different urls.

**Example 1:**

**Input:**
urls = \[
   "http://news.yahoo.com ",
   "http://news.yahoo.com/news ",
   "http://news.yahoo.com/news/topics/ ",
   "http://news.google.com ",
   "http://news.yahoo.com/us "
\]
edges = \[\[2,0\],\[2,1\],\[3,2\],\[3,1\],\[0,4\]\]
startUrl =  "http://news.yahoo.com/news/topics/ "
**Output:** \[
   "http://news.yahoo.com ",
   "http://news.yahoo.com/news ",
   "http://news.yahoo.com/news/topics/ ",
   "http://news.yahoo.com/us "
\]

**Example 2:**

**Input:**
urls = \[
   "http://news.yahoo.com ",
   "http://news.yahoo.com/news ",
   "http://news.yahoo.com/news/topics/ ",
   "http://news.google.com "
\]
edges = \[\[0,2\],\[2,1\],\[3,2\],\[3,1\],\[3,0\]\]
startUrl =  "http://news.google.com "
**Output:** \[ "http://news.google.com "\]
**Explanation:** The startUrl links to all other pages that do not share the same hostname.

**Constraints:**

*   `1 <= urls.length <= 1000`
*   `1 <= urls[i].length <= 300`
*   `startUrl` is one of the `urls`.
*   Hostname label must be from 1 to 63 characters long, including the dots, may contain only the ASCII letters from 'a' to 'z', digits from '0' to '9' and the hyphen-minus character ('-').
*   The hostname may not start or end with the hyphen-minus character ('-').
*   See: [https://en.wikipedia.org/wiki/Hostname#Restrictions\_on\_valid\_hostnames](https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_hostnames)
*   You may assume there're no duplicates in url library.

## A solution in Java

```java
public int tribonacci(int n) {
    if(n==0) return 0;
    if(n==1 || n==2) return 1;
    int a = 0, b = 1, c = 1, d;
    for(int i = 3; i <= n; i++) {
        d = a + b + c;
        a = b;
        b = c;
        c = d;
    }
    return c;
}
```
The algorithm initializes the first three Tribonacci numbers `a`, `b`, and `c` with the values `0`, `1`, and `1`, respectively. It then iterates from `i=3` to `i=n`, computing each next Tribonacci number as the sum of the previous three (`a, b, c`). After each iteration, it shifts the values of `a`, `b`, and `c` to the right, dropping the smallest one and assigning the new calculated value to the last position. This is done until the value of `c` is the nth Tribonacci number.

Finally, the algorithm returns the latest value of `c`, which represents the desired Tribonacci number `Tn`.

## A solution in C++

```cpp
int tribonacci(int n) {
    if(n==0) return 0;
    if(n==1 || n==2) return 1;
    int a = 0, b = 1, c = 1, d;
    for(int i = 3; i <= n; ++i) {
        d = a + b + c;
        a = b;
        b = c;
        c = d;
    }
    return c;
}
```
The algorithm initializes the first three Tribonacci numbers `a`, `b`, and `c` with the values `0`, `1`, and `1`, respectively. It then iterates from `i=3` to `i=n`, computing each next Tribonacci number as the sum of the previous three (`a, b, c`). After each iteration, it shifts the values of `a`, `b`, and `c` to the right, dropping the smallest one and assigning the new calculated value to the last position. This is done until the value of `c` is the nth Tribonacci number.

Finally, the algorithm returns the latest value of `c`, which represents the desired Tribonacci number `Tn`.

## A solution in Python

```python
def tribonacci(n: int) -> int:
    if n == 0: return 0
    if n == 1 or n == 2: return 1
    a, b, c = 0, 1, 1
    for _ in range(3, n + 1):
        a, b, c = b, c, a + b + c
    return c
```
The algorithm initializes the first three Tribonacci numbers `a`, `b`, and `c` with the values `0`, `1`, and `1`, respectively. It then iterates from `i=3` to `i=n`, computing each next Tribonacci number as the sum of the previous three (`a, b, c`). After each iteration, it shifts the values of `a`, `b`, and `c` to the right, dropping the smallest one and assigning the new calculated value to the last position. This is done until the value of `c` is the nth Tribonacci number.

Finally, the algorithm returns the latest value of `c`, which represents the desired Tribonacci number `Tn`.

## A solution in Javascript

```javascript
function tribonacci(n) {
    if(n==0) return 0;
    if(n==1 || n==2) return 1;
    let a = 0, b = 1, c = 1, d;
    for(let i = 3; i <= n; ++i) {
        d = a + b + c;
        a = b;
        b = c;
        c = d;
    }
    return c;
}
```
The algorithm initializes the first three Tribonacci numbers `a`, `b`, and `c` with the values `0`, `1`, and `1`, respectively. It then iterates from `i=3` to `i=n`, computing each next Tribonacci number as the sum of the previous three (`a, b, c`). After each iteration, it shifts the values of `a`, `b`, and `c` to the right, dropping the smallest one and assigning the new calculated value to the last position. This is done until the value of `c` is the nth Tribonacci number.

Finally, the algorithm returns the latest value of `c`, which represents the desired Tribonacci number `Tn`.


# Find Positive Integer Solution for a Given Equation

- slug: find-positive-integer-solution-for-a-given-equation
- difficulty: Medium

Given a callable function `f(x, y)` **with a hidden formula** and a value `z`, reverse engineer the formula and return _all positive integer pairs_ `x` _and_ `y` _where_ `f(x,y) == z`. You may return the pairs in any order.

While the exact formula is hidden, the function is monotonically increasing, i.e.:

*   `f(x, y) < f(x + 1, y)`
*   `f(x, y) < f(x, y + 1)`

The function interface is defined like this:

interface CustomFunction {
public:
  // Returns some positive integer f(x, y) for two positive integers x and y based on a formula.
  int f(int x, int y);
};

We will judge your solution as follows:

*   The judge has a list of `9` hidden implementations of `CustomFunction`, along with a way to generate an **answer key** of all valid pairs for a specific `z`.
*   The judge will receive two inputs: a `function_id` (to determine which implementation to test your code with), and the target `z`.
*   The judge will call your `findSolution` and compare your results with the **answer key**.
*   If your results match the **answer key**, your solution will be `Accepted`.

**Example 1:**

**Input:** function\_id = 1, z = 5
**Output:** \[\[1,4\],\[2,3\],\[3,2\],\[4,1\]\]
**Explanation:** The hidden formula for function\_id = 1 is f(x, y) = x + y.
The following positive integer values of x and y make f(x, y) equal to 5:
x=1, y=4 -> f(1, 4) = 1 + 4 = 5.
x=2, y=3 -> f(2, 3) = 2 + 3 = 5.
x=3, y=2 -> f(3, 2) = 3 + 2 = 5.
x=4, y=1 -> f(4, 1) = 4 + 1 = 5.

**Example 2:**

**Input:** function\_id = 2, z = 5
**Output:** \[\[1,5\],\[5,1\]\]
**Explanation:** The hidden formula for function\_id = 2 is f(x, y) = x \* y.
The following positive integer values of x and y make f(x, y) equal to 5:
x=1, y=5 -> f(1, 5) = 1 \* 5 = 5.
x=5, y=1 -> f(5, 1) = 5 \* 1 = 5.

**Constraints:**

*   `1 <= function_id <= 9`
*   `1 <= z <= 100`
*   It is guaranteed that the solutions of `f(x, y) == z` will be in the range `1 <= x, y <= 1000`.
*   It is also guaranteed that `f(x, y)` will fit in 32 bit signed integer if `1 <= x, y <= 1000`.

## A solution in Java

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

public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
    List<List<Integer>> results = new ArrayList<>();
    for (int x = 1; x <= 1000; x++) {
        for (int y = 1; y <= 1000; y++) {
            if (customfunction.f(x, y) == z) {
                List<Integer> pair = new ArrayList<>();
                pair.add(x);
                pair.add(y);
                results.add(pair);
            } else if (customfunction.f(x, y) > z) {
                break;
            }
        }
    }
    return results;
}
```
To solve the given problem, we need to iterate through all positive integers `x` and `y` between 1 and 1000. For each pair of `x` and `y`, we will call the custom function `f(x, y)` and check if it returns the desired value `z`. If so, we will add the pair `[x, y]` to the result list. If the function returns a value greater than `z`, we will break the inner loop as we know that for this `x`, the values of `y` will only increase the result further, which can't be equal to `z`. Thus we will move on to the next iteration of `x`. Once all pairs of x and y have been tested, we return the resulting pairs list.

## A solution in C++

```cpp
#include<vector>
#include "CustomFunction.h"

std::vector<std::vector<int>> findSolution(CustomFunction& customfunction, int z) {
    std::vector<std::vector<int>> results;
    for (int x = 1; x <= 1000; x++) {
        for (int y = 1; y <= 1000; y++) {
            if (customfunction.f(x, y) == z) {
                results.push_back({x, y});
            } else if (customfunction.f(x, y) > z) {
                break;
            }
        }
    }
    return results;
}
```
To solve the given problem, we need to iterate through all positive integers `x` and `y` between 1 and 1000. For each pair of `x` and `y`, we will call the custom function `f(x, y)` and check if it returns the desired value `z`. If so, we will add the pair `[x, y]` to the result list. If the function returns a value greater than `z`, we will break the inner loop as we know that for this `x`, the values of `y` will only increase the result further, which can't be equal to `z`. Thus we will move on to the next iteration of `x`. Once all pairs of x and y have been tested, we return the resulting pairs list.

## A solution in Python

```python
def findSolution(customfunction: 'CustomFunction', z: int) -> List[List[int]]:
    results = []
    for x in range(1, 1001):
        for y in range(1, 1001):
            if customfunction.f(x, y) == z:
                results.append([x, y])
            elif customfunction.f(x, y) > z:
                break
    return results
```
To solve the given problem, we need to iterate through all positive integers `x` and `y` between 1 and 1000. For each pair of `x` and `y`, we will call the custom function `f(x, y)` and check if it returns the desired value `z`. If so, we will add the pair `[x, y]` to the result list. If the function returns a value greater than `z`, we will break the inner loop as we know that for this `x`, the values of `y` will only increase the result further, which can't be equal to `z`. Thus we will move on to the next iteration of `x`. Once all pairs of x and y have been tested, we return the resulting pairs list.

## A solution in Javascript

```javascript
var findSolution = function(customFunction, z) {
    let results = [];
    for (let x = 1; x <= 1000; x++) {
        for (let y = 1; y <= 1000; y++) {
            if (customFunction.f(x, y) === z) {
                results.push([x, y]);
            } else if (customFunction.f(x, y) > z) {
                break;
            }
        }
    }
    return results;
};
```
To solve the given problem, we need to iterate through all positive integers `x` and `y` between 1 and 1000. For each pair of `x` and `y`, we will call the custom function `f(x, y)` and check if it returns the desired value `z`. If so, we will add the pair `[x, y]` to the result list. If the function returns a value greater than `z`, we will break the inner loop as we know that for this `x`, the values of `y` will only increase the result further, which can't be equal to `z`. Thus we will move on to the next iteration of `x`. Once all pairs of x and y have been tested, we return the resulting pairs list.


# Circular Permutation in Binary Representation

- slug: circular-permutation-in-binary-representation
- difficulty: Medium

Given 2 integers `n` and `start`. Your task is return **any** permutation `p` of `(0,1,2.....,2^n -1)` such that :

*   `p[0] = start`
*   `p[i]` and `p[i+1]` differ by only one bit in their binary representation.
*   `p[0]` and `p[2^n -1]` must also differ by only one bit in their binary representation.

**Example 1:**

**Input:** n = 2, start = 3
**Output:** \[3,2,0,1\]
**Explanation:** The binary representation of the permutation is (11,10,00,01).
All the adjacent element differ by one bit. Another valid permutation is \[3,1,0,2\]

**Example 2:**

**Input:** n = 3, start = 2
**Output:** \[2,6,7,5,4,0,1,3\]
**Explanation:** The binary representation of the permutation is (010,110,111,101,100,000,001,011).

**Constraints:**

*   `1 <= n <= 16`
*   `0 <= start < 2 ^ n`

## A solution in Java

```java
public String alphabetBoardPath(String target) {
    int x = 0, y = 0;
    StringBuilder sb = new StringBuilder();

    for (char c : target.toCharArray()) {
        int dx = (c - 'a') / 5;
        int dy = (c - 'a') % 5;
        while (x > dx) {
            sb.append('U');
            x--;
        }
        while (y > dy) {
            sb.append('L');
            y--;
        }
        while (x < dx) {
            sb.append('D');
            x++;
        }
        while (y < dy) {
            sb.append('R');
            y++;
        }
        sb.append('!');
    }
    return sb.toString();
}
```
The algorithm follows these steps:
1. Initialize a current position variable at (0, 0) and an empty result string.
2. For each character in the target string:
   - Calculate the target row and column based on the character's position in the alphabet. (Convert the character to the ASCII code and subtract the ASCII code of 'a'). Then take the quotient and remainder when divided by 5.
   - Move the current position to the target position by adding the appropriate moves ('U', 'L', 'D', 'R') to the result string. Adjust the current position variables accordingly.
   - Add an exclamation mark to the result string to indicate a valid touch.
3. After the loop ends, return the result string.

The time complexity of this algorithm is O(n), as it iterates through the characters in the target string.

## A solution in C++

```cpp
#include <string>
#include <utility>

std::string alphabetBoardPath(const std::string& target) {
    std::string result;
    std::pair<int, int> startPosition(0, 0);

    for (char t : target) {
        int r = (t - 'a') / 5;
        int c = (t - 'a') % 5;
        while (startPosition.first > r) {
            result.push_back('U');
            --startPosition.first;
        }
        while (startPosition.second > c) {
            result.push_back('L');
            --startPosition.second;
        }
        while (startPosition.first < r) {
            result.push_back('D');
            ++startPosition.first;
        }
        while (startPosition.second < c) {
            result.push_back('R');
            ++startPosition.second;
        }
        result.push_back('!');
    }
    return result;
}
```
The algorithm follows these steps:
1. Initialize a current position variable at (0, 0) and an empty result string.
2. For each character in the target string:
   - Calculate the target row and column based on the character's position in the alphabet. (Convert the character to the ASCII code and subtract the ASCII code of 'a'). Then take the quotient and remainder when divided by 5.
   - Move the current position to the target position by adding the appropriate moves ('U', 'L', 'D', 'R') to the result string. Adjust the current position variables accordingly.
   - Add an exclamation mark to the result string to indicate a valid touch.
3. After the loop ends, return the result string.

The time complexity of this algorithm is O(n), as it iterates through the characters in the target string.

## A solution in Python

```python
def alphabet_board_path(target: str) -> str:
    startX, startY = 0, 0
    result = []

    for t in target:
        targetX, targetY = divmod(ord(t) - ord('a'), 5)
        while startX > targetX:
            result.append('U')
            startX -= 1
        while startY > targetY:
            result.append('L')
            startY -= 1
        while startX < targetX:
            result.append('D')
            startX += 1
        while startY < targetY:
            result.append('R')
            startY += 1
        result.append('!')

    return ''.join(result)
```
The algorithm follows these steps:
1. Initialize a current position variable at (0, 0) and an empty result string.
2. For each character in the target string:
   - Calculate the target row and column based on the character's position in the alphabet. (Convert the character to the ASCII code and subtract the ASCII code of 'a'). Then take the quotient and remainder when divided by 5.
   - Move the current position to the target position by adding the appropriate moves ('U', 'L', 'D', 'R') to the result string. Adjust the current position variables accordingly.
   - Add an exclamation mark to the result string to indicate a valid touch.
3. After the loop ends, return the result string.

The time complexity of this algorithm is O(n), as it iterates through the characters in the target string.

## A solution in Javascript

```javascript
function alphabetBoardPath(target) {
    let res = '';
    let startX = 0;
    let startY = 0;

    for (let t of target) {
        let newPos = t.charCodeAt(0) - 'a'.charCodeAt(0);
        let targetX = Math.floor(newPos / 5);
        let targetY = newPos % 5;

        while (startX > targetX) {
            res += 'U';
            startX--;
        }
        while (startY > targetY) {
            res += 'L';
            startY--;
        }
        while (startX < targetX) {
            res += 'D';
            startX++;
        }
        while (startY < targetY) {
            res += 'R';
            startY++;
        }
        res += '!';
    }
    return res;
}
```
The algorithm follows these steps:
1. Initialize a current position variable at (0, 0) and an empty result string.
2. For each character in the target string:
   - Calculate the target row and column based on the character's position in the alphabet. (Convert the character to the ASCII code and subtract the ASCII code of 'a'). Then take the quotient and remainder when divided by 5.
   - Move the current position to the target position by adding the appropriate moves ('U', 'L', 'D', 'R') to the result string. Adjust the current position variables accordingly.
   - Add an exclamation mark to the result string to indicate a valid touch.
3. After the loop ends, return the result string.

The time complexity of this algorithm is O(n), as it iterates through the characters in the target string.


# Maximum Length of a Concatenated String with Unique Characters

- slug: maximum-length-of-a-concatenated-string-with-unique-characters
- difficulty: Medium

You are given an array of strings `arr`. A string `s` is formed by the **concatenation** of a **subsequence** of `arr` that has **unique characters**.

Return _the **maximum** possible length_ of `s`.

A **subsequence** is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

**Example 1:**

**Input:** arr = \[ "un ", "iq ", "ue "\]
**Output:** 4
**Explanation:** All the valid concatenations are:
-  " "
-  "un "
-  "iq "
-  "ue "
-  "uniq " ( "un " +  "iq ")
-  "ique " ( "iq " +  "ue ")
Maximum length is 4.

**Example 2:**

**Input:** arr = \[ "cha ", "r ", "act ", "ers "\]
**Output:** 6
**Explanation:** Possible longest valid concatenations are  "chaers " ( "cha " +  "ers ") and  "acters " ( "act " +  "ers ").

**Example 3:**

**Input:** arr = \[ "abcdefghijklmnopqrstuvwxyz "\]
**Output:** 26
**Explanation:** The only string in arr has all 26 characters.

**Constraints:**

*   `1 <= arr.length <= 16`
*   `1 <= arr[i].length <= 26`
*   `arr[i]` contains only lowercase English letters.

## A solution in Java

```java
public int largest1BorderedSquare(int[][] grid) {
    int m = grid.length;
    int n = grid[0].length;
    int[][] horizontal = new int[m][n];
    int[][] vertical = new int[m][n];

    int maxSquareSize = 0;

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 1) {
                horizontal[i][j] = (j == 0) ? 1 : horizontal[i][j - 1] + 1;
                vertical[i][j] = (i == 0) ? 1 : vertical[i - 1][j] + 1;

                int minSize = Math.min(horizontal[i][j], vertical[i][j]);
                while (minSize > maxSquareSize) {
                    if (horizontal[i - minSize + 1][j] >= minSize &&
                        vertical[i][j - minSize + 1] >= minSize) {
                        maxSquareSize = minSize;
                    }
                    minSize--;
                }
            }
        }
    }

    return maxSquareSize * maxSquareSize;
}
```
1. Create two matrices `horizontal` and `vertical` to store the counts of consecutive 1s from left to right and from top to bottom respectively.
2. Iterate through each element in the `grid`. If the current element is 1, update the respective `horizontal` and `vertical` counts.
3. Calculate the minimum of the `horizontal` and `vertical` counts, `min_size`.
4. Check if a square subgrid of size `min_size` exists with all 1s on its border. If found, update the `max_square_size`.
5. Check for smaller square sizes by decrementing `min_size`.
6. Finally, return the area of the largest square subgrid found by squaring `max_square_size`. If no such subgrid is found, the result is `0`.

## A solution in C++

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

    int max_square_size = 0;

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 1) {
                horizontal[i][j] = (j == 0) ? 1 : horizontal[i][j - 1] + 1;
                vertical[i][j] = (i == 0) ? 1 : vertical[i - 1][j] + 1;

                int min_size = min(horizontal[i][j], vertical[i][j]);
                while (min_size > max_square_size) {
                    if (horizontal[i - min_size + 1][j] >= min_size &&
                        vertical[i][j - min_size + 1] >= min_size) {
                        max_square_size = min_size;
                    }
                    min_size--;
                }
            }
        }
    }

    return max_square_size * max_square_size;
}
```
1. Create two matrices `horizontal` and `vertical` to store the counts of consecutive 1s from left to right and from top to bottom respectively.
2. Iterate through each element in the `grid`. If the current element is 1, update the respective `horizontal` and `vertical` counts.
3. Calculate the minimum of the `horizontal` and `vertical` counts, `min_size`.
4. Check if a square subgrid of size `min_size` exists with all 1s on its border. If found, update the `max_square_size`.
5. Check for smaller square sizes by decrementing `min_size`.
6. Finally, return the area of the largest square subgrid found by squaring `max_square_size`. If no such subgrid is found, the result is `0`.

## A solution in Python

```python
def largest1BorderedSquare(grid):
    m, n = len(grid), len(grid[0])
    horizontal, vertical = [[0] * n for _ in range(m)], [[0] * n for _ in range(m)]

    max_square_size = 0

    for i in range(m):
        for j in range(n):
            if grid[i][j] == 1:
                horizontal[i][j] = 1 if j == 0 else horizontal[i][j - 1] + 1
                vertical[i][j] = 1 if i == 0 else vertical[i - 1][j] + 1

                min_size = min(horizontal[i][j], vertical[i][j])
                while min_size > max_square_size:
                    if (horizontal[i - min_size + 1][j] >= min_size and
                        vertical[i][j - min_size + 1] >= min_size):
                        max_square_size = min_size
                    min_size -= 1

    return max_square_size * max_square_size
```
1. Create two matrices `horizontal` and `vertical` to store the counts of consecutive 1s from left to right and from top to bottom respectively.
2. Iterate through each element in the `grid`. If the current element is 1, update the respective `horizontal` and `vertical` counts.
3. Calculate the minimum of the `horizontal` and `vertical` counts, `min_size`.
4. Check if a square subgrid of size `min_size` exists with all 1s on its border. If found, update the `max_square_size`.
5. Check for smaller square sizes by decrementing `min_size`.
6. Finally, return the area of the largest square subgrid found by squaring `max_square_size`. If no such subgrid is found, the result is `0`.

## A solution in Javascript

```javascript
function largest1BorderedSquare(grid) {
    const m = grid.length;
    const n = grid[0].length;
    const horizontal = Array.from({ length: m }, () => Array(n).fill(0));
    const vertical = Array.from({ length: m }, () => Array(n).fill(0));

    let maxSquareSize = 0;

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 1) {
                horizontal[i][j] = (j === 0) ? 1 : horizontal[i][j - 1] + 1;
                vertical[i][j] = (i === 0) ? 1 : vertical[i - 1][j] + 1;

                let minSize = Math.min(horizontal[i][j], vertical[i][j]);
                while (minSize > maxSquareSize) {
                    if (horizontal[i - minSize + 1][j] >= minSize &&
                        vertical[i][j - minSize + 1] >= minSize) {
                        maxSquareSize = minSize;
                    }
                    minSize--;
                }
            }
        }
    }

    return maxSquareSize * maxSquareSize;
}
```
1. Create two matrices `horizontal` and `vertical` to store the counts of consecutive 1s from left to right and from top to bottom respectively.
2. Iterate through each element in the `grid`. If the current element is 1, update the respective `horizontal` and `vertical` counts.
3. Calculate the minimum of the `horizontal` and `vertical` counts, `min_size`.
4. Check if a square subgrid of size `min_size` exists with all 1s on its border. If found, update the `max_square_size`.
5. Check for smaller square sizes by decrementing `min_size`.
6. Finally, return the area of the largest square subgrid found by squaring `max_square_size`. If no such subgrid is found, the result is `0`.


# Tiling a Rectangle with the Fewest Squares

- slug: tiling-a-rectangle-with-the-fewest-squares
- difficulty: Hard

Given a rectangle of size `n` x `m`, return _the minimum number of integer-sided squares that tile the rectangle_.

**Example 1:**

**Input:** n = 2, m = 3
**Output:** 3
**Explanation:** `3` squares are necessary to cover the rectangle.
`2` (squares of `1x1`)
`1` (square of `2x2`)

**Example 2:**

**Input:** n = 5, m = 8
**Output:** 5

**Example 3:**

**Input:** n = 11, m = 13
**Output:** 6

**Constraints:**

*   `1 <= n, m <= 13`

## A solution in Java

```java
public int stoneGameII(int[] piles) {
    int n = piles.length;
    int[][] memo = new int[n][n + 1];

    for (int i = n - 2 ; i >= 0; --i) {
        piles[i] += piles[i + 1];
    }

    return search(piles, 0, 1, memo);
}

private int search(int[] piles, int idx, int M, int[][] memo) {
    int n = piles.length;

    if (idx + 2 * M >= n) {
        return piles[idx];
    }

    if (memo[idx][M] > 0) {
        return memo[idx][M];
    }

    memo[idx][M] = 0;

    for (int x = 1; x <= 2 * M; ++x) {
        memo[idx][M] = Math.max(memo[idx][M], piles[idx] - search(piles, idx + x, Math.max(M, x), memo));
    }

    return memo[idx][M];
}
```
The algorithm uses dynamic programming with memoization. It first calculates the total number of remaining stones starting from each pile. This can be done in O(n) time complexity. Then, it checks the memoization table for previously computed values.

The main search function goes through all possible values of X (1 <= X <= 2M) while recursively maximizing the stones difference. After all the positions are checked, it returns the maximum value found. This way, the algorithm guarantees that Alice will choose the optimal move to get the maximum number of stones possible.

The time complexity is O(n^2*M) where n is the number of piles and M is the maximum limit of piles that can be picked.

## A solution in C++

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

int stoneGameII(std::vector<int>& piles) {
    int n = piles.size();
    std::vector<std::vector<int>> memo(n, std::vector<int>(n + 1, 0));

    for (int i = n - 2; i >= 0; --i) {
        piles[i] += piles[i + 1];
    }

    function<int(int, int)> search = [&](int idx, int M) {
        if (idx + 2 * M >= n) {
            return piles[idx];
        }
        if (memo[idx][M] > 0) {
            return memo[idx][M];
        }
        memo[idx][M] = 0;
        for (int x = 1; x <= 2 * M; ++x) {
            memo[idx][M] = std::max(memo[idx][M], piles[idx] - search(idx + x, std::max(M, x)));
        }
        return memo[idx][M];
    };

    return search(0, 1);
}
```
The algorithm uses dynamic programming with memoization. It first calculates the total number of remaining stones starting from each pile. This can be done in O(n) time complexity. Then, it checks the memoization table for previously computed values.

The main search function goes through all possible values of X (1 <= X <= 2M) while recursively maximizing the stones difference. After all the positions are checked, it returns the maximum value found. This way, the algorithm guarantees that Alice will choose the optimal move to get the maximum number of stones possible.

The time complexity is O(n^2*M) where n is the number of piles and M is the maximum limit of piles that can be picked.

## A solution in Python

```python
from functools import lru_cache

def stoneGameII(piles):
    n = len(piles)
    for i in range(n - 2, -1, -1):
        piles[i] += piles[i + 1]

    @lru_cache(None)
    def search(idx, M):
        if idx + 2 * M >= n:
            return piles[idx]
        return max(piles[idx] - search(idx + x, max(M, x)) for x in range(1, 2 * M + 1))

    return search(0, 1)
```
The algorithm uses dynamic programming with memoization. It first calculates the total number of remaining stones starting from each pile. This can be done in O(n) time complexity. Then, it checks the memoization table for previously computed values.

The main search function goes through all possible values of X (1 <= X <= 2M) while recursively maximizing the stones difference. After all the positions are checked, it returns the maximum value found. This way, the algorithm guarantees that Alice will choose the optimal move to get the maximum number of stones possible.

The time complexity is O(n^2*M) where n is the number of piles and M is the maximum limit of piles that can be picked.

## A solution in Javascript

```javascript
function stoneGameII(piles) {
    let n = piles.length;
    let memo = new Array(n).fill(0).map(() => new Array(n + 1).fill(0));

    for (let i = n - 2 ; i >= 0; --i) {
        piles[i] += piles[i + 1];
    }

    function search(idx, M) {
        if (idx + 2 * M >= n) {
            return piles[idx];
        }

        if (memo[idx][M] > 0) {
            return memo[idx][M];
        }

        memo[idx][M] = 0;

        for (let x = 1; x <= 2 * M; ++x) {
            memo[idx][M] = Math.max(memo[idx][M], piles[idx] - search(idx + x, Math.max(M, x)));
        }

        return memo[idx][M];
    }

    return search(0, 1);
}
```
The algorithm uses dynamic programming with memoization. It first calculates the total number of remaining stones starting from each pile. This can be done in O(n) time complexity. Then, it checks the memoization table for previously computed values.

The main search function goes through all possible values of X (1 <= X <= 2M) while recursively maximizing the stones difference. After all the positions are checked, it returns the maximum value found. This way, the algorithm guarantees that Alice will choose the optimal move to get the maximum number of stones possible.

The time complexity is O(n^2*M) where n is the number of piles and M is the maximum limit of piles that can be picked.


# Array Transformation

- slug: array-transformation
- difficulty: Easy

Given an initial array `arr`, every day you produce a new array using the array of the previous day.

On the `i`\-th day, you do the following operations on the array of day `i-1` to produce the array of day `i`:

1.  If an element is smaller than both its left neighbor and its right neighbor, then this element is incremented.
2.  If an element is bigger than both its left neighbor and its right neighbor, then this element is decremented.
3.  The first and last elements never change.

After some days, the array does not change. Return that final array.

**Example 1:**

**Input:** arr = \[6,2,3,4\]
**Output:** \[6,3,3,4\]
**Explanation:**
On the first day, the array is changed from \[6,2,3,4\] to \[6,3,3,4\].
No more operations can be done to this array.

**Example 2:**

**Input:** arr = \[1,6,3,4,3,5\]
**Output:** \[1,4,4,4,4,5\]
**Explanation:**
On the first day, the array is changed from \[1,6,3,4,3,5\] to \[1,5,4,3,4,5\].
On the second day, the array is changed from \[1,5,4,3,4,5\] to \[1,4,4,4,4,5\].
No more operations can be done to this array.

**Constraints:**

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

## A solution in Java

```java
public int sumEvenGrandparent(TreeNode root) {
    return sumEvenGrandparent(root, null, null);
}

private int sumEvenGrandparent(TreeNode root, TreeNode parent, TreeNode grandparent) {
    if (root == null) return 0;
    int sum = 0;
    if (grandparent != null && grandparent.val % 2 == 0) {
        sum += root.val;
    }
    sum += sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent);
    return sum;
}
```
We perform a depth-first search traversal of the binary tree.
For each node, we maintain the current node's parent and grandparent in the traversal.
While traversing the tree, we check if the current node's grandparent has an even value.
If yes, we add the current node's value to the sum.
The algorithm is the same for all languages, with only syntax differences.

## A solution in C++

```cpp
int sumEvenGrandparent(TreeNode* root, TreeNode* parent = nullptr, TreeNode* grandparent = nullptr) {
    if (!root) return 0;
    int sum = 0;
    if (grandparent && grandparent->val % 2 == 0) {
        sum += root->val;
    }
    sum += sumEvenGrandparent(root->left, root, parent) + sumEvenGrandparent(root->right, root, parent);
    return sum;
}
```
We perform a depth-first search traversal of the binary tree.
For each node, we maintain the current node's parent and grandparent in the traversal.
While traversing the tree, we check if the current node's grandparent has an even value.
If yes, we add the current node's value to the sum.
The algorithm is the same for all languages, with only syntax differences.

## A solution in Python

```python
def sumEvenGrandparent(root, parent=None, grandparent=None):
    if not root:
        return 0
    sum = 0
    if grandparent and grandparent.val % 2 == 0:
        sum += root.val
    sum += sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent)
    return sum
```
We perform a depth-first search traversal of the binary tree.
For each node, we maintain the current node's parent and grandparent in the traversal.
While traversing the tree, we check if the current node's grandparent has an even value.
If yes, we add the current node's value to the sum.
The algorithm is the same for all languages, with only syntax differences.

## A solution in Javascript

```javascript
function sumEvenGrandparent(root, parent = null, grandparent = null) {
    if (!root) return 0;
    let sum = 0;
    if (grandparent && grandparent.val % 2 === 0) {
        sum += root.val;
    }
    sum += sumEvenGrandparent(root.left, root, parent) + sumEvenGrandparent(root.right, root, parent);
    return sum;
}
```
We perform a depth-first search traversal of the binary tree.
For each node, we maintain the current node's parent and grandparent in the traversal.
While traversing the tree, we check if the current node's grandparent has an even value.
If yes, we add the current node's value to the sum.
The algorithm is the same for all languages, with only syntax differences.


# Design A Leaderboard

- slug: design-a-leaderboard
- difficulty: Medium

Design a Leaderboard class, which has 3 functions:

1.  `addScore(playerId, score)`: Update the leaderboard by adding `score` to the given player's score. If there is no player with such id in the leaderboard, add him to the leaderboard with the given `score`.
2.  `top(K)`: Return the score sum of the top `K` players.
3.  `reset(playerId)`: Reset the score of the player with the given id to 0 (in other words erase it from the leaderboard). It is guaranteed that the player was added to the leaderboard before calling this function.

Initially, the leaderboard is empty.

**Example 1:**

**Input:**
\[ "Leaderboard ", "addScore ", "addScore ", "addScore ", "addScore ", "addScore ", "top ", "reset ", "reset ", "addScore ", "top "\]
\[\[\],\[1,73\],\[2,56\],\[3,39\],\[4,51\],\[5,4\],\[1\],\[1\],\[2\],\[2,51\],\[3\]\]
**Output:**
\[null,null,null,null,null,null,73,null,null,null,141\]

**Explanation:**
Leaderboard leaderboard = new Leaderboard ();
leaderboard.addScore(1,73);   // leaderboard = \[\[1,73\]\];
leaderboard.addScore(2,56);   // leaderboard = \[\[1,73\],\[2,56\]\];
leaderboard.addScore(3,39);   // leaderboard = \[\[1,73\],\[2,56\],\[3,39\]\];
leaderboard.addScore(4,51);   // leaderboard = \[\[1,73\],\[2,56\],\[3,39\],\[4,51\]\];
leaderboard.addScore(5,4);    // leaderboard = \[\[1,73\],\[2,56\],\[3,39\],\[4,51\],\[5,4\]\];
leaderboard.top(1);           // returns 73;
leaderboard.reset(1);         // leaderboard = \[\[2,56\],\[3,39\],\[4,51\],\[5,4\]\];
leaderboard.reset(2);         // leaderboard = \[\[3,39\],\[4,51\],\[5,4\]\];
leaderboard.addScore(2,51);   // leaderboard = \[\[2,51\],\[3,39\],\[4,51\],\[5,4\]\];
leaderboard.top(3);           // returns 141 = 51 + 51 + 39;

**Constraints:**

*   `1 <= playerId, K <= 10000`
*   It's guaranteed that `K` is less than or equal to the current number of players.
*   `1 <= score <= 100`
*   There will be at most `1000` function calls.

## A solution in Java

```java
int numDistinctRepeatedSubstrings(String s) {
    HashSet<String> seen = new HashSet<>();
    for (int len = s.length() / 2; len >= 1; len--) {
        for (int i = 0; i <= s.length() - 2 * len; i++) {
            String substr = s.substring(i, i + len);
            if (s.indexOf(substr, i + len) != -1)
                seen.add(substr);
        }
    }
    return seen.size();
}
```
1. Initialize an empty set `seen` to store distinct substrings.
2. Iterate over the possible lengths of a substring from half the length of the input string to 1 (inclusive), because the maximum length of the duplicated substring would be half the length of the text in case it's fully repeated.
3. For each length, iterate over the string and extract a substring of that length starting at the current position.
4. Check if there is another occurrence of this substring after the current position (i.e., if it can be concatenated with itself).
5. If it satisfies the above condition, add it to the `seen` set.
6. At the end of the iterations, return the size of the `seen` set to get the number of distinct non-empty substrings that can be written as a concatenation of some string with itself.

## A solution in C++

```cpp
int numDistinctRepeatedSubstrings(const string& s) {
    unordered_set<string> seen;
    for (int len = s.length() / 2; len >= 1; len--) {
        for (int i = 0; i <= s.length() - 2 * len; i++) {
            string substr = s.substr(i, len);
            if (s.find(substr, i + len) != string::npos)
                seen.insert(substr);
        }
    }
    return seen.size();
}
```
1. Initialize an empty set `seen` to store distinct substrings.
2. Iterate over the possible lengths of a substring from half the length of the input string to 1 (inclusive), because the maximum length of the duplicated substring would be half the length of the text in case it's fully repeated.
3. For each length, iterate over the string and extract a substring of that length starting at the current position.
4. Check if there is another occurrence of this substring after the current position (i.e., if it can be concatenated with itself).
5. If it satisfies the above condition, add it to the `seen` set.
6. At the end of the iterations, return the size of the `seen` set to get the number of distinct non-empty substrings that can be written as a concatenation of some string with itself.

## A solution in Python

```python
def num_distinct_repeated_substrings(s):
    seen = set()
    for length in range(len(s) // 2, 0, -1):
        for i in range(len(s) - 2 * length + 1):
            substr = s[i:i + length]
            if substr in s[i + length:]:
                seen.add(substr)
    return len(seen)
```
1. Initialize an empty set `seen` to store distinct substrings.
2. Iterate over the possible lengths of a substring from half the length of the input string to 1 (inclusive), because the maximum length of the duplicated substring would be half the length of the text in case it's fully repeated.
3. For each length, iterate over the string and extract a substring of that length starting at the current position.
4. Check if there is another occurrence of this substring after the current position (i.e., if it can be concatenated with itself).
5. If it satisfies the above condition, add it to the `seen` set.
6. At the end of the iterations, return the size of the `seen` set to get the number of distinct non-empty substrings that can be written as a concatenation of some string with itself.

## A solution in Javascript

```javascript
function numDistinctRepeatedSubstrings(s) {
  let seen = new Set();
  for (let len = Math.floor(s.length / 2); len >= 1; len--) {
    for (let i = 0; i <= s.length - 2 * len; i++) {
      let substr = s.slice(i, i + len);
      if (s.indexOf(substr, i + len) !== -1)
        seen.add(substr);
    }
  }
  return seen.size;
}
```
1. Initialize an empty set `seen` to store distinct substrings.
2. Iterate over the possible lengths of a substring from half the length of the input string to 1 (inclusive), because the maximum length of the duplicated substring would be half the length of the text in case it's fully repeated.
3. For each length, iterate over the string and extract a substring of that length starting at the current position.
4. Check if there is another occurrence of this substring after the current position (i.e., if it can be concatenated with itself).
5. If it satisfies the above condition, add it to the `seen` set.
6. At the end of the iterations, return the size of the `seen` set to get the number of distinct non-empty substrings that can be written as a concatenation of some string with itself.


# Tree Diameter

- slug: tree-diameter
- difficulty: Medium

The **diameter** of a tree is **the number of edges** in the longest path in that tree.

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

Return _the **diameter** of the tree_.

**Example 1:**

**Input:** edges = \[\[0,1\],\[0,2\]\]
**Output:** 2
**Explanation:** The longest path of the tree is the path 1 - 0 - 2.

**Example 2:**

**Input:** edges = \[\[0,1\],\[1,2\],\[2,3\],\[1,4\],\[4,5\]\]
**Output:** 4
**Explanation:** The longest path of the tree is the path 3 - 2 - 1 - 4 - 5.

**Constraints:**

*   `n == edges.length + 1`
*   `1 <= n <= 104`
*   `0 <= ai, bi < n`
*   `ai != bi`

## A solution in Java

```java
import java.util.*;

class Solution {
    public int treeDiameter(int[][] edges) {
        Map<Integer, List<Integer>> tree = new HashMap<>();
        for (int[] edge : edges) {
            tree.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]);
            tree.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]);
        }

        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {0, 0});
        int furthest = 0;
        int maxDistance = 0;
        while (!queue.isEmpty()) {
            int[] info = queue.poll();
            int node = info[0];
            int distance = info[1];
            if (distance > maxDistance) {
                maxDistance = distance;
                furthest = node;
            }
            for (int neighbor : tree.get(node)) {
                tree.get(neighbor).remove((Integer)node);
                queue.add(new int[] {neighbor, distance + 1});
            }
        }

        queue.add(new int[] {furthest, 0});
        maxDistance = 0;
        while (!queue.isEmpty()) {
            int[] info = queue.poll();
            int node = info[0];
            int distance = info[1];
            if (distance > maxDistance) {
                maxDistance = distance;
            }
            for (int neighbor : tree.get(node)) {
                tree.get(neighbor).remove((Integer)node);
                queue.add(new int[] {neighbor, distance + 1});
            }
        }

        return maxDistance;
    }
}
```
To calculate the diameter of the tree, we can perform two breadth-first searches (BFS). First, we start a BFS from any arbitrary node (we can choose node 0) and find the furthest node in the tree. Then, we start another BFS from the furthest node found in the previous step and find its furthest node. The distance between these two nodes is the diameter of the tree.

1. Construct the tree from the given edges, storing each node's neighbors in a data structure (hashmap in C++ and Java, defaultdict in Python, and Map in JavaScript).

2. Perform the first BFS:
   - Initialize a queue with the starting node (0) and its distance (0).
   - Track the furthest node and its maximum distance from the starting node.
   - While the queue is not empty:
     - Dequeue the current node and its distance.
     - If the current distance is greater than the current maximum distance, update the furthest node and maximum distance.
     - For each neighbor of the current node:
       - Remove the edge between the current node and its neighbor.
       - Enqueue the neighbor and its distance from the current node (distance + 1).

3. Perform the second BFS (similar to the first BFS) from the furthest node found in the previous step. Calculate the new maximum distance, which is the diameter of the tree.

4. Return the diameter of the tree.

## A solution in C++

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

int treeDiameter(vector<vector<int>>& edges) {
    unordered_map<int, vector<int>> tree;
    for (const auto& edge : edges) {
        tree[edge[0]].push_back(edge[1]);
        tree[edge[1]].push_back(edge[0]);
    }

    queue<pair<int, int>> q;
    q.push({0, 0});
    int furthest = 0;
    int max_distance = 0;
    while (!q.empty()) {
        int node = q.front().first;
        int distance = q.front().second;
        q.pop();
        if (distance > max_distance) {
            max_distance = distance;
            furthest = node;
        }
        for (int neighbor : tree[node]) {
            tree[neighbor].erase(remove(tree[neighbor].begin(), tree[neighbor].end(), node), tree[neighbor].end());
            q.push({neighbor, distance + 1});
        }
    }

    q.push({furthest, 0});
    max_distance = 0;
    while (!q.empty()) {
        int node = q.front().first;
        int distance = q.front().second;
        q.pop();
        if (distance > max_distance) {
            max_distance = distance;
        }
        for (int neighbor : tree[node]) {
            tree[neighbor].erase(remove(tree[neighbor].begin(), tree[neighbor].end(), node), tree[neighbor].end());
            q.push({neighbor, distance + 1});
        }
    }

    return max_distance;
}
```
To calculate the diameter of the tree, we can perform two breadth-first searches (BFS). First, we start a BFS from any arbitrary node (we can choose node 0) and find the furthest node in the tree. Then, we start another BFS from the furthest node found in the previous step and find its furthest node. The distance between these two nodes is the diameter of the tree.

1. Construct the tree from the given edges, storing each node's neighbors in a data structure (hashmap in C++ and Java, defaultdict in Python, and Map in JavaScript).

2. Perform the first BFS:
   - Initialize a queue with the starting node (0) and its distance (0).
   - Track the furthest node and its maximum distance from the starting node.
   - While the queue is not empty:
     - Dequeue the current node and its distance.
     - If the current distance is greater than the current maximum distance, update the furthest node and maximum distance.
     - For each neighbor of the current node:
       - Remove the edge between the current node and its neighbor.
       - Enqueue the neighbor and its distance from the current node (distance + 1).

3. Perform the second BFS (similar to the first BFS) from the furthest node found in the previous step. Calculate the new maximum distance, which is the diameter of the tree.

4. Return the diameter of the tree.

## A solution in Python

```python
from collections import deque, defaultdict

def tree_diameter(edges):
    tree = defaultdict(list)
    for edge in edges:
        tree[edge[0]].append(edge[1])
        tree[edge[1]].append(edge[0])

    queue = deque([(0, 0)])
    furthest, max_distance = 0, 0
    while queue:
        node, distance = queue.popleft()
        if distance > max_distance:
            max_distance = distance
            furthest = node
        for neighbor in tree[node]:
            tree[neighbor].remove(node)
            queue.append((neighbor, distance + 1))

    queue.append((furthest, 0))
    max_distance = 0
    while queue:
        node, distance = queue.popleft()
        if distance > max_distance:
            max_distance = distance
        for neighbor in tree[node]:
            tree[neighbor].remove(node)
            queue.append((neighbor, distance + 1))

    return max_distance
```
To calculate the diameter of the tree, we can perform two breadth-first searches (BFS). First, we start a BFS from any arbitrary node (we can choose node 0) and find the furthest node in the tree. Then, we start another BFS from the furthest node found in the previous step and find its furthest node. The distance between these two nodes is the diameter of the tree.

1. Construct the tree from the given edges, storing each node's neighbors in a data structure (hashmap in C++ and Java, defaultdict in Python, and Map in JavaScript).

2. Perform the first BFS:
   - Initialize a queue with the starting node (0) and its distance (0).
   - Track the furthest node and its maximum distance from the starting node.
   - While the queue is not empty:
     - Dequeue the current node and its distance.
     - If the current distance is greater than the current maximum distance, update the furthest node and maximum distance.
     - For each neighbor of the current node:
       - Remove the edge between the current node and its neighbor.
       - Enqueue the neighbor and its distance from the current node (distance + 1).

3. Perform the second BFS (similar to the first BFS) from the furthest node found in the previous step. Calculate the new maximum distance, which is the diameter of the tree.

4. Return the diameter of the tree.

## A solution in Javascript

```javascript
/**
 * @param {number[][]} edges
 * @return {number}
 */
var treeDiameter = function(edges) {
    const tree = new Map();

    for (const 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 queue = [[0, 0]];
    let furthest = 0;
    let maxDistance = 0;

    while (queue.length > 0) {
        const [node, distance] = queue.shift();
        if (distance > maxDistance) {
            maxDistance = distance;
            furthest = node;
        }

        for (const neighbor of tree.get(node)) {
            tree.get(neighbor).splice(tree.get(neighbor).indexOf(node), 1);
            queue.push([neighbor, distance + 1]);
        }
    }

    queue.push([furthest, 0]);
    maxDistance = 0;

    while (queue.length > 0) {
        const [node, distance] = queue.shift();
        if (distance > maxDistance) {
            maxDistance = distance;
        }

        for (const neighbor of tree.get(node)) {
            tree.get(neighbor).splice(tree.get(neighbor).indexOf(node), 1);
            queue.push([neighbor, distance + 1]);
        }
    }

    return maxDistance;
};
```
To calculate the diameter of the tree, we can perform two breadth-first searches (BFS). First, we start a BFS from any arbitrary node (we can choose node 0) and find the furthest node in the tree. Then, we start another BFS from the furthest node found in the previous step and find its furthest node. The distance between these two nodes is the diameter of the tree.

1. Construct the tree from the given edges, storing each node's neighbors in a data structure (hashmap in C++ and Java, defaultdict in Python, and Map in JavaScript).

2. Perform the first BFS:
   - Initialize a queue with the starting node (0) and its distance (0).
   - Track the furthest node and its maximum distance from the starting node.
   - While the queue is not empty:
     - Dequeue the current node and its distance.
     - If the current distance is greater than the current maximum distance, update the furthest node and maximum distance.
     - For each neighbor of the current node:
       - Remove the edge between the current node and its neighbor.
       - Enqueue the neighbor and its distance from the current node (distance + 1).

3. Perform the second BFS (similar to the first BFS) from the furthest node found in the previous step. Calculate the new maximum distance, which is the diameter of the tree.

4. Return the diameter of the tree.


# Palindrome Removal

- slug: palindrome-removal
- difficulty: Hard

You are given an integer array `arr`.

In one move, you can select a **palindromic** subarray `arr[i], arr[i + 1], ..., arr[j]` where `i <= j`, and remove that subarray from the given array. Note that after removing a subarray, the elements on the left and on the right of that subarray move to fill the gap left by the removal.

Return _the minimum number of moves needed to remove all numbers from the array_.

**Example 1:**

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

**Example 2:**

**Input:** arr = \[1,3,4,1,5\]
**Output:** 3
**Explanation:** Remove \[4\] then remove \[1,3,1\] then remove \[5\].

**Constraints:**

*   `1 <= arr.length <= 100`
*   `1 <= arr[i] <= 20`

## A solution in Java

```java
public int minimumMoves(int[] arr) {
    int[][] dp = new int[arr.length][arr.length];
    for (int[] row : dp)
        Arrays.fill(row, -1);
    return minRemovals(arr, 0, arr.length - 1, dp);
}

private int minRemovals(int[] arr, int i, int j, int[][] dp) {
    if (i > j) return 0;
    if (i == j) return 1;
    if (dp[i][j] != -1) return dp[i][j];

    int ans = minRemovals(arr, i + 1, j, dp) + 1;
    for (int k = i + 1; k <= j; k++) {
        if (arr[i] == arr[k])
            ans = Math.min(ans, minRemovals(arr, i + 1, k - 1, dp) + minRemovals(arr, k + 1, j, dp));
    }
    return dp[i][j] = ans;
}
```
The algorithm uses a dynamic programming approach by storing results from subproblems in the `dp` array. This reduces the number of computations required. It uses a helper function `minRemovals` to recursively compute results for subproblems.

1. If `i` is greater than `j`, the subarray is empty, and no moves are needed, so return 0.
2. If `i` is equal to `j`, the subarray has one element, which is always a palindrome, so return 1.
3. If the current subarray has been solved before (i.e., `dp[i][j] != -1`), return the precomputed result.
4. Initialize a variable `ans` with the value of removing subarray[i] itself and finding the remaining moves for the rest of the subarray.
5. Loop through each element in the subarray and check for elements that are equal to the first element (arr[i]). For each matching element, find the moves using the helper function for the subarrays arr[i+1...k-1] and arr[k+1...j]. Update `ans` to the minimum of the current value of `ans` and the sum of moves found for the subarrays.
6. Save the result in the `dp` array and return `ans`.
7. Finally, call helper function with the initial subarray and return the result.

## A solution in C++

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

int dp[101][101];

bool isPalindrome(const vector<int>& arr, int i, int j) {
    while (i < j)
        if (arr[i++] != arr[j--]) return false;
    return true;
}

int minRemovals(vector<int>& arr, int i, int j) {
    if (i > j) return 0;
    if (i == j) return 1;
    if (dp[i][j] != -1) return dp[i][j];

    int ans = minRemovals(arr, i + 1, j) + 1;
    for (int k = i + 1; k <= j; k++)
        if (arr[i] == arr[k])
            ans = min(ans, minRemovals(arr, i + 1, k - 1) + minRemovals(arr, k + 1, j));
    return dp[i][j] = ans;
}

int minimumMoves(vector<int>& arr) {
    memset(dp, -1, sizeof(dp));
    return minRemovals(arr, 0, arr.size() - 1);
}
```
The algorithm uses a dynamic programming approach by storing results from subproblems in the `dp` array. This reduces the number of computations required. It uses a helper function `minRemovals` to recursively compute results for subproblems.

1. If `i` is greater than `j`, the subarray is empty, and no moves are needed, so return 0.
2. If `i` is equal to `j`, the subarray has one element, which is always a palindrome, so return 1.
3. If the current subarray has been solved before (i.e., `dp[i][j] != -1`), return the precomputed result.
4. Initialize a variable `ans` with the value of removing subarray[i] itself and finding the remaining moves for the rest of the subarray.
5. Loop through each element in the subarray and check for elements that are equal to the first element (arr[i]). For each matching element, find the moves using the helper function for the subarrays arr[i+1...k-1] and arr[k+1...j]. Update `ans` to the minimum of the current value of `ans` and the sum of moves found for the subarrays.
6. Save the result in the `dp` array and return `ans`.
7. Finally, call helper function with the initial subarray and return the result.

## A solution in Python

```python
def minimumMoves(arr):
    def minRemovals(i, j):
        if i > j:
            return 0
        if i == j:
            return 1
        if dp[i][j] != -1:
            return dp[i][j]

        ans = minRemovals(i + 1, j) + 1
        for k in range(i + 1, j + 1):
            if arr[i] == arr[k]:
                ans = min(ans, minRemovals(i + 1, k - 1) + minRemovals(k + 1, j))
        dp[i][j] = ans
        return ans

    dp = [[-1] * len(arr) for _ in range(len(arr))]
    return minRemovals(0, len(arr) - 1)
```
The algorithm uses a dynamic programming approach by storing results from subproblems in the `dp` array. This reduces the number of computations required. It uses a helper function `minRemovals` to recursively compute results for subproblems.

1. If `i` is greater than `j`, the subarray is empty, and no moves are needed, so return 0.
2. If `i` is equal to `j`, the subarray has one element, which is always a palindrome, so return 1.
3. If the current subarray has been solved before (i.e., `dp[i][j] != -1`), return the precomputed result.
4. Initialize a variable `ans` with the value of removing subarray[i] itself and finding the remaining moves for the rest of the subarray.
5. Loop through each element in the subarray and check for elements that are equal to the first element (arr[i]). For each matching element, find the moves using the helper function for the subarrays arr[i+1...k-1] and arr[k+1...j]. Update `ans` to the minimum of the current value of `ans` and the sum of moves found for the subarrays.
6. Save the result in the `dp` array and return `ans`.
7. Finally, call helper function with the initial subarray and return the result.

## A solution in Javascript

```javascript
var minimumMoves = function (arr) {
    let dp = [];
    for (let i = 0; i < arr.length; i++) {
        dp[i] = Array.from({ length: arr.length }, () => -1);
    }

    function minRemovals(i, j) {
        if (i > j) return 0;
        if (i == j) return 1;
        if (dp[i][j] != -1) return dp[i][j];

        let ans = minRemovals(i + 1, j) + 1;
        for (let k = i + 1; k <= j; k++) {
            if (arr[i] == arr[k])
                ans = Math.min(ans, minRemovals(i + 1, k - 1) + minRemovals(k + 1, j));
        }
        dp[i][j] = ans;
        return ans;
    }

    return minRemovals(0, arr.length - 1);
};
```
The algorithm uses a dynamic programming approach by storing results from subproblems in the `dp` array. This reduces the number of computations required. It uses a helper function `minRemovals` to recursively compute results for subproblems.

1. If `i` is greater than `j`, the subarray is empty, and no moves are needed, so return 0.
2. If `i` is equal to `j`, the subarray has one element, which is always a palindrome, so return 1.
3. If the current subarray has been solved before (i.e., `dp[i][j] != -1`), return the precomputed result.
4. Initialize a variable `ans` with the value of removing subarray[i] itself and finding the remaining moves for the rest of the subarray.
5. Loop through each element in the subarray and check for elements that are equal to the first element (arr[i]). For each matching element, find the moves using the helper function for the subarrays arr[i+1...k-1] and arr[k+1...j]. Update `ans` to the minimum of the current value of `ans` and the sum of moves found for the subarrays.
6. Save the result in the `dp` array and return `ans`.
7. Finally, call helper function with the initial subarray and return the result.


# Minimum Swaps to Make Strings Equal

- slug: minimum-swaps-to-make-strings-equal
- difficulty: Medium

You are given two strings `s1` and `s2` of equal length consisting of letters `"x "` and `"y "` **only**. Your task is to make these two strings equal to each other. You can swap any two characters that belong to **different** strings, which means: swap `s1[i]` and `s2[j]`.

Return the minimum number of swaps required to make `s1` and `s2` equal, or return `-1` if it is impossible to do so.

**Example 1:**

**Input:** s1 =  "xx ", s2 =  "yy "
**Output:** 1
**Explanation:** Swap s1\[0\] and s2\[1\], s1 =  "yx ", s2 =  "yx ".

**Example 2:**

**Input:** s1 =  "xy ", s2 =  "yx "
**Output:** 2
**Explanation:** Swap s1\[0\] and s2\[0\], s1 =  "yy ", s2 =  "xx ".
Swap s1\[0\] and s2\[1\], s1 =  "xy ", s2 =  "xy ".
Note that you cannot swap s1\[0\] and s1\[1\] to make s1 equal to  "yx ", cause we can only swap chars in different strings.

**Example 3:**

**Input:** s1 =  "xx ", s2 =  "xy "
**Output:** -1

**Constraints:**

*   `1 <= s1.length, s2.length <= 1000`
*   `s1.length == s2.length`
*   `s1, s2` only contain `'x'` or `'y'`.

## A solution in Java

```java
int movesToMakeZigzag(int[] nums) {
    int moves1 = 0, moves2 = 0;
    for (int i = 0; i < nums.length; i++) {
        int left = i > 0 ? nums[i - 1] : Integer.MAX_VALUE;
        int right = i + 1 < nums.length ? nums[i + 1] : Integer.MAX_VALUE;
        int diff1 = nums[i] - Math.min(left, right) + 1;
        int diff2 = nums[i] - Math.min(left, right) + 1;
        if (i % 2 == 0) {
            moves1 += Math.max(0, diff1);
        } else {
            moves2 += Math.max(0, diff2);
        }
    }
    return Math.min(moves1, moves2);
}
```
The algorithm iterates through the input array and calculates the number of moves required to create a zigzag pattern for both even and odd positions. At each position i, it calculates the minimum value between the left and right neighbors and then the difference between the current value and the minimum neighbor value. The difference is added to the total moves for even and odd positions depending on the index. Finally, the minimum of the total moves for both even and odd positions is returned as the result.

## A solution in C++

```cpp
int movesToMakeZigzag(std::vector<int>& nums) {
    int moves1 = 0, moves2 = 0;
    for (int i = 0; i < nums.size(); i++) {
        int left = i > 0 ? nums[i - 1] : INT_MAX;
        int right = i + 1 < nums.size() ? nums[i + 1] : INT_MAX;
        int diff1 = nums[i] - std::min(left, right) + 1;
        int diff2 = nums[i] - std::min(left, right) + 1;
        if (i % 2 == 0) {
            moves1 += std::max(0, diff1);
        } else {
            moves2 += std::max(0, diff2);
        }
    }
    return std::min(moves1, moves2);
}
```
The algorithm iterates through the input array and calculates the number of moves required to create a zigzag pattern for both even and odd positions. At each position i, it calculates the minimum value between the left and right neighbors and then the difference between the current value and the minimum neighbor value. The difference is added to the total moves for even and odd positions depending on the index. Finally, the minimum of the total moves for both even and odd positions is returned as the result.

## A solution in Python

```python
def moves_to_make_zigzag(nums):
    moves1, moves2 = 0, 0
    for i in range(len(nums)):
        left = nums[i - 1] if i > 0 else float('inf')
        right = nums[i + 1] if i + 1 < len(nums) else float('inf')
        diff1 = nums[i] - min(left, right) + 1
        diff2 = nums[i] - min(left, right) + 1
        if i % 2 == 0:
            moves1 += max(0, diff1)
        else:
            moves2 += max(0, diff2)
    return min(moves1, moves2)
```
The algorithm iterates through the input array and calculates the number of moves required to create a zigzag pattern for both even and odd positions. At each position i, it calculates the minimum value between the left and right neighbors and then the difference between the current value and the minimum neighbor value. The difference is added to the total moves for even and odd positions depending on the index. Finally, the minimum of the total moves for both even and odd positions is returned as the result.

## A solution in Javascript

```javascript
function movesToMakeZigzag(nums) {
    let moves1 = 0, moves2 = 0;
    for (let i = 0; i < nums.length; i++) {
        let left = i > 0 ? nums[i - 1] : Number.MAX_VALUE;
        let right = i + 1 < nums.length ? nums[i + 1] : Number.MAX_VALUE;
        let diff1 = nums[i] - Math.min(left, right) + 1;
        let diff2 = nums[i] - Math.min(left, right) + 1;
        if (i % 2 === 0) {
            moves1 += Math.max(0, diff1);
        } else {
            moves2 += Math.max(0, diff2);
        }
    }
    return Math.min(moves1, moves2);
}
```
The algorithm iterates through the input array and calculates the number of moves required to create a zigzag pattern for both even and odd positions. At each position i, it calculates the minimum value between the left and right neighbors and then the difference between the current value and the minimum neighbor value. The difference is added to the total moves for even and odd positions depending on the index. Finally, the minimum of the total moves for both even and odd positions is returned as the result.


# Count Number of Nice Subarrays

- slug: count-number-of-nice-subarrays
- difficulty: Medium

Given an array of integers `nums` and an integer `k`. A continuous subarray is called **nice** if there are `k` odd numbers on it.

Return _the number of **nice** sub-arrays_.

**Example 1:**

**Input:** nums = \[1,1,2,1,1\], k = 3
**Output:** 2
**Explanation:** The only sub-arrays with 3 odd numbers are \[1,1,2,1\] and \[1,2,1,1\].

**Example 2:**

**Input:** nums = \[2,4,6\], k = 1
**Output:** 0
**Explanation:** There is no odd numbers in the array.

**Example 3:**

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

**Constraints:**

*   `1 <= nums.length <= 50000`
*   `1 <= nums[i] <= 10^5`
*   `1 <= k <= nums.length`

## A solution in Java

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

public boolean canWin(TreeNode root, int x) {
    if (root == null) return false;
    if (root.val == x) {
        int leftNodes = 0, rightNodes = 0;
        if (root.left != null) leftNodes = 1 + canWin(root.left, x);
        if (root.right != null) rightNodes = 1 + canWin(root.right, x);
        return leftNodes % 2 != 0 || rightNodes % 2 != 0;
    }
    return canWin(root.left, x) || canWin(root.right, x);
}
```
The algorithm is implemented with a recursive `can_win` function which traverses the tree until it finds the node with the value x. Once the node with value x is found, the number of nodes in the left subtree and the right subtree is calculated. If either the left subtree nodes or the right subtree nodes is odd, then player 2 is guaranteed to win by choosing node y on the side with an odd number of nodes. Otherwise, the function returns false which means it's not possible for player 2 to ensure a win.

## A solution in C++

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

bool can_win(TreeNode* root, int x) {
    if (!root) return false;
    if (root->val == x) {
        int left_nodes = 0, right_nodes = 0;
        if (root->left) left_nodes = 1 + can_win(root->left, x);
        if (root->right) right_nodes = 1 + can_win(root->right, x);
        return left_nodes % 2 || right_nodes % 2;
    }
    return can_win(root->left, x) || can_win(root->right, x);
}
```
The algorithm is implemented with a recursive `can_win` function which traverses the tree until it finds the node with the value x. Once the node with value x is found, the number of nodes in the left subtree and the right subtree is calculated. If either the left subtree nodes or the right subtree nodes is odd, then player 2 is guaranteed to win by choosing node y on the side with an odd number of nodes. Otherwise, the function returns false which means it's not possible for player 2 to ensure a win.

## A solution in Python

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

def can_win(root, x):
    if not root:
        return False
    if root.val == x:
        left_nodes = 1 + can_win(root.left, x) if root.left else 0
        right_nodes = 1 + can_win(root.right, x) if root.right else 0
        return left_nodes % 2 != 0 or right_nodes % 2 != 0
    return can_win(root.left, x) or can_win(root.right, x)
```
The algorithm is implemented with a recursive `can_win` function which traverses the tree until it finds the node with the value x. Once the node with value x is found, the number of nodes in the left subtree and the right subtree is calculated. If either the left subtree nodes or the right subtree nodes is odd, then player 2 is guaranteed to win by choosing node y on the side with an odd number of nodes. Otherwise, the function returns false which means it's not possible for player 2 to ensure a win.

## A solution in Javascript

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

function canWin(root, x) {
    if (!root) return false;
    if (root.val === x) {
        let leftNodes = 0, rightNodes = 0;
        if (root.left) leftNodes = 1 + canWin(root.left, x);
        if (root.right) rightNodes = 1 + canWin(root.right, x);
        return leftNodes % 2 !== 0 || rightNodes % 2 !== 0;
    }
    return canWin(root.left, x) || canWin(root.right, x);
}
```
The algorithm is implemented with a recursive `can_win` function which traverses the tree until it finds the node with the value x. Once the node with value x is found, the number of nodes in the left subtree and the right subtree is calculated. If either the left subtree nodes or the right subtree nodes is odd, then player 2 is guaranteed to win by choosing node y on the side with an odd number of nodes. Otherwise, the function returns false which means it's not possible for player 2 to ensure a win.


# Check If It Is a Good Array

- slug: check-if-it-is-a-good-array
- difficulty: Hard

Given an array `nums` of positive integers. Your task is to select some subset of `nums`, multiply each element by an integer and add all these numbers. The array is said to be **good** if you can obtain a sum of `1` from the array by any possible subset and multiplicand.

Return `True` if the array is **good** otherwise return `False`.

**Example 1:**

**Input:** nums = \[12,5,7,23\]
**Output:** true
**Explanation:** Pick numbers 5 and 7.
5\*3 + 7\*(-2) = 1

**Example 2:**

**Input:** nums = \[29,6,10\]
**Output:** true
**Explanation:** Pick numbers 29, 6 and 10.
29\*1 + 6\*(-3) + 10\*(-1) = 1

**Example 3:**

**Input:** nums = \[3,6\]
**Output:** false

**Constraints:**

*   `1 <= nums.length <= 10^5`
*   `1 <= nums[i] <= 10^9`

## A solution in Java

```java
class Solution {
    public boolean isGoodArray(int[] nums) {
        int res = nums[0];
        for (int num : nums) {
            res = gcd(res, num);
        }
        return res == 1;
    }

    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}
```
The problem can be solved using the mathematical concept of Bézout's identity, which states that the greates common divisor (GCD) of two integers `a` and `b` can be represented in the form `ax + by = gcd(a, b)`. The array is said to be good if there exists a combination of elements which can be multiplied by an integer and added together to result in 1.

The solution involves iterating through the input array and finding the GCD of all the numbers. To find the GCD, we use the Euclidean algorithm. If the GCD is 1, then there exists a subset and multiplicand that satisfies the given condition, and the function returns true. Otherwise, the function returns false.

## A solution in C++

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

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

bool isGoodArray(vector<int>& nums) {
    int res = nums[0];
    for (int num : nums) {
        res = gcd(res, num);
    }
    return res == 1;
}
```
The problem can be solved using the mathematical concept of Bézout's identity, which states that the greates common divisor (GCD) of two integers `a` and `b` can be represented in the form `ax + by = gcd(a, b)`. The array is said to be good if there exists a combination of elements which can be multiplied by an integer and added together to result in 1.

The solution involves iterating through the input array and finding the GCD of all the numbers. To find the GCD, we use the Euclidean algorithm. If the GCD is 1, then there exists a subset and multiplicand that satisfies the given condition, and the function returns true. Otherwise, the function returns false.

## A solution in Python

```python
from math import gcd
from functools import reduce

def isGoodArray(nums):
    return reduce(gcd, nums) == 1
```
The problem can be solved using the mathematical concept of Bézout's identity, which states that the greates common divisor (GCD) of two integers `a` and `b` can be represented in the form `ax + by = gcd(a, b)`. The array is said to be good if there exists a combination of elements which can be multiplied by an integer and added together to result in 1.

The solution involves iterating through the input array and finding the GCD of all the numbers. To find the GCD, we use the Euclidean algorithm. If the GCD is 1, then there exists a subset and multiplicand that satisfies the given condition, and the function returns true. Otherwise, the function returns false.

## A solution in Javascript

```javascript
function gcd(a, b) {
    return b === 0 ? a : gcd(b, a % b);
}

function isGoodArray(nums) {
    let res = nums[0];
    for (let num of nums) {
        res = gcd(res, num);
    }
    return res === 1;
}
```
The problem can be solved using the mathematical concept of Bézout's identity, which states that the greates common divisor (GCD) of two integers `a` and `b` can be represented in the form `ax + by = gcd(a, b)`. The array is said to be good if there exists a combination of elements which can be multiplied by an integer and added together to result in 1.

The solution involves iterating through the input array and finding the GCD of all the numbers. To find the GCD, we use the Euclidean algorithm. If the GCD is 1, then there exists a subset and multiplicand that satisfies the given condition, and the function returns true. Otherwise, the function returns false.


# Cells with Odd Values in a Matrix

- slug: cells-with-odd-values-in-a-matrix
- difficulty: Easy

There is an `m x n` matrix that is initialized to all `0`'s. There is also a 2D array `indices` where each `indices[i] = [ri, ci]` represents a **0-indexed location** to perform some increment operations on the matrix.

For each location `indices[i]`, do **both** of the following:

1.  Increment **all** the cells on row `ri`.
2.  Increment **all** the cells on column `ci`.

Given `m`, `n`, and `indices`, return _the **number of odd-valued cells** in the matrix after applying the increment to all locations in_ `indices`.

**Example 1:**

**Input:** m = 2, n = 3, indices = \[\[0,1\],\[1,1\]\]
**Output:** 6
**Explanation:** Initial matrix = \[\[0,0,0\],\[0,0,0\]\].
After applying first increment it becomes \[\[1,2,1\],\[0,1,0\]\].
The final matrix is \[\[1,3,1\],\[1,3,1\]\], which contains 6 odd numbers.

**Example 2:**

**Input:** m = 2, n = 2, indices = \[\[1,1\],\[0,0\]\]
**Output:** 0
**Explanation:** Final matrix = \[\[2,2\],\[2,2\]\]. There are no odd numbers in the final matrix.

**Constraints:**

*   `1 <= m, n <= 50`
*   `1 <= indices.length <= 100`
*   `0 <= ri < m`
*   `0 <= ci < n`

**Follow up:** Could you solve this in `O(n + m + indices.length)` time with only `O(n + m)` extra space?

## A solution in Java

```java
public String breakPalindrome(String palindrome) {
    int n = palindrome.length();
    if (n < 2) return "";

    char[] arr = palindrome.toCharArray();
    for (int i = 0; i < n / 2; i++) {
        if (arr[i] != 'a') {
            arr[i] = 'a';
            return new String(arr);
        }
    }

    arr[n - 1] = 'b';
    return new String(arr);
}
```
The algorithm starts by checking if the length of the input string is less than 2, in which case it returns an empty string, as there is no way to make it non-palindrome with a single character replacement.

Then, it iterates over the characters of the string up to the middle position (length / 2). If it finds a character different from 'a', it replaces the character with 'a' to ensure lexicographically smallest result, and returns the modified string.

If the loop ends and all characters up to the middle are 'a's, then it replaces the last character of the string with 'b' and returns the modified string. This ensures that the string is no longer a palindrome, and retains the lexicographically smallest property.

## A solution in C++

```cpp
#include <string>

std::string breakPalindrome(std::string palindrome) {
    int n = palindrome.size();
    if (n < 2) return "";

    for (int i = 0; i < n / 2; i++) {
        if (palindrome[i] != 'a') {
            palindrome[i] = 'a';
            return palindrome;
        }
    }

    palindrome[n - 1] = 'b';
    return palindrome;
}
```
The algorithm starts by checking if the length of the input string is less than 2, in which case it returns an empty string, as there is no way to make it non-palindrome with a single character replacement.

Then, it iterates over the characters of the string up to the middle position (length / 2). If it finds a character different from 'a', it replaces the character with 'a' to ensure lexicographically smallest result, and returns the modified string.

If the loop ends and all characters up to the middle are 'a's, then it replaces the last character of the string with 'b' and returns the modified string. This ensures that the string is no longer a palindrome, and retains the lexicographically smallest property.

## A solution in Python

```python
def break_palindrome(palindrome: str) -> str:
    n = len(palindrome)
    if n < 2:
        return ""

    palindrome = list(palindrome)
    for i in range(n // 2):
        if palindrome[i] != 'a':
            palindrome[i] = 'a'
            return "".join(palindrome)

    palindrome[-1] = 'b'
    return "".join(palindrome)
```
The algorithm starts by checking if the length of the input string is less than 2, in which case it returns an empty string, as there is no way to make it non-palindrome with a single character replacement.

Then, it iterates over the characters of the string up to the middle position (length / 2). If it finds a character different from 'a', it replaces the character with 'a' to ensure lexicographically smallest result, and returns the modified string.

If the loop ends and all characters up to the middle are 'a's, then it replaces the last character of the string with 'b' and returns the modified string. This ensures that the string is no longer a palindrome, and retains the lexicographically smallest property.

## A solution in Javascript

```javascript
function breakPalindrome(palindrome) {
    const n = palindrome.length;
    if (n < 2) return "";

    let arr = palindrome.split("");
    for (let i = 0; i < Math.floor(n / 2); i++) {
        if (arr[i] !== 'a') {
            arr[i] = 'a';
            return arr.join("");
        }
    }

    arr[n - 1] = 'b';
    return arr.join("");
}
```
The algorithm starts by checking if the length of the input string is less than 2, in which case it returns an empty string, as there is no way to make it non-palindrome with a single character replacement.

Then, it iterates over the characters of the string up to the middle position (length / 2). If it finds a character different from 'a', it replaces the character with 'a' to ensure lexicographically smallest result, and returns the modified string.

If the loop ends and all characters up to the middle are 'a's, then it replaces the last character of the string with 'b' and returns the modified string. This ensures that the string is no longer a palindrome, and retains the lexicographically smallest property.


# Reconstruct a 2-Row Binary Matrix

- slug: reconstruct-a-2-row-binary-matrix
- difficulty: Medium

Given the following details of a matrix with `n` columns and `2` rows :

*   The matrix is a binary matrix, which means each element in the matrix can be `0` or `1`.
*   The sum of elements of the 0-th(upper) row is given as `upper`.
*   The sum of elements of the 1-st(lower) row is given as `lower`.
*   The sum of elements in the i-th column(0-indexed) is `colsum[i]`, where `colsum` is given as an integer array with length `n`.

Your task is to reconstruct the matrix with `upper`, `lower` and `colsum`.

Return it as a 2-D integer array.

If there are more than one valid solution, any of them will be accepted.

If no valid solution exists, return an empty 2-D array.

**Example 1:**

**Input:** upper = 2, lower = 1, colsum = \[1,1,1\]
**Output:** \[\[1,1,0\],\[0,0,1\]\]
**Explanation:** \[\[1,0,1\],\[0,1,0\]\], and \[\[0,1,1\],\[1,0,0\]\] are also correct answers.

**Example 2:**

**Input:** upper = 2, lower = 3, colsum = \[2,2,1,1\]
**Output:** \[\]

**Example 3:**

**Input:** upper = 5, lower = 5, colsum = \[2,1,2,0,1,0,1,2,0,1\]
**Output:** \[\[1,1,1,0,1,0,0,1,0,0\],\[1,0,1,0,0,0,1,1,0,1\]\]

**Constraints:**

*   `1 <= colsum.length <= 10^5`
*   `0 <= upper, lower <= colsum.length`
*   `0 <= colsum[i] <= 2`

## A solution in Java

```java
import java.util.*;

class Solution {
    public int[][] diagonalSort(int[][] mat) {
        int m = mat.length, n = mat[0].length;
        for (int i = 0; i < m; ++i) {
            PriorityQueue<Integer> pq = new PriorityQueue<>();
            int row = i, col = 0;
            while (row < m && col < n) {
                pq.offer(mat[row++][col++]);
            }
            row = i; col = 0;
            while (row < m && col < n) {
                mat[row++][col++] = pq.poll();
            }
        }
        for (int i = 1; i < n; ++i) {
            PriorityQueue<Integer> pq = new PriorityQueue<>();
            int row = 0, col = i;
            while (row < m && col < n) {
                pq.offer(mat[row++][col++]);
            }
            row = 0; col = i;
            while (row < m && col < n) {
                mat[row++][col++] = pq.poll();
            }
        }
        return mat;
    }
}
```
For each starting cells `(i, 0)` (top row) and `(0, j)` (left column), we first iterate through the cells that belong to its diagonal and push their values into a min heap (priority queue). This way, we have the values sorted in ascending order for each diagonal. After that, we iterate again over the same cells, popping from the priority queue and replacing the cell values with the sorted values. We do this process for all the diagonals.

## A solution in C++

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

using namespace std;

vector<vector<int>> diagonalSort(vector<vector<int>>& mat) {
    int m = mat.size(), n = mat[0].size();
    for (int i = 0; i < m; ++i) {
        priority_queue<int, vector<int>, greater<>> pq;
        int row = i, col = 0;
        while (row < m && col < n) {
            pq.push(mat[row++][col++]);
        }
        row = i, col = 0;
        while (row < m && col < n) {
            mat[row++][col++] = pq.top();
            pq.pop();
        }
    }
    for (int i = 1; i < n; ++i) {
        priority_queue<int, vector<int>, greater<>> pq;
        int row = 0, col = i;
        while (row < m && col < n) {
            pq.push(mat[row++][col++]);
        }
        row = 0, col = i;
        while (row < m && col < n) {
            mat[row++][col++] = pq.top();
            pq.pop();
        }
    }
    return mat;
}
```
For each starting cells `(i, 0)` (top row) and `(0, j)` (left column), we first iterate through the cells that belong to its diagonal and push their values into a min heap (priority queue). This way, we have the values sorted in ascending order for each diagonal. After that, we iterate again over the same cells, popping from the priority queue and replacing the cell values with the sorted values. We do this process for all the diagonals.

## A solution in Python

```python
from heapq import heappush, heappop

def diagonalSort(mat):
    m, n = len(mat), len(mat[0])
    for i in range(m):
        pq = []
        row, col = i, 0
        while row < m and col < n:
            heappush(pq, mat[row][col])
            row += 1
            col += 1
        row, col = i, 0
        while row < m and col < n:
            mat[row][col] = heappop(pq)
            row += 1
            col += 1

    for i in range(1, n):
        pq = []
        row, col = 0, i
        while row < m and col < n:
            heappush(pq, mat[row][col])
            row += 1
            col += 1
        row, col = 0, i
        while row < m and col < n:
            mat[row][col] = heappop(pq)
            row += 1
            col += 1
    return mat
```
For each starting cells `(i, 0)` (top row) and `(0, j)` (left column), we first iterate through the cells that belong to its diagonal and push their values into a min heap (priority queue). This way, we have the values sorted in ascending order for each diagonal. After that, we iterate again over the same cells, popping from the priority queue and replacing the cell values with the sorted values. We do this process for all the diagonals.

## A solution in Javascript

```javascript
function diagonalSort(mat) {
    const m = mat.length, n = mat[0].length;
    for (let i = 0; i < m; ++i) {
        let pq = [];
        let [row, col] = [i, 0];
        while (row < m && col < n) {
            pq.push(mat[row++][col++]);
        }
        pq.sort((a, b) => a - b);
        [row, col] = [i, 0];
        while (row < m && col < n) {
            mat[row++][col++] = pq.shift();
        }
    }
    for (let i = 1; i < n; ++i) {
        let pq = [];
        let [row, col] = [0, i];
        while (row < m && col < n) {
            pq.push(mat[row++][col++]);
        }
        pq.sort((a, b) => a - b);
        [row, col] = [0, i];
        while (row < m && col < n) {
            mat[row++][col++] = pq.shift();
        }
    }
    return mat;
}
```
For each starting cells `(i, 0)` (top row) and `(0, j)` (left column), we first iterate through the cells that belong to its diagonal and push their values into a min heap (priority queue). This way, we have the values sorted in ascending order for each diagonal. After that, we iterate again over the same cells, popping from the priority queue and replacing the cell values with the sorted values. We do this process for all the diagonals.