# Building Boxes

- slug: building-boxes
- difficulty: Hard

You have a cubic storeroom where the width, length, and height of the room are all equal to `n` units. You are asked to place `n` boxes in this room where each box is a cube of unit side length. There are however some rules to placing the boxes:

*   You can place the boxes anywhere on the floor.
*   If box `x` is placed on top of the box `y`, then each side of the four vertical sides of the box `y` **must** either be adjacent to another box or to a wall.

Given an integer `n`, return _the **minimum** possible number of boxes touching the floor._

**Example 1:**

**Input:** n = 3
**Output:** 3
**Explanation:** The figure above is for the placement of the three boxes.
These boxes are placed in the corner of the room, where the corner is on the left side.

**Example 2:**

**Input:** n = 4
**Output:** 3
**Explanation:** The figure above is for the placement of the four boxes.
These boxes are placed in the corner of the room, where the corner is on the left side.

**Example 3:**

**Input:** n = 10
**Output:** 6
**Explanation:** The figure above is for the placement of the ten boxes.
These boxes are placed in the corner of the room, where the corner is on the back side.

**Constraints:**

*   `1 <= n <= 109`

## A solution in Java

```java
public class Solution {
    public boolean checkPalindromeFormation(String a, String b) {
        for (int i = 0, j = a.length() - 1; i < j; ++i, --j) {
            if (a.charAt(i) != b.charAt(j))
                return isPalindrome(a, i, j) || isPalindrome(b, i, j);
        }
        return true;
    }

    private boolean isPalindrome(String s, int left, int right) {
        while (left < right) {
            if (s.charAt(left++) != s.charAt(right--)) return false;
        }
        return true;
    }
}
```
The algorithm works by iterating through the two strings a and b from both ends (i starts at 0, and j starts at the end). The loop condition is `i < j`, which means it will iterate approximately half of the string length.

Inside the loop, we check if `a[i]` is not equal to `b[j]`. If they are not equal, we split the string a and b at the current index i and check if they form a palindrome. The function `isPalindrome` is used to check if a string is a palindrome, which takes a string and two pointers (left and right). It iterates through the string from left to right and checks if the characters are equal. If they are not, the function returns false (not a palindrome), otherwise it continues till left >= right, and returns true (palindrome).

To check if the concatenated strings (aprefix + bsuffix or bprefix + asuffix) form a palindrome, we call the `isPalindrome` function with the required parameters. If either of the concatenated strings provide a palindrome, the function returns true.

After the loop has ended, if no palindrome combination has been found, the function returns false. Otherwise, it returns true.

## A solution in C++

```cpp
#include <string>

bool checkPalindromeFormation(std::string a, std::string b) {
    auto isPalindrome = [](const std::string& s, int left, int right) {
        while (left < right) {
            if (s[left++] != s[right--]) return false;
        }
        return true;
    };

    for (int i = 0, j = a.size() - 1; i < j; ++i, --j) {
        if (a[i] != b[j]) return isPalindrome(a, i, j) || isPalindrome(b, i, j);
    }
    return true;
}
```
The algorithm works by iterating through the two strings a and b from both ends (i starts at 0, and j starts at the end). The loop condition is `i < j`, which means it will iterate approximately half of the string length.

Inside the loop, we check if `a[i]` is not equal to `b[j]`. If they are not equal, we split the string a and b at the current index i and check if they form a palindrome. The function `isPalindrome` is used to check if a string is a palindrome, which takes a string and two pointers (left and right). It iterates through the string from left to right and checks if the characters are equal. If they are not, the function returns false (not a palindrome), otherwise it continues till left >= right, and returns true (palindrome).

To check if the concatenated strings (aprefix + bsuffix or bprefix + asuffix) form a palindrome, we call the `isPalindrome` function with the required parameters. If either of the concatenated strings provide a palindrome, the function returns true.

After the loop has ended, if no palindrome combination has been found, the function returns false. Otherwise, it returns true.

## A solution in Python

```python
def check_palindrome_formation(a: str, b: str) -> bool:
    def is_palindrome(s: str, left: int, right: int) -> bool:
        while left < right:
            if s[left] != s[right]:
                return False
            left += 1
            right -= 1
        return True

    i, j = 0, len(a) - 1
    while i < j:
        if a[i] != b[j]:
            return is_palindrome(a, i, j) or is_palindrome(b, i, j)
        i += 1
        j -= 1
    return True
```
The algorithm works by iterating through the two strings a and b from both ends (i starts at 0, and j starts at the end). The loop condition is `i < j`, which means it will iterate approximately half of the string length.

Inside the loop, we check if `a[i]` is not equal to `b[j]`. If they are not equal, we split the string a and b at the current index i and check if they form a palindrome. The function `isPalindrome` is used to check if a string is a palindrome, which takes a string and two pointers (left and right). It iterates through the string from left to right and checks if the characters are equal. If they are not, the function returns false (not a palindrome), otherwise it continues till left >= right, and returns true (palindrome).

To check if the concatenated strings (aprefix + bsuffix or bprefix + asuffix) form a palindrome, we call the `isPalindrome` function with the required parameters. If either of the concatenated strings provide a palindrome, the function returns true.

After the loop has ended, if no palindrome combination has been found, the function returns false. Otherwise, it returns true.

## A solution in Javascript

```javascript
function checkPalindromeFormation(a, b) {
    function isPalindrome(s, left, right) {
        while (left < right) {
            if (s.charAt(left++) !== s.charAt(right--)) return false;
        }
        return true;
    }

    for (let i = 0, j = a.length - 1; i < j; ++i, --j) {
        if (a.charAt(i) !== b.charAt(j))
            return isPalindrome(a, i, j) || isPalindrome(b, i, j);
    }
    return true;
}
```
The algorithm works by iterating through the two strings a and b from both ends (i starts at 0, and j starts at the end). The loop condition is `i < j`, which means it will iterate approximately half of the string length.

Inside the loop, we check if `a[i]` is not equal to `b[j]`. If they are not equal, we split the string a and b at the current index i and check if they form a palindrome. The function `isPalindrome` is used to check if a string is a palindrome, which takes a string and two pointers (left and right). It iterates through the string from left to right and checks if the characters are equal. If they are not, the function returns false (not a palindrome), otherwise it continues till left >= right, and returns true (palindrome).

To check if the concatenated strings (aprefix + bsuffix or bprefix + asuffix) form a palindrome, we call the `isPalindrome` function with the required parameters. If either of the concatenated strings provide a palindrome, the function returns true.

After the loop has ended, if no palindrome combination has been found, the function returns false. Otherwise, it returns true.


# Find Distance in a Binary Tree

- slug: find-distance-in-a-binary-tree
- difficulty: Medium

Given the root of a binary tree and two integers `p` and `q`, return _the **distance** between the nodes of value_ `p` _and value_ `q` _in the tree_.

The **distance** between two nodes is the number of edges on the path from one to the other.

**Example 1:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], p = 5, q = 0
**Output:** 3
**Explanation:** There are 3 edges between 5 and 0: 5-3-1-0.

**Example 2:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], p = 5, q = 7
**Output:** 2
**Explanation:** There are 2 edges between 5 and 7: 5-2-7.

**Example 3:**

**Input:** root = \[3,5,1,6,2,0,8,null,null,7,4\], p = 5, q = 5
**Output:** 0
**Explanation:** The distance between a node and itself is 0.

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 104]`.
*   `0 <= Node.val <= 109`
*   All `Node.val` are **unique**.
*   `p` and `q` are values in the tree.

## A solution in Java

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

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

    int[] ans = new int[n - 1];
    for (int i = 1; i <= n; i++) {
        int maxD = dfs(tree, i, 0);
        if (maxD > 0) ans[maxD - 1]++;
    }
    return ans;
}

private int dfs(List<List<Integer>> tree, int node, int parent) {
    int depth = 0;
    for (int child : tree.get(node)) {
        if (child != parent) depth = Math.max(depth, 1 + dfs(tree, child, node));
    }
    return depth;
}
```
1. Convert the given edges into a tree data structure (an adjacency list).
2. Write a recursive depth-first search (dfs) function that returns the maximum depth of a given node from its children, excluding the parent.
3. Loop through each city from 1 to n and call the dfs function with the city as the starting node and 0 as the parent. Calculate the maximum distance (maxD) for each city.
4. Increment the count in the ans array for the index of maxD - 1.
5. The ans array now contains the count of subtrees for each distance d.

(Note: This solution counts each subtree twice, but it doesn't affect the final result, as every subtree is counted twice, which cancels out the multiplicity.)

## A solution in C++

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

vector<int> countSubgraphsForEachD(int n, vector<pair<int, int>>& edges) {
    vector<vector<int>> tree(n + 1);
    for (auto &edge : edges) {
        tree[edge.first].push_back(edge.second);
        tree[edge.second].push_back(edge.first);
    }

    function<int(int, int)> dfs = [&](int node, int parent) {
        int depth = 0;
        for (int child : tree[node]) {
            if (child != parent) depth = max(depth, 1 + dfs(child, node));
        }
        return depth;
    };

    vector<int> ans(n - 1);
    for (int i = 1; i <= n; ++i) {
        int maxD = dfs(i, 0);
        if (maxD > 0) ans[maxD - 1]++;
    }
    return ans;
}
```
1. Convert the given edges into a tree data structure (an adjacency list).
2. Write a recursive depth-first search (dfs) function that returns the maximum depth of a given node from its children, excluding the parent.
3. Loop through each city from 1 to n and call the dfs function with the city as the starting node and 0 as the parent. Calculate the maximum distance (maxD) for each city.
4. Increment the count in the ans array for the index of maxD - 1.
5. The ans array now contains the count of subtrees for each distance d.

(Note: This solution counts each subtree twice, but it doesn't affect the final result, as every subtree is counted twice, which cancels out the multiplicity.)

## A solution in Python

```python
from collections import defaultdict

def countSubgraphsForEachD(n, edges):
    tree = defaultdict(list)
    for u, v in edges:
        tree[u].append(v)
        tree[v].append(u)

    def dfs(node, parent):
        depth = 0
        for child in tree[node]:
            if child != parent:
                depth = max(depth, 1 + dfs(child, node))
        return depth

    ans = [0] * (n - 1)
    for i in range(1, n + 1):
        maxD = dfs(i, 0)
        if maxD > 0:
            ans[maxD - 1] += 1

    return ans
```
1. Convert the given edges into a tree data structure (an adjacency list).
2. Write a recursive depth-first search (dfs) function that returns the maximum depth of a given node from its children, excluding the parent.
3. Loop through each city from 1 to n and call the dfs function with the city as the starting node and 0 as the parent. Calculate the maximum distance (maxD) for each city.
4. Increment the count in the ans array for the index of maxD - 1.
5. The ans array now contains the count of subtrees for each distance d.

(Note: This solution counts each subtree twice, but it doesn't affect the final result, as every subtree is counted twice, which cancels out the multiplicity.)

## A solution in Javascript

```javascript
function countSubgraphsForEachD(n, edges) {
    const tree = Array.from({ length: n + 1 }, () => []);
    for (const [u, v] of edges) {
        tree[u].push(v);
        tree[v].push(u);
    }

    function dfs(node, parent) {
        let depth = 0;
        for (const child of tree[node]) {
            if (child !== parent) depth = Math.max(depth, 1 + dfs(child, node));
        }
        return depth;
    }

    const ans = new Array(n - 1).fill(0);
    for (let i = 1; i <= n; i++) {
        const maxD = dfs(i, 0);
        if (maxD > 0) ans[maxD - 1]++;
    }
    return ans;
}
```
1. Convert the given edges into a tree data structure (an adjacency list).
2. Write a recursive depth-first search (dfs) function that returns the maximum depth of a given node from its children, excluding the parent.
3. Loop through each city from 1 to n and call the dfs function with the city as the starting node and 0 as the parent. Calculate the maximum distance (maxD) for each city.
4. Increment the count in the ans array for the index of maxD - 1.
5. The ans array now contains the count of subtrees for each distance d.

(Note: This solution counts each subtree twice, but it doesn't affect the final result, as every subtree is counted twice, which cancels out the multiplicity.)


# Maximum Number of Balls in a Box

- slug: maximum-number-of-balls-in-a-box
- difficulty: Easy

You are working in a ball factory where you have `n` balls numbered from `lowLimit` up to `highLimit` **inclusive** (i.e., `n == highLimit - lowLimit + 1`), and an infinite number of boxes numbered from `1` to `infinity`.

Your job at this factory is to put each ball in the box with a number equal to the sum of digits of the ball's number. For example, the ball number `321` will be put in the box number `3 + 2 + 1 = 6` and the ball number `10` will be put in the box number `1 + 0 = 1`.

Given two integers `lowLimit` and `highLimit`, return _the number of balls in the box with the most balls._

**Example 1:**

**Input:** lowLimit = 1, highLimit = 10
**Output:** 2
**Explanation:**
Box Number:  1 2 3 4 5 6 7 8 9 10 11 ...
Ball Count:  2 1 1 1 1 1 1 1 1 0  0  ...
Box 1 has the most number of balls with 2 balls.

**Example 2:**

**Input:** lowLimit = 5, highLimit = 15
**Output:** 2
**Explanation:**
Box Number:  1 2 3 4 5 6 7 8 9 10 11 ...
Ball Count:  1 1 1 1 2 2 1 1 1 0  0  ...
Boxes 5 and 6 have the most number of balls with 2 balls in each.

**Example 3:**

**Input:** lowLimit = 19, highLimit = 28
**Output:** 2
**Explanation:**
Box Number:  1 2 3 4 5 6 7 8 9 10 11 12 ...
Ball Count:  0 1 1 1 1 1 1 1 1 2  0  0  ...
Box 10 has the most number of balls with 2 balls.

**Constraints:**

*   `1 <= lowLimit <= highLimit <= 105`

## A solution in Java

```java
import java.util.*;

public int maxWidthOfVerticalArea(int[][] points) {
    List<Integer> xs = new ArrayList<>();
    for (int[] point : points) {
        xs.add(point[0]);
    }
    Collections.sort(xs);

    int max_width = 0;
    for (int i = 1; i < xs.size(); i++) {
        max_width = Math.max(max_width, xs.get(i) - xs.get(i - 1));
    }

    return max_width;
}
```
1. Obtain all the x-coordinates from the given points, and store them in a new list (`xs`).
2. Sort the x-coordinates in ascending order.
3. Initialize the maximum width (`max_width`) to be 0.
4. Iterate through the sorted x coordinates:
   - For each consecutive pair of x-coordinates, calculate their difference.
   - Update the `max_width` with the maximum value between the current `max_width` and the difference.
5. Return the `max_width`.

## A solution in C++

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

int maxWidthOfVerticalArea(std::vector<std::vector<int>>& points) {
    std::vector<int> xs;
    for (const auto& point : points) {
        xs.push_back(point[0]);
    }
    std::sort(xs.begin(), xs.end());

    int max_width = 0;
    for (size_t i = 1; i < xs.size(); ++i) {
        max_width = std::max(max_width, xs[i] - xs[i - 1]);
    }

    return max_width;
}
```
1. Obtain all the x-coordinates from the given points, and store them in a new list (`xs`).
2. Sort the x-coordinates in ascending order.
3. Initialize the maximum width (`max_width`) to be 0.
4. Iterate through the sorted x coordinates:
   - For each consecutive pair of x-coordinates, calculate their difference.
   - Update the `max_width` with the maximum value between the current `max_width` and the difference.
5. Return the `max_width`.

## A solution in Python

```python
def maxWidthOfVerticalArea(points):
    xs = sorted([point[0] for point in points])
    max_width = 0
    for i in range(1, len(xs)):
        max_width = max(max_width, xs[i] - xs[i - 1])
    return max_width
```
1. Obtain all the x-coordinates from the given points, and store them in a new list (`xs`).
2. Sort the x-coordinates in ascending order.
3. Initialize the maximum width (`max_width`) to be 0.
4. Iterate through the sorted x coordinates:
   - For each consecutive pair of x-coordinates, calculate their difference.
   - Update the `max_width` with the maximum value between the current `max_width` and the difference.
5. Return the `max_width`.

## A solution in Javascript

```javascript
function maxWidthOfVerticalArea(points) {
    const xs = points.map(point => point[0]).sort((a, b) => a - b);
    let max_width = 0;
    for (let i = 1; i < xs.length; i++) {
        max_width = Math.max(max_width, xs[i] - xs[i - 1]);
    }
    return max_width;
}
```
1. Obtain all the x-coordinates from the given points, and store them in a new list (`xs`).
2. Sort the x-coordinates in ascending order.
3. Initialize the maximum width (`max_width`) to be 0.
4. Iterate through the sorted x coordinates:
   - For each consecutive pair of x-coordinates, calculate their difference.
   - Update the `max_width` with the maximum value between the current `max_width` and the difference.
5. Return the `max_width`.


# Restore the Array From Adjacent Pairs

- slug: restore-the-array-from-adjacent-pairs
- difficulty: Medium

There is an integer array `nums` that consists of `n` **unique** elements, but you have forgotten it. However, you do remember every pair of adjacent elements in `nums`.

You are given a 2D integer array `adjacentPairs` of size `n - 1` where each `adjacentPairs[i] = [ui, vi]` indicates that the elements `ui` and `vi` are adjacent in `nums`.

It is guaranteed that every adjacent pair of elements `nums[i]` and `nums[i+1]` will exist in `adjacentPairs`, either as `[nums[i], nums[i+1]]` or `[nums[i+1], nums[i]]`. The pairs can appear **in any order**.

Return _the original array_ `nums`_. If there are multiple solutions, return **any of them**_.

**Example 1:**

**Input:** adjacentPairs = \[\[2,1\],\[3,4\],\[3,2\]\]
**Output:** \[1,2,3,4\]
**Explanation:** This array has all its adjacent pairs in adjacentPairs.
Notice that adjacentPairs\[i\] may not be in left-to-right order.

**Example 2:**

**Input:** adjacentPairs = \[\[4,-2\],\[1,4\],\[-3,1\]\]
**Output:** \[-2,4,1,-3\]
**Explanation:** There can be negative numbers.
Another solution is \[-3,1,4,-2\], which would also be accepted.

**Example 3:**

**Input:** adjacentPairs = \[\[100000,-100000\]\]
**Output:** \[100000,-100000\]

**Constraints:**

*   `nums.length == n`
*   `adjacentPairs.length == n - 1`
*   `adjacentPairs[i].length == 2`
*   `2 <= n <= 105`
*   `-105 <= nums[i], ui, vi <= 105`
*   There exists some `nums` that has `adjacentPairs` as its pairs.

## A solution in Java

```java
int countSubstringsWithOneDifference(String s, String t) {
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        for (int j = 0; j < t.length(); j++) {
            int differences = 0;
            for (int k = 0; i + k < s.length() && j + k < t.length(); k++) {
                if (s.charAt(i + k) != t.charAt(j + k)) {
                    differences++;
                }
                if (differences == 2) {
                    break;
                }
                if (differences == 1) {
                    count++;
                }
            }
        }
    }
    return count;
}
```
The algorithm iterates through all the possible substrings of the given strings s and t. In each iteration, it keeps track of the number of differences between the substrings. If the number of differences becomes 2, it breaks the inner loop since we are only interested in substrings that differ by exactly one character. If the number of differences is 1, it increments the count, which is the final result. The time complexity of the algorithm is O(n^3), where n is the length of the strings.

## A solution in C++

```cpp
int countSubstringsWithOneDifference(const std::string& s, const std::string& t) {
    int count = 0;
    for (int i = 0; i < s.size(); i++) {
        for (int j = 0; j < t.size(); j++) {
            int differences = 0;
            for (int k = 0; i + k < s.size() && j + k < t.size(); k++) {
                if (s[i + k] != t[j + k]) {
                    differences++;
                }
                if (differences == 2) {
                    break;
                }
                if (differences == 1) {
                    count++;
                }
            }
        }
    }
    return count;
}
```
The algorithm iterates through all the possible substrings of the given strings s and t. In each iteration, it keeps track of the number of differences between the substrings. If the number of differences becomes 2, it breaks the inner loop since we are only interested in substrings that differ by exactly one character. If the number of differences is 1, it increments the count, which is the final result. The time complexity of the algorithm is O(n^3), where n is the length of the strings.

## A solution in Python

```python
def count_substrings_with_one_difference(s, t):
    count = 0
    for i in range(len(s)):
        for j in range(len(t)):
            differences = 0
            k = 0
            while i + k < len(s) and j + k < len(t):
                if s[i + k] != t[j + k]:
                    differences += 1
                if differences == 2:
                    break
                if differences == 1:
                    count += 1
                k += 1
    return count
```
The algorithm iterates through all the possible substrings of the given strings s and t. In each iteration, it keeps track of the number of differences between the substrings. If the number of differences becomes 2, it breaks the inner loop since we are only interested in substrings that differ by exactly one character. If the number of differences is 1, it increments the count, which is the final result. The time complexity of the algorithm is O(n^3), where n is the length of the strings.

## A solution in Javascript

```javascript
function countSubstringsWithOneDifference(s, t) {
    let count = 0;
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < t.length; j++) {
            let differences = 0;
            for (let k = 0; i + k < s.length && j + k < t.length; k++) {
                if (s[i + k] !== t[j + k]) {
                    differences++;
                }
                if (differences === 2) {
                    break;
                }
                if (differences === 1) {
                    count++;
                }
            }
        }
    }
    return count;
}
```
The algorithm iterates through all the possible substrings of the given strings s and t. In each iteration, it keeps track of the number of differences between the substrings. If the number of differences becomes 2, it breaks the inner loop since we are only interested in substrings that differ by exactly one character. If the number of differences is 1, it increments the count, which is the final result. The time complexity of the algorithm is O(n^3), where n is the length of the strings.


# Can You Eat Your Favorite Candy on Your Favorite Day?

- slug: can-you-eat-your-favorite-candy-on-your-favorite-day
- difficulty: Medium

You are given a **(0-indexed)** array of positive integers `candiesCount` where `candiesCount[i]` represents the number of candies of the `ith` type you have. You are also given a 2D array `queries` where `queries[i] = [favoriteTypei, favoriteDayi, dailyCapi]`.

You play a game with the following rules:

*   You start eating candies on day `**0**`.
*   You **cannot** eat **any** candy of type `i` unless you have eaten **all** candies of type `i - 1`.
*   You must eat **at least** **one** candy per day until you have eaten all the candies.

Construct a boolean array `answer` such that `answer.length == queries.length` and `answer[i]` is `true` if you can eat a candy of type `favoriteTypei` on day `favoriteDayi` without eating **more than** `dailyCapi` candies on **any** day, and `false` otherwise. Note that you can eat different types of candy on the same day, provided that you follow rule 2.

Return _the constructed array_ `answer`.

**Example 1:**

**Input:** candiesCount = \[7,4,5,3,8\], queries = \[\[0,2,2\],\[4,2,4\],\[2,13,1000000000\]\]
**Output:** \[true,false,true\]
**Explanation:**
1- If you eat 2 candies (type 0) on day 0 and 2 candies (type 0) on day 1, you will eat a candy of type 0 on day 2.
2- You can eat at most 4 candies each day.
   If you eat 4 candies every day, you will eat 4 candies (type 0) on day 0 and 4 candies (type 0 and type 1) on day 1.
   On day 2, you can only eat 4 candies (type 1 and type 2), so you cannot eat a candy of type 4 on day 2.
3- If you eat 1 candy each day, you will eat a candy of type 2 on day 13.

**Example 2:**

**Input:** candiesCount = \[5,2,6,4,1\], queries = \[\[3,1,2\],\[4,10,3\],\[3,10,100\],\[4,100,30\],\[1,3,1\]\]
**Output:** \[false,true,true,false,false\]

**Constraints:**

*   `1 <= candiesCount.length <= 105`
*   `1 <= candiesCount[i] <= 105`
*   `1 <= queries.length <= 105`
*   `queries[i].length == 3`
*   `0 <= favoriteTypei < candiesCount.length`
*   `0 <= favoriteDayi <= 109`
*   `1 <= dailyCapi <= 109`

## A solution in Java

```java
import java.util.*;

public int numWays(List<String> words, String target) {
    int n = words.size(), m = target.length();
    int MOD = 1000000007;
    int[] cnt = new int[26];
    for (String word : words) {
        for (char ch : word.toCharArray()) {
            cnt[ch - 'a']++;
        }
    }
    long[] dp = new long[m + 1];
    dp[0] = 1;
    for (char ch : target.toCharArray()) {
        for (int i = m - 1; i >= 0; i--) {
            dp[i + 1] += dp[i] * cnt[ch - 'a'];
            dp[i + 1] %= MOD;
        }
    }
    return (int)dp[m];
}
```
First, we count the frequency of each character in the given words and store it in an array `cnt`. Then, we use dynamic programming. Initialize a `dp` array of size m+1 (where m is the length of the target string) and set `dp[0] = 1`.

Iterate through all characters in the target string, and for each character, iterate through the `dp` array in reverse order from m-1 to 0. Update `dp[i+1]` as: `dp[i+1] += dp[i] * cnt[ch - 'a']`, taking the modulo 1e9+7 at every step.

In the end, return `dp[m]` which contains the number of ways to form the target from the given words.

## A solution in C++

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

const int MOD = 1e9 + 7;

int numWays(std::vector<std::string>& words, std::string& target) {
    int n = words.size(), m = target.size();
    std::vector<int> cnt(26);
    for (const std::string& word : words) {
        for (char ch : word) {
            cnt[ch - 'a']++;
        }
    }
    std::vector<long long> dp(m + 1);
    dp[0] = 1;
    for (char ch : target) {
        for (int i = m - 1; i >= 0; i--) {
            dp[i + 1] += dp[i] * cnt[ch - 'a'];
            dp[i + 1] %= MOD;
        }
    }
    return dp[m];
}
```
First, we count the frequency of each character in the given words and store it in an array `cnt`. Then, we use dynamic programming. Initialize a `dp` array of size m+1 (where m is the length of the target string) and set `dp[0] = 1`.

Iterate through all characters in the target string, and for each character, iterate through the `dp` array in reverse order from m-1 to 0. Update `dp[i+1]` as: `dp[i+1] += dp[i] * cnt[ch - 'a']`, taking the modulo 1e9+7 at every step.

In the end, return `dp[m]` which contains the number of ways to form the target from the given words.

## A solution in Python

```python
def num_ways(words, target):
    n, m = len(words), len(target)
    MOD = 10**9 + 7
    cnt = [0] * 26
    for word in words:
        for ch in word:
            cnt[ord(ch) - ord('a')] += 1
    dp = [0] * (m + 1)
    dp[0] = 1
    for ch in target:
        for i in range(m - 1, -1, -1):
            dp[i + 1] += dp[i] * cnt[ord(ch) - ord('a')]
            dp[i + 1] %= MOD
    return dp[m]
```
First, we count the frequency of each character in the given words and store it in an array `cnt`. Then, we use dynamic programming. Initialize a `dp` array of size m+1 (where m is the length of the target string) and set `dp[0] = 1`.

Iterate through all characters in the target string, and for each character, iterate through the `dp` array in reverse order from m-1 to 0. Update `dp[i+1]` as: `dp[i+1] += dp[i] * cnt[ch - 'a']`, taking the modulo 1e9+7 at every step.

In the end, return `dp[m]` which contains the number of ways to form the target from the given words.

## A solution in Javascript

```javascript
function numWays(words, target) {
    let n = words.length, m = target.length;
    const MOD = 1e9 + 7;
    let cnt = Array(26).fill(0);
    for (let word of words) {
        for (let ch of word) {
            cnt[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
        }
    }
    let dp = Array(m + 1).fill(0);
    dp[0] = 1;
    for (let ch of target) {
        for (let i = m - 1; i >= 0; i--) {
            dp[i + 1] += dp[i] * cnt[ch.charCodeAt(0) - 'a'.charCodeAt(0)];
            dp[i + 1] %= MOD;
        }
    }
    return dp[m];
}
```
First, we count the frequency of each character in the given words and store it in an array `cnt`. Then, we use dynamic programming. Initialize a `dp` array of size m+1 (where m is the length of the target string) and set `dp[0] = 1`.

Iterate through all characters in the target string, and for each character, iterate through the `dp` array in reverse order from m-1 to 0. Update `dp[i+1]` as: `dp[i+1] += dp[i] * cnt[ch - 'a']`, taking the modulo 1e9+7 at every step.

In the end, return `dp[m]` which contains the number of ways to form the target from the given words.


# Palindrome Partitioning IV

- slug: palindrome-partitioning-iv
- difficulty: Hard

Given a string `s`, return `true` _if it is possible to split the string_ `s` _into three **non-empty** palindromic substrings. Otherwise, return_ `false`.

A string is said to be palindrome if it the same string when reversed.

**Example 1:**

**Input:** s =  "abcbdd "
**Output:** true
**Explanation: ** "abcbdd " =  "a " +  "bcb " +  "dd ", and all three substrings are palindromes.

**Example 2:**

**Input:** s =  "bcbddxy "
**Output:** false
**Explanation:** s cannot be split into 3 palindromes.

**Constraints:**

*   `3 <= s.length <= 2000`
*   `s` consists only of lowercase English letters.

## A solution in Java

```java
public class Solution {
    private boolean isPalindrome(String s, int start, int end) {
        while (start < end) {
            if (s.charAt(start) != s.charAt(end)) return false;
            start++;
            end--;
        }
        return true;
    }

    public boolean checkPartitioning(String s) {
        int n = s.length();
        for (int i = 0; i < n - 2; ++i) {
            if (isPalindrome(s, 0, i)) {
                for (int j = i + 1; j < n - 1; ++j) {
                    if (isPalindrome(s, i + 1, j) && isPalindrome(s, j + 1, n - 1)) return true;
                }
            }
        }
        return false;
    }
}
```
The algorithm creates a helper function `isPalindrome` to check if a given substring is a palindrome based on start and end indices. Then, in the main function `checkPartitioning`, it iterates through the string to find a possible split that gives three non-empty palindromic substrings. In the outer loop, it goes from 0 to `n - 3` and checks if the substring from 0 to `i` is palindrome. In the inner loop, it goes from `i + 1` to `n - 2` and checks if the substring from `i + 1` to `j` and from `j + 1` to `n-1` are both palindromes. If such a split is found, it returns true. If all possible splits are checked and no palindromic split is found, the function returns false.

## A solution in C++

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

bool isPalindrome(const string& s, int start, int end) {
    while (start < end) {
        if (s[start] != s[end]) return false;
        start++;
        end--;
    }
    return true;
}

bool checkPartitioning(const string& s) {
    int n = s.length();
    for (int i = 0; i < n - 2; ++i) {
        if (isPalindrome(s, 0, i)) {
            for (int j = i + 1; j < n - 1; ++j) {
                if (isPalindrome(s, i + 1, j) && isPalindrome(s, j + 1, n - 1)) return true;
            }
        }
    }
    return false;
}
```
The algorithm creates a helper function `isPalindrome` to check if a given substring is a palindrome based on start and end indices. Then, in the main function `checkPartitioning`, it iterates through the string to find a possible split that gives three non-empty palindromic substrings. In the outer loop, it goes from 0 to `n - 3` and checks if the substring from 0 to `i` is palindrome. In the inner loop, it goes from `i + 1` to `n - 2` and checks if the substring from `i + 1` to `j` and from `j + 1` to `n-1` are both palindromes. If such a split is found, it returns true. If all possible splits are checked and no palindromic split is found, the function returns false.

## A solution in Python

```python
def is_palindrome(s, start, end):
    while start < end:
        if s[start] != s[end]:
            return False
        start += 1
        end -= 1
    return True

def check_partitioning(s):
    n = len(s)
    for i in range(0, n - 2):
        if is_palindrome(s, 0, i):
            for j in range(i + 1, n - 1):
                if is_palindrome(s, i + 1, j) and is_palindrome(s, j + 1, n - 1):
                    return True
    return False
```
The algorithm creates a helper function `isPalindrome` to check if a given substring is a palindrome based on start and end indices. Then, in the main function `checkPartitioning`, it iterates through the string to find a possible split that gives three non-empty palindromic substrings. In the outer loop, it goes from 0 to `n - 3` and checks if the substring from 0 to `i` is palindrome. In the inner loop, it goes from `i + 1` to `n - 2` and checks if the substring from `i + 1` to `j` and from `j + 1` to `n-1` are both palindromes. If such a split is found, it returns true. If all possible splits are checked and no palindromic split is found, the function returns false.

## A solution in Javascript

```javascript
function isPalindrome(s, start, end) {
    while (start < end) {
        if (s[start] !== s[end]) return false;
        start++;
        end--;
    }
    return true;
}

function checkPartitioning(s) {
    const n = s.length;
    for (let i = 0; i < n - 2; ++i) {
        if (isPalindrome(s, 0, i)) {
            for (let j = i + 1; j < n - 1; ++j) {
                if (isPalindrome(s, i + 1, j) && isPalindrome(s, j + 1, n - 1)) return true;
            }
        }
    }
    return false;
}
```
The algorithm creates a helper function `isPalindrome` to check if a given substring is a palindrome based on start and end indices. Then, in the main function `checkPartitioning`, it iterates through the string to find a possible split that gives three non-empty palindromic substrings. In the outer loop, it goes from 0 to `n - 3` and checks if the substring from 0 to `i` is palindrome. In the inner loop, it goes from `i + 1` to `n - 2` and checks if the substring from `i + 1` to `j` and from `j + 1` to `n-1` are both palindromes. If such a split is found, it returns true. If all possible splits are checked and no palindromic split is found, the function returns false.


# Maximum Subarray Sum After One Operation

- slug: maximum-subarray-sum-after-one-operation
- difficulty: Medium

You are given an integer array `nums`. You must perform **exactly one** operation where you can **replace** one element `nums[i]` with `nums[i] * nums[i]`.

Return _the **maximum** possible subarray sum after **exactly one** operation_. The subarray must be non-empty.

**Example 1:**

**Input:** nums = \[2,-1,-4,-3\]
**Output:** 17
**Explanation:** You can perform the operation on index 2 (0-indexed) to make nums = \[2,-1,**16**,-3\]. Now, the maximum subarray sum is 2 + -1 + 16 = 17.

**Example 2:**

**Input:** nums = \[1,-1,1,1,-1,-1,1\]
**Output:** 4
**Explanation:** You can perform the operation on index 1 (0-indexed) to make nums = \[1,**1**,1,1,-1,-1,1\]. Now, the maximum subarray sum is 1 + 1 + 1 + 1 = 4.

**Constraints:**

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

## A solution in Java

```java
public int maxLengthBetweenEqualCharacters(String s) {
    int maxLength = -1;
    HashMap<Character, Integer> charIndexMap = new HashMap<>();

    for (int i = 0; i < s.length(); i++) {
        char currentChar = s.charAt(i);

        if (charIndexMap.containsKey(currentChar)) {
            maxLength = Math.max(maxLength, i - charIndexMap.get(currentChar) - 1);
        } else {
            charIndexMap.put(currentChar, i);
        }
    }

    return maxLength;
}
```
1. Initialize maxLength to -1 and create a hash map (or dictionary) called charIndexMap.
2. Iterate through the string s and for each character:
   a. If the character is already in charIndexMap, update maxLength with the maximum value between the current maxLength and the distance between the current index and the previous index of the character minus 1.
   b. If the character is not in the charIndexMap, store the character and its index in the map.
3. Return maxLength. If maxLength is never updated (no equal characters found), it will return -1 as required.

## A solution in C++

```cpp
int maxLengthBetweenEqualCharacters(std::string s) {
    int maxLength = -1;
    std::unordered_map<char, int> charIndexMap;

    for (int i = 0; i < s.length(); i++) {
        if (charIndexMap.count(s[i])) {
            maxLength = std::max(maxLength, i - charIndexMap[s[i]] - 1);
        } else {
            charIndexMap[s[i]] = i;
        }
    }

    return maxLength;
}
```
1. Initialize maxLength to -1 and create a hash map (or dictionary) called charIndexMap.
2. Iterate through the string s and for each character:
   a. If the character is already in charIndexMap, update maxLength with the maximum value between the current maxLength and the distance between the current index and the previous index of the character minus 1.
   b. If the character is not in the charIndexMap, store the character and its index in the map.
3. Return maxLength. If maxLength is never updated (no equal characters found), it will return -1 as required.

## A solution in Python

```python
def maxLengthBetweenEqualCharacters(s: str) -> int:
    max_length = -1
    char_index_map = {}

    for i, char in enumerate(s):
        if char in char_index_map:
            max_length = max(max_length, i - char_index_map[char] - 1)
        else:
            char_index_map[char] = i

    return max_length
```
1. Initialize maxLength to -1 and create a hash map (or dictionary) called charIndexMap.
2. Iterate through the string s and for each character:
   a. If the character is already in charIndexMap, update maxLength with the maximum value between the current maxLength and the distance between the current index and the previous index of the character minus 1.
   b. If the character is not in the charIndexMap, store the character and its index in the map.
3. Return maxLength. If maxLength is never updated (no equal characters found), it will return -1 as required.

## A solution in Javascript

```javascript
function maxLengthBetweenEqualCharacters(s) {
    let maxLength = -1;
    let charIndexMap = new Map();

    for (let i = 0; i < s.length; i++) {
        if (charIndexMap.has(s[i])) {
            maxLength = Math.max(maxLength, i - charIndexMap.get(s[i]) - 1);
        } else {
            charIndexMap.set(s[i], i);
        }
    }

    return maxLength;
}
```
1. Initialize maxLength to -1 and create a hash map (or dictionary) called charIndexMap.
2. Iterate through the string s and for each character:
   a. If the character is already in charIndexMap, update maxLength with the maximum value between the current maxLength and the distance between the current index and the previous index of the character minus 1.
   b. If the character is not in the charIndexMap, store the character and its index in the map.
3. Return maxLength. If maxLength is never updated (no equal characters found), it will return -1 as required.


# Sum of Unique Elements

- slug: sum-of-unique-elements
- difficulty: Easy

You are given an integer array `nums`. The unique elements of an array are the elements that appear **exactly once** in the array.

Return _the **sum** of all the unique elements of_ `nums`.

**Example 1:**

**Input:** nums = \[1,2,3,2\]
**Output:** 4
**Explanation:** The unique elements are \[1,3\], and the sum is 4.

**Example 2:**

**Input:** nums = \[1,1,1,1,1\]
**Output:** 0
**Explanation:** There are no unique elements, and the sum is 0.

**Example 3:**

**Input:** nums = \[1,2,3,4,5\]
**Output:** 15
**Explanation:** The unique elements are \[1,2,3,4,5\], and the sum is 15.

**Constraints:**

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

## A solution in Java

```java
import java.util.*;

class Solution {
    public int bestTeamScore(int[] scores, int[] ages) {
        int n = scores.length;
        Integer[] indices = new Integer[n];
        for (int i = 0; i < n; i++) {
            indices[i] = i;
        }

        Arrays.sort(indices, (i, j) -> ages[i] == ages[j] ? scores[i] - scores[j] : ages[i] - ages[j]);

        int[] dp = new int[n];
        int best_score = 0;

        for (int i = 0; i < n; i++) {
            dp[i] = scores[indices[i]];
            for (int j = 0; j < i; j++) {
                if (scores[indices[i]] >= scores[indices[j]]) {
                    dp[i] = Math.max(dp[i], dp[j] + scores[indices[i]]);
                }
            }
            best_score = Math.max(best_score, dp[i]);
        }

        return best_score;
    }
}
```
1. First, we create a new array/list (`players`) of pairs containing the players' ages and scores.
2. Next, we sort the `players` array/list by age, followed by sorting by scores within the same age.
3. We create a `dp` array/list of length `n` (number of players) initializing it with 0.
4. Then, we iterate through each player in the sorted `players` array/list:
    a. Set `dp[i]` to the current player's score.
    b. Iterate through all previous players (0 to i-1) and check if the current player's score is greater or equal to the previous player's score. If true, set `dp[i]` to the maximum value between existing `dp[i]` and the sum of that previous player's DP value plus the current player's score.
    c. Update the `best_score` with the maximum of its current value and `dp[i]` for each player.
5. Lastly, return the `best_score` which represents the highest overall score of all possible basketball teams without conflicts.

## A solution in C++

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

using namespace std;

int bestTeamScore(vector<int>& scores, vector<int>& ages) {
    int n = scores.size();
    vector<pair<int, int>> players(n);

    for (int i = 0; i < n; ++i) {
        players[i] = {ages[i], scores[i]};
    }

    sort(players.begin(), players.end());

    vector<int> dp(n);
    int best_score = 0;

    for (int i = 0; i < n; ++i) {
        dp[i] = players[i].second;
        for (int j = 0; j < i; ++j) {
            if (players[i].second >= players[j].second) {
                dp[i] = max(dp[i], dp[j] + players[i].second);
            }
        }
        best_score = max(best_score, dp[i]);
    }

    return best_score;
}
```
1. First, we create a new array/list (`players`) of pairs containing the players' ages and scores.
2. Next, we sort the `players` array/list by age, followed by sorting by scores within the same age.
3. We create a `dp` array/list of length `n` (number of players) initializing it with 0.
4. Then, we iterate through each player in the sorted `players` array/list:
    a. Set `dp[i]` to the current player's score.
    b. Iterate through all previous players (0 to i-1) and check if the current player's score is greater or equal to the previous player's score. If true, set `dp[i]` to the maximum value between existing `dp[i]` and the sum of that previous player's DP value plus the current player's score.
    c. Update the `best_score` with the maximum of its current value and `dp[i]` for each player.
5. Lastly, return the `best_score` which represents the highest overall score of all possible basketball teams without conflicts.

## A solution in Python

```python
def bestTeamScore(scores, ages):
    players = sorted(zip(ages, scores))
    n = len(players)
    dp = [0] * n
    best_score = 0

    for i in range(n):
        dp[i] = players[i][1]
        for j in range(i):
            if players[i][1] >= players[j][1]:
                dp[i] = max(dp[i], dp[j] + players[i][1])
        best_score = max(best_score, dp[i])

    return best_score
```
1. First, we create a new array/list (`players`) of pairs containing the players' ages and scores.
2. Next, we sort the `players` array/list by age, followed by sorting by scores within the same age.
3. We create a `dp` array/list of length `n` (number of players) initializing it with 0.
4. Then, we iterate through each player in the sorted `players` array/list:
    a. Set `dp[i]` to the current player's score.
    b. Iterate through all previous players (0 to i-1) and check if the current player's score is greater or equal to the previous player's score. If true, set `dp[i]` to the maximum value between existing `dp[i]` and the sum of that previous player's DP value plus the current player's score.
    c. Update the `best_score` with the maximum of its current value and `dp[i]` for each player.
5. Lastly, return the `best_score` which represents the highest overall score of all possible basketball teams without conflicts.

## A solution in Javascript

```javascript
function bestTeamScore(scores, ages) {
    const players = ages.map((age, index) => [age, scores[index]]);
    players.sort((a, b) => a[0] - b[0] || a[1] - b[1]);

    const n = players.length;
    const dp = Array(n).fill(0);
    let bestScore = 0;

    for (let i = 0; i < n; i++) {
        dp[i] = players[i][1];
        for (let j = 0; j < i; j++) {
            if (players[i][1] >= players[j][1]) {
                dp[i] = Math.max(dp[i], dp[j] + players[i][1]);
            }
        }
        bestScore = Math.max(bestScore, dp[i]);
    }

    return bestScore;
}
```
1. First, we create a new array/list (`players`) of pairs containing the players' ages and scores.
2. Next, we sort the `players` array/list by age, followed by sorting by scores within the same age.
3. We create a `dp` array/list of length `n` (number of players) initializing it with 0.
4. Then, we iterate through each player in the sorted `players` array/list:
    a. Set `dp[i]` to the current player's score.
    b. Iterate through all previous players (0 to i-1) and check if the current player's score is greater or equal to the previous player's score. If true, set `dp[i]` to the maximum value between existing `dp[i]` and the sum of that previous player's DP value plus the current player's score.
    c. Update the `best_score` with the maximum of its current value and `dp[i]` for each player.
5. Lastly, return the `best_score` which represents the highest overall score of all possible basketball teams without conflicts.


# Maximum Absolute Sum of Any Subarray

- slug: maximum-absolute-sum-of-any-subarray
- difficulty: Medium

You are given an integer array `nums`. The **absolute sum** of a subarray `[numsl, numsl+1, ..., numsr-1, numsr]` is `abs(numsl + numsl+1 + ... + numsr-1 + numsr)`.

Return _the **maximum** absolute sum of any **(possibly empty)** subarray of_ `nums`.

Note that `abs(x)` is defined as follows:

*   If `x` is a negative integer, then `abs(x) = -x`.
*   If `x` is a non-negative integer, then `abs(x) = x`.

**Example 1:**

**Input:** nums = \[1,-3,2,3,-4\]
**Output:** 5
**Explanation:** The subarray \[2,3\] has absolute sum = abs(2+3) = abs(5) = 5.

**Example 2:**

**Input:** nums = \[2,-5,1,-4,3,-2\]
**Output:** 8
**Explanation:** The subarray \[-5,1,-4\] has absolute sum = abs(-5+1-4) = abs(-8) = 8.

**Constraints:**

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

## A solution in Java

```java
public int maxAbsoluteSum(int[] nums) {
    int max_sum = 0, min_sum = 0, max_end = 0, min_end = 0;
    for (int num : nums) {
        max_end = Math.max(max_end + num, num);
        min_end = Math.min(min_end + num, num);
        max_sum = Math.max(max_sum, max_end);
        min_sum = Math.min(min_sum, min_end);
    }
    return Math.max(max_sum, -min_sum);
}
```
We use the Kadane's algorithm to maintain both the maximum sum subarray (max_end) and the minimum sum subarray (min_end) ending at the current position.

1. Iterate through the given array nums
2. For each number in nums:
   1. Update max_end to be the maximum of max_end + num and num
   2. Update min_end to be the minimum of min_end + num and num
   3. Update max_sum to be the maximum of max_sum and max_end
   4. Update min_sum to be the minimum of min_sum and min_end
3. Return the maximum of max_sum and -min_sum.

Keep in mind that empty subarray is allowed, but in practice we won't need any additional code to handle empty subarray since the minimum absolute sum is always 0 (which can be the result of an empty subarray).

## A solution in C++

```cpp
int maxAbsoluteSum(vector<int>& nums) {
    int max_sum = 0, min_sum = 0, max_end = 0, min_end = 0;
    for (int num : nums) {
        max_end = max(max_end + num, num);
        min_end = min(min_end + num, num);
        max_sum = max(max_sum, max_end);
        min_sum = min(min_sum, min_end);
    }
    return max(max_sum, -min_sum);
}
```
We use the Kadane's algorithm to maintain both the maximum sum subarray (max_end) and the minimum sum subarray (min_end) ending at the current position.

1. Iterate through the given array nums
2. For each number in nums:
   1. Update max_end to be the maximum of max_end + num and num
   2. Update min_end to be the minimum of min_end + num and num
   3. Update max_sum to be the maximum of max_sum and max_end
   4. Update min_sum to be the minimum of min_sum and min_end
3. Return the maximum of max_sum and -min_sum.

Keep in mind that empty subarray is allowed, but in practice we won't need any additional code to handle empty subarray since the minimum absolute sum is always 0 (which can be the result of an empty subarray).

## A solution in Python

```python
def maxAbsoluteSum(nums):
    max_sum = max_end = min_sum = min_end = 0
    for num in nums:
        max_end = max(max_end + num, num)
        min_end = min(min_end + num, num)
        max_sum = max(max_sum, max_end)
        min_sum = min(min_sum, min_end)
    return max(max_sum, -min_sum)
```
We use the Kadane's algorithm to maintain both the maximum sum subarray (max_end) and the minimum sum subarray (min_end) ending at the current position.

1. Iterate through the given array nums
2. For each number in nums:
   1. Update max_end to be the maximum of max_end + num and num
   2. Update min_end to be the minimum of min_end + num and num
   3. Update max_sum to be the maximum of max_sum and max_end
   4. Update min_sum to be the minimum of min_sum and min_end
3. Return the maximum of max_sum and -min_sum.

Keep in mind that empty subarray is allowed, but in practice we won't need any additional code to handle empty subarray since the minimum absolute sum is always 0 (which can be the result of an empty subarray).

## A solution in Javascript

```javascript
function maxAbsoluteSum(nums) {
    let max_sum = 0, min_sum = 0, max_end = 0, min_end = 0;
    for (let num of nums) {
        max_end = Math.max(max_end + num, num);
        min_end = Math.min(min_end + num, num);
        max_sum = Math.max(max_sum, max_end);
        min_sum = Math.min(min_sum, min_end);
    }
    return Math.max(max_sum, -min_sum);
}
```
We use the Kadane's algorithm to maintain both the maximum sum subarray (max_end) and the minimum sum subarray (min_end) ending at the current position.

1. Iterate through the given array nums
2. For each number in nums:
   1. Update max_end to be the maximum of max_end + num and num
   2. Update min_end to be the minimum of min_end + num and num
   3. Update max_sum to be the maximum of max_sum and max_end
   4. Update min_sum to be the minimum of min_sum and min_end
3. Return the maximum of max_sum and -min_sum.

Keep in mind that empty subarray is allowed, but in practice we won't need any additional code to handle empty subarray since the minimum absolute sum is always 0 (which can be the result of an empty subarray).


# Minimum Length of String After Deleting Similar Ends

- slug: minimum-length-of-string-after-deleting-similar-ends
- difficulty: Medium

Given a string `s` consisting only of characters `'a'`, `'b'`, and `'c'`. You are asked to apply the following algorithm on the string any number of times:

1.  Pick a **non-empty** prefix from the string `s` where all the characters in the prefix are equal.
2.  Pick a **non-empty** suffix from the string `s` where all the characters in this suffix are equal.
3.  The prefix and the suffix should not intersect at any index.
4.  The characters from the prefix and suffix must be the same.
5.  Delete both the prefix and the suffix.

Return _the **minimum length** of_ `s` _after performing the above operation any number of times (possibly zero times)_.

**Example 1:**

**Input:** s =  "ca "
**Output:** 2
**Explanation:** You can't remove any characters, so the string stays as is.

**Example 2:**

**Input:** s =  "cabaabac "
**Output:** 0
**Explanation:** An optimal sequence of operations is:
- Take prefix =  "c " and suffix =  "c " and remove them, s =  "abaaba ".
- Take prefix =  "a " and suffix =  "a " and remove them, s =  "baab ".
- Take prefix =  "b " and suffix =  "b " and remove them, s =  "aa ".
- Take prefix =  "a " and suffix =  "a " and remove them, s =  " ".

**Example 3:**

**Input:** s =  "aabccabba "
**Output:** 3
**Explanation:** An optimal sequence of operations is:
- Take prefix =  "aa " and suffix =  "a " and remove them, s =  "bccabb ".
- Take prefix =  "b " and suffix =  "bb " and remove them, s =  "cca ".

**Constraints:**

*   `1 <= s.length <= 105`
*   `s` only consists of characters `'a'`, `'b'`, and `'c'`.

## A solution in Java

```java
public int minimumLength(String s) {
    if(s.isEmpty()) return 0;
    int i = 0, j = s.length() - 1;
    while(i < j){
        if(s.charAt(i) != s.charAt(j)) break;
        char remove_char = s.charAt(i);
        while(i < s.length() && s.charAt(i) == remove_char) i++;
        while(j >= 0 && s.charAt(j) == remove_char) j--;
    }
    return Math.max(0, j - i + 1);
}
```
The algorithm involves the use of two pointers, one at the beginning and the other at the end of the string. While the characters at the positions of both pointers are the same, we increment the first pointer (i) until a different character is found in the string, and decrement the second pointer (j) until a different character is found. We then return the difference between j and i plus 1, or 0 if the result is negative, as the minimum length after performing the operations.

## A solution in C++

```cpp
int minimumLength(string s) {
    if(s.empty()) return 0;
    int i = 0, j = s.length() - 1;
    while(i < j){
        if(s[i] != s[j]) break;
        char remove_char = s[i];
        while(i < s.length() && s[i] == remove_char) i++;
        while(j >= 0 && s[j] == remove_char) j--;
    }
    return max(0, j - i + 1);
}
```
The algorithm involves the use of two pointers, one at the beginning and the other at the end of the string. While the characters at the positions of both pointers are the same, we increment the first pointer (i) until a different character is found in the string, and decrement the second pointer (j) until a different character is found. We then return the difference between j and i plus 1, or 0 if the result is negative, as the minimum length after performing the operations.

## A solution in Python

```python
def minimumLength(s: str) -> int:
    if not s: return 0
    i, j = 0, len(s) - 1
    while i < j:
        if s[i] != s[j]: break
        remove_char = s[i]
        while i < len(s) and s[i] == remove_char: i += 1
        while j >= 0 and s[j] == remove_char: j -= 1
    return max(0, j - i + 1)
```
The algorithm involves the use of two pointers, one at the beginning and the other at the end of the string. While the characters at the positions of both pointers are the same, we increment the first pointer (i) until a different character is found in the string, and decrement the second pointer (j) until a different character is found. We then return the difference between j and i plus 1, or 0 if the result is negative, as the minimum length after performing the operations.

## A solution in Javascript

```javascript
function minimumLength(s) {
    if(s.isEmpty()) return 0;
    let i = 0, j = s.length - 1;
    while(i < j){
        if(s[i] != s[j]) break;
        let remove_char = s[i];
        while(i < s.length && s[i] == remove_char) i++;
        while(j >= 0 && s[j] == remove_char) j--;
    }
    return Math.max(0, j - i + 1);
}
```
The algorithm involves the use of two pointers, one at the beginning and the other at the end of the string. While the characters at the positions of both pointers are the same, we increment the first pointer (i) until a different character is found in the string, and decrement the second pointer (j) until a different character is found. We then return the difference between j and i plus 1, or 0 if the result is negative, as the minimum length after performing the operations.


# Maximum Number of Events That Can Be Attended II

- slug: maximum-number-of-events-that-can-be-attended-ii
- difficulty: Hard

You are given an array of `events` where `events[i] = [startDayi, endDayi, valuei]`. The `ith` event starts at `startDayi` and ends at `endDayi`, and if you attend this event, you will receive a value of `valuei`. You are also given an integer `k` which represents the maximum number of events you can attend.

You can only attend one event at a time. If you choose to attend an event, you must attend the **entire** event. Note that the end day is **inclusive**: that is, you cannot attend two events where one of them starts and the other ends on the same day.

Return _the **maximum sum** of values that you can receive by attending events._

**Example 1:**

**Input:** events = \[\[1,2,4\],\[3,4,3\],\[2,3,1\]\], k = 2
**Output:** 7
**Explanation:** Choose the green events, 0 and 1 (0-indexed) for a total value of 4 + 3 = 7.

**Example 2:**

**Input:** events = \[\[1,2,4\],\[3,4,3\],\[2,3,10\]\], k = 2
**Output:** 10
**Explanation:** Choose event 2 for a total value of 10.
Notice that you cannot attend any other event as they overlap, and that you do **not** have to attend k events.

**Example 3:**

**Input:** events = \[\[1,1,1\],\[2,2,2\],\[3,3,3\],\[4,4,4\]\], k = 3
**Output:** 9
**Explanation:** Although the events do not overlap, you can only attend 3 events. Pick the highest valued three.

**Constraints:**

*   `1 <= k <= events.length`
*   `1 <= k * events.length <= 106`
*   `1 <= startDayi <= endDayi <= 109`
*   `1 <= valuei <= 106`

## A solution in Java

```java
public char slowestKey(int[] releaseTimes, String keysPressed) {
    char max_key = keysPressed.charAt(0);
    int max_duration = releaseTimes[0];
    for (int i = 1; i < releaseTimes.length; i++) {
        int duration = releaseTimes[i] - releaseTimes[i - 1];
        if (duration > max_duration || (duration == max_duration && keysPressed.charAt(i) > max_key)) {
            max_key = keysPressed.charAt(i);
            max_duration = duration;
        }
    }
    return max_key;
}
```
The algorithm starts by initializing the max_key to the first key in keysPressed and max_duration to the duration of the first key press. Then, from the second key press to the last, it calculates the duration of each key press by subtracting the previous release time from the current release time. It compares the current duration with the max_duration. If the current duration is larger than max_duration or if the durations are equal and the current key is lexicographically larger than the max_key, update max_key and max_duration. Finally, return max_key as the result.

## A solution in C++

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

char slowestKey(vector<int>& releaseTimes, string keysPressed) {
    char max_key = keysPressed[0];
    int max_duration = releaseTimes[0];
    for (int i = 1; i < releaseTimes.size(); i++) {
        int duration = releaseTimes[i] - releaseTimes[i - 1];
        if (duration > max_duration || (duration == max_duration && keysPressed[i] > max_key)) {
            max_key = keysPressed[i];
            max_duration = duration;
        }
    }
    return max_key;
}
```
The algorithm starts by initializing the max_key to the first key in keysPressed and max_duration to the duration of the first key press. Then, from the second key press to the last, it calculates the duration of each key press by subtracting the previous release time from the current release time. It compares the current duration with the max_duration. If the current duration is larger than max_duration or if the durations are equal and the current key is lexicographically larger than the max_key, update max_key and max_duration. Finally, return max_key as the result.

## A solution in Python

```python
def slowestKey(releaseTimes, keysPressed):
    max_key = keysPressed[0]
    max_duration = releaseTimes[0]
    for i in range(1, len(releaseTimes)):
        duration = releaseTimes[i] - releaseTimes[i - 1]
        if duration > max_duration or (duration == max_duration and keysPressed[i] > max_key):
            max_key = keysPressed[i]
            max_duration = duration
    return max_key
```
The algorithm starts by initializing the max_key to the first key in keysPressed and max_duration to the duration of the first key press. Then, from the second key press to the last, it calculates the duration of each key press by subtracting the previous release time from the current release time. It compares the current duration with the max_duration. If the current duration is larger than max_duration or if the durations are equal and the current key is lexicographically larger than the max_key, update max_key and max_duration. Finally, return max_key as the result.

## A solution in Javascript

```javascript
function slowestKey(releaseTimes, keysPressed) {
    let max_key = keysPressed[0];
    let max_duration = releaseTimes[0];

    for (let i = 1; i < releaseTimes.length; i++) {
        let duration = releaseTimes[i] - releaseTimes[i - 1];
        if (duration > max_duration || (duration === max_duration && keysPressed[i] > max_key)) {
            max_key = keysPressed[i];
            max_duration = duration;
        }
    }
    return max_key;
}
```
The algorithm starts by initializing the max_key to the first key in keysPressed and max_duration to the duration of the first key press. Then, from the second key press to the last, it calculates the duration of each key press by subtracting the previous release time from the current release time. It compares the current duration with the max_duration. If the current duration is larger than max_duration or if the durations are equal and the current key is lexicographically larger than the max_key, update max_key and max_duration. Finally, return max_key as the result.


# Check if Array Is Sorted and Rotated

- slug: check-if-array-is-sorted-and-rotated
- difficulty: Easy

Given an array `nums`, return `true` _if the array was originally sorted in non-decreasing order, then rotated **some** number of positions (including zero)_. Otherwise, return `false`.

There may be **duplicates** in the original array.

**Note:** An array `A` rotated by `x` positions results in an array `B` of the same length such that `A[i] == B[(i+x) % A.length]`, where `%` is the modulo operation.

**Example 1:**

**Input:** nums = \[3,4,5,1,2\]
**Output:** true
**Explanation:** \[1,2,3,4,5\] is the original sorted array.
You can rotate the array by x = 3 positions to begin on the the element of value 3: \[3,4,5,1,2\].

**Example 2:**

**Input:** nums = \[2,1,3,4\]
**Output:** false
**Explanation:** There is no sorted array once rotated that can make nums.

**Example 3:**

**Input:** nums = \[1,2,3\]
**Output:** true
**Explanation:** \[1,2,3\] is the original sorted array.
You can rotate the array by x = 0 positions (i.e. no rotation) to make nums.

**Constraints:**

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

## A solution in Java

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

public List<Boolean> checkArithmeticSubarrays(int[] nums, int[] l, int[] r) {
    List<Boolean> results = new ArrayList<>();
    for(int i = 0; i < l.length; i++) {
        int[] subarray = Arrays.copyOfRange(nums, l[i], r[i] + 1);
        Arrays.sort(subarray);
        boolean is_arithmetic = true;
        int diff = subarray[1] - subarray[0];
        for(int j = 1; j < subarray.length - 1; j++) {
            if(subarray[j + 1] - subarray[j] != diff) {
                is_arithmetic = false;
                break;
            }
        }
        results.add(is_arithmetic);
    }
    return results;
}
```
1. For each element `i` in arrays `l` and `r`, create a subarray from `nums` using the range `[l[i], r[i]]`.
2. Sort the subarray.
3. Check if the subarray is an arithmetic sequence, by iterating through the subarray and making sure the difference between consecutive elements is the same.
4. If the subarray is an arithmetic sequence, add `true` to the result array, otherwise, add `false`.
5. Repeat this process for all the elements in arrays `l` and `r`.
6. Return the results array containing the answers for each query.

## A solution in C++

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

vector<bool> checkArithmeticSubarrays(vector<int>& nums, vector<int>& l, vector<int>& r) {
    vector<bool> results;
    for(int i = 0; i < l.size(); i++) {
        vector<int> subarray(nums.begin() + l[i], nums.begin() + r[i] + 1);
        sort(subarray.begin(), subarray.end());
        bool is_arithmetic = true;
        int diff = subarray[1] - subarray[0];
        for(int j = 1; j < subarray.size() - 1; j++) {
            if(subarray[j + 1] - subarray[j] != diff) {
                is_arithmetic = false;
                break;
            }
        }
        results.push_back(is_arithmetic);
    }
    return results;
}
```
1. For each element `i` in arrays `l` and `r`, create a subarray from `nums` using the range `[l[i], r[i]]`.
2. Sort the subarray.
3. Check if the subarray is an arithmetic sequence, by iterating through the subarray and making sure the difference between consecutive elements is the same.
4. If the subarray is an arithmetic sequence, add `true` to the result array, otherwise, add `false`.
5. Repeat this process for all the elements in arrays `l` and `r`.
6. Return the results array containing the answers for each query.

## A solution in Python

```python
def check_arithmetic_subarrays(nums, l, r):
    results = []
    for i in range(len(l)):
        subarray = sorted(nums[l[i]:r[i] + 1])
        is_arithmetic = True
        diff = subarray[1] - subarray[0]
        for j in range(1, len(subarray) - 1):
            if subarray[j + 1] - subarray[j] != diff:
                is_arithmetic = False
                break
        results.append(is_arithmetic)
    return results
```
1. For each element `i` in arrays `l` and `r`, create a subarray from `nums` using the range `[l[i], r[i]]`.
2. Sort the subarray.
3. Check if the subarray is an arithmetic sequence, by iterating through the subarray and making sure the difference between consecutive elements is the same.
4. If the subarray is an arithmetic sequence, add `true` to the result array, otherwise, add `false`.
5. Repeat this process for all the elements in arrays `l` and `r`.
6. Return the results array containing the answers for each query.

## A solution in Javascript

```javascript
function checkArithmeticSubarrays(nums, l, r) {
    const results = [];
    for(let i = 0; i < l.length; i++) {
        const subarray = nums.slice(l[i], r[i] + 1).sort((a, b) => a - b);
        let is_arithmetic = true;
        const diff = subarray[1] - subarray[0];
        for(let j = 1; j < subarray.length - 1; j++) {
            if(subarray[j + 1] - subarray[j] !== diff) {
                is_arithmetic = false;
                break;
            }
        }
        results.push(is_arithmetic);
    }
    return results;
}
```
1. For each element `i` in arrays `l` and `r`, create a subarray from `nums` using the range `[l[i], r[i]]`.
2. Sort the subarray.
3. Check if the subarray is an arithmetic sequence, by iterating through the subarray and making sure the difference between consecutive elements is the same.
4. If the subarray is an arithmetic sequence, add `true` to the result array, otherwise, add `false`.
5. Repeat this process for all the elements in arrays `l` and `r`.
6. Return the results array containing the answers for each query.


# Maximum Score From Removing Stones

- slug: maximum-score-from-removing-stones
- difficulty: Medium

You are playing a solitaire game with **three piles** of stones of sizes `a`, `b`, and `c` respectively. Each turn you choose two **different non-empty** piles, take one stone from each, and add `1` point to your score. The game stops when there are **fewer than two non-empty** piles (meaning there are no more available moves).

Given three integers `a`, `b`, and `c`, return _the_ **_maximum_** _**score** you can get._

**Example 1:**

**Input:** a = 2, b = 4, c = 6
**Output:** 6
**Explanation:** The starting state is (2, 4, 6). One optimal set of moves is:
- Take from 1st and 3rd piles, state is now (1, 4, 5)
- Take from 1st and 3rd piles, state is now (0, 4, 4)
- Take from 2nd and 3rd piles, state is now (0, 3, 3)
- Take from 2nd and 3rd piles, state is now (0, 2, 2)
- Take from 2nd and 3rd piles, state is now (0, 1, 1)
- Take from 2nd and 3rd piles, state is now (0, 0, 0)
There are fewer than two non-empty piles, so the game ends. Total: 6 points.

**Example 2:**

**Input:** a = 4, b = 4, c = 6
**Output:** 7
**Explanation:** The starting state is (4, 4, 6). One optimal set of moves is:
- Take from 1st and 2nd piles, state is now (3, 3, 6)
- Take from 1st and 3rd piles, state is now (2, 3, 5)
- Take from 1st and 3rd piles, state is now (1, 3, 4)
- Take from 1st and 3rd piles, state is now (0, 3, 3)
- Take from 2nd and 3rd piles, state is now (0, 2, 2)
- Take from 2nd and 3rd piles, state is now (0, 1, 1)
- Take from 2nd and 3rd piles, state is now (0, 0, 0)
There are fewer than two non-empty piles, so the game ends. Total: 7 points.

**Example 3:**

**Input:** a = 1, b = 8, c = 8
**Output:** 8
**Explanation:** One optimal set of moves is to take from the 2nd and 3rd piles for 8 turns until they are empty.
After that, there are fewer than two non-empty piles, so the game ends.

**Constraints:**

*   `1 <= a, b, c <= 105`

## A solution in Java

```java
import java.util.PriorityQueue;

class Solution {
    private int[][] directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

    public int minimumEffortPath(int[][] heights) {
        int rows = heights.length;
        int cols = heights[0].length;
        int[][] efforts = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                efforts[i][j] = Integer.MAX_VALUE;
            }
        }

        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
        efforts[0][0] = 0;
        pq.offer(new int[]{0, 0, 0});

        while (!pq.isEmpty()) {
            int[] cur = pq.poll();
            int effort = cur[0], x = cur[1], y = cur[2];

            if (x == rows - 1 && y == cols - 1) {
                return effort;
            }

            for (int[] dir : directions) {
                int nx = x + dir[0];
                int ny = y + dir[1];
                if (nx >= 0 && nx < rows && ny >= 0 && ny < cols) {
                    int new_effort = Math.max(effort, Math.abs(heights[nx][ny] - heights[x][y]));
                    if (new_effort < efforts[nx][ny]) {
                        efforts[nx][ny] = new_effort;
                        pq.offer(new int[]{new_effort, nx, ny});
                    }
                }
            }
        }

        return -1;
    }
}
```
The algorithm uses Dijkstra's shortest path algorithm to find the path with the minimum effort. Starting from position (0, 0), the algorithm maintains a priority queue of cells to visit, with their current efforts. At each step, the algorithm chooses the cell with the lowest effort, and then tries to move to its neighbors in all four possible directions. When updating the effort of its neighbor, the algorithm only takes into account the highest effort seen so far on its path, which is the maximum absolute difference in heights between two consecutive cells on its path.

The algorithm maintains a 2D effort array, where efforts[row][col] represents the minimum effort required to reach the cell (row, col). It then pushes these efforts into a priority queue that sorts the cells in non-decreasing order of their efforts.

When the algorithm finally reaches the destination cell (rows-1, columns-1), it returns the corresponding effort.

The time complexity of the algorithm is O(rows*columns*log(rows*columns)), as it potentially visits all cells and uses a priority queue for the processing. The space complexity is O(rows*columns) due to the effort array and priority queue storage.

## A solution in C++

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

using std::vector;
using std::pair;
using std::priority_queue;

int minimumEffortPath(vector<vector<int>>& heights) {
    const vector<pair<int, int>> directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    int rows = heights.size();
    int cols = heights[0].size();
    vector<vector<int>> efforts(rows, vector<int>(cols, INT_MAX));
    priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, std::greater<>> pq;

    efforts[0][0] = 0;
    pq.push({0, {0, 0}});

    while (!pq.empty()) {
        auto [effort, pos] = pq.top();
        pq.pop();
        int x = pos.first, y = pos.second;

        if (x == rows - 1 && y == cols - 1) {
            return effort;
        }

        for (const auto& dir : directions) {
            int nx = x + dir.first;
            int ny = y + dir.second;
            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols) {
                int new_effort = std::max(effort, std::abs(heights[nx][ny] - heights[x][y]));
                if (new_effort < efforts[nx][ny]) {
                    efforts[nx][ny] = new_effort;
                    pq.push({new_effort, {nx, ny}});
                }
            }
        }
    }

    return -1;
}
```
The algorithm uses Dijkstra's shortest path algorithm to find the path with the minimum effort. Starting from position (0, 0), the algorithm maintains a priority queue of cells to visit, with their current efforts. At each step, the algorithm chooses the cell with the lowest effort, and then tries to move to its neighbors in all four possible directions. When updating the effort of its neighbor, the algorithm only takes into account the highest effort seen so far on its path, which is the maximum absolute difference in heights between two consecutive cells on its path.

The algorithm maintains a 2D effort array, where efforts[row][col] represents the minimum effort required to reach the cell (row, col). It then pushes these efforts into a priority queue that sorts the cells in non-decreasing order of their efforts.

When the algorithm finally reaches the destination cell (rows-1, columns-1), it returns the corresponding effort.

The time complexity of the algorithm is O(rows*columns*log(rows*columns)), as it potentially visits all cells and uses a priority queue for the processing. The space complexity is O(rows*columns) due to the effort array and priority queue storage.

## A solution in Python

```python
import heapq
from typing import List

def minimumEffortPath(heights: List[List[int]]) -> int:
    directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
    rows = len(heights)
    cols = len(heights[0])
    efforts = [[float('inf')] * cols for _ in range(rows)]

    q = [(0, 0, 0)]
    efforts[0][0] = 0

    while q:
        effort, x, y = heapq.heappop(q)

        if x == rows - 1 and y == cols - 1:
            return effort

        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if 0 <= nx < rows and 0 <= ny < cols:
                new_effort = max(effort, abs(heights[nx][ny] - heights[x][y]))
                if new_effort < efforts[nx][ny]:
                    efforts[nx][ny] = new_effort
                    heapq.heappush(q, (new_effort, nx, ny))

    return -1
```
The algorithm uses Dijkstra's shortest path algorithm to find the path with the minimum effort. Starting from position (0, 0), the algorithm maintains a priority queue of cells to visit, with their current efforts. At each step, the algorithm chooses the cell with the lowest effort, and then tries to move to its neighbors in all four possible directions. When updating the effort of its neighbor, the algorithm only takes into account the highest effort seen so far on its path, which is the maximum absolute difference in heights between two consecutive cells on its path.

The algorithm maintains a 2D effort array, where efforts[row][col] represents the minimum effort required to reach the cell (row, col). It then pushes these efforts into a priority queue that sorts the cells in non-decreasing order of their efforts.

When the algorithm finally reaches the destination cell (rows-1, columns-1), it returns the corresponding effort.

The time complexity of the algorithm is O(rows*columns*log(rows*columns)), as it potentially visits all cells and uses a priority queue for the processing. The space complexity is O(rows*columns) due to the effort array and priority queue storage.

## A solution in Javascript

```javascript
function minimumEffortPath(heights) {
    const directions = [[1, 0], [0, 1], [-1, 0], [0, -1]];
    const rows = heights.length;
    const cols = heights[0].length;
    const efforts = Array.from({ length: rows }, () => Array(cols).fill(Infinity));
    const pq = new PriorityQueue((a, b) => a[0] - b[0]);

    efforts[0][0] = 0;
    pq.offer([0, 0, 0]);

    while (!pq.isEmpty()) {
        const [effort, x, y] = pq.poll();

        if (x === rows - 1 && y === cols - 1) {
            return effort;
        }

        for (const [dx, dy] of directions) {
            const nx = x + dx;
            const ny = y + dy;
            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols) {
                const newEffort = Math.max(effort, Math.abs(heights[nx][ny] - heights[x][y]));
                if (newEffort < efforts[nx][ny]) {
                    efforts[nx][ny] = newEffort;
                    pq.offer([newEffort, nx, ny]);
                }
            }
        }
    }

    return -1;
}

class PriorityQueue {
    constructor(comparator) {
        this.comparator = comparator;
        this.data = [];
    }

    offer(elem) {
        let i = this.data.length;
        this.data.push(elem);

        while (i > 0) {
            const parent = Math.floor((i - 1) / 2);
            if (this.comparator(this.data[i], this.data[parent]) >= 0) {
                break;
            }
            [this.data[i], this.data[parent]] = [this.data[parent], this.data[i]];
            i = parent;
        }
    }

    poll() {
        if (this.isEmpty()) return null;

        const result = this.data[0];
        const last = this.data.pop();

        if (!this.isEmpty()) {
            this.data[0] = last;
            let i = 0;

            while (true) {
                const left = 2 * i + 1;
                const right = 2 * i + 2;
                let smallest = i;

                if (left < this.data.length && this.comparator(this.data[left], this.data[smallest]) < 0) {
                    smallest = left;
                }

                if (right < this.data.length && this.comparator(this.data[right], this.data[smallest]) < 0) {
                    smallest = right;
                }

                if (smallest === i) break;

                [this.data[i], this.data[smallest]] = [this.data[smallest], this.data[i]];
                i = smallest;
            }
        }

        return result;
    }

    isEmpty() {
        return this.data.length === 0;
    }
}
```
The algorithm uses Dijkstra's shortest path algorithm to find the path with the minimum effort. Starting from position (0, 0), the algorithm maintains a priority queue of cells to visit, with their current efforts. At each step, the algorithm chooses the cell with the lowest effort, and then tries to move to its neighbors in all four possible directions. When updating the effort of its neighbor, the algorithm only takes into account the highest effort seen so far on its path, which is the maximum absolute difference in heights between two consecutive cells on its path.

The algorithm maintains a 2D effort array, where efforts[row][col] represents the minimum effort required to reach the cell (row, col). It then pushes these efforts into a priority queue that sorts the cells in non-decreasing order of their efforts.

When the algorithm finally reaches the destination cell (rows-1, columns-1), it returns the corresponding effort.

The time complexity of the algorithm is O(rows*columns*log(rows*columns)), as it potentially visits all cells and uses a priority queue for the processing. The space complexity is O(rows*columns) due to the effort array and priority queue storage.


# Largest Merge Of Two Strings

- slug: largest-merge-of-two-strings
- difficulty: Medium

You are given two strings `word1` and `word2`. You want to construct a string `merge` in the following way: while either `word1` or `word2` are non-empty, choose **one** of the following options:

*   If `word1` is non-empty, append the **first** character in `word1` to `merge` and delete it from `word1`.
    *   For example, if `word1 = "abc "` and `merge = "dv "`, then after choosing this operation, `word1 = "bc "` and `merge = "dva "`.
*   If `word2` is non-empty, append the **first** character in `word2` to `merge` and delete it from `word2`.
    *   For example, if `word2 = "abc "` and `merge = " "`, then after choosing this operation, `word2 = "bc "` and `merge = "a "`.

Return _the lexicographically **largest**_ `merge` _you can construct_.

A string `a` is lexicographically larger than a string `b` (of the same length) if in the first position where `a` and `b` differ, `a` has a character strictly larger than the corresponding character in `b`. For example, `"abcd "` is lexicographically larger than `"abcc "` because the first position they differ is at the fourth character, and `d` is greater than `c`.

**Example 1:**

**Input:** word1 =  "cabaa ", word2 =  "bcaaa "
**Output:**  "cbcabaaaaa "
**Explanation:** One way to get the lexicographically largest merge is:
- Take from word1: merge =  "c ", word1 =  "abaa ", word2 =  "bcaaa "
- Take from word2: merge =  "cb ", word1 =  "abaa ", word2 =  "caaa "
- Take from word2: merge =  "cbc ", word1 =  "abaa ", word2 =  "aaa "
- Take from word1: merge =  "cbca ", word1 =  "baa ", word2 =  "aaa "
- Take from word1: merge =  "cbcab ", word1 =  "aa ", word2 =  "aaa "
- Append the remaining 5 a's from word1 and word2 at the end of merge.

**Example 2:**

**Input:** word1 =  "abcabc ", word2 =  "abdcaba "
**Output:**  "abdcabcabcaba "

**Constraints:**

*   `1 <= word1.length, word2.length <= 3000`
*   `word1` and `word2` consist only of lowercase English letters.

## A solution in Java

```java
public String largestMerge(String word1, String word2) {
    StringBuilder result = new StringBuilder();
    while (!word1.isEmpty() || !word2.isEmpty()) {
        if (word1.compareTo(word2) > 0) {
            result.append(word1.charAt(0));
            word1 = word1.substring(1);
        } else {
            result.append(word2.charAt(0));
            word2 = word2.substring(1);
        }
    }
    return result.toString();
}
```
The algorithm iterates through both `word1` and `word2` until they are both empty. At each step, it compares the two strings and appends the first character of the lexicographically larger string to the `result` string. It then removes that character from its respective string (using `erase` in C++, `substring` in Java, slicing in Python, and `slice` in JavaScript). Once both `word1` and `word2` are empty, the loop ends, and the constructed `result` string is returned.

This algorithm ensures that we prioritize the lexicographically larger character when appending to the result, always creating the largest possible merged string.

## A solution in C++

```cpp
std::string largestMerge(std::string word1, std::string word2) {
    std::string result;
    while (!word1.empty() || !word2.empty()) {
        if (word1 > word2) {
            result += word1[0];
            word1.erase(word1.begin());
        } else {
            result += word2[0];
            word2.erase(word2.begin());
        }
    }
    return result;
}
```
The algorithm iterates through both `word1` and `word2` until they are both empty. At each step, it compares the two strings and appends the first character of the lexicographically larger string to the `result` string. It then removes that character from its respective string (using `erase` in C++, `substring` in Java, slicing in Python, and `slice` in JavaScript). Once both `word1` and `word2` are empty, the loop ends, and the constructed `result` string is returned.

This algorithm ensures that we prioritize the lexicographically larger character when appending to the result, always creating the largest possible merged string.

## A solution in Python

```python
def largest_merge(word1: str, word2: str) -> str:
    merge = []
    while word1 or word2:
        if word1 > word2:
            merge.append(word1[0])
            word1 = word1[1:]
        else:
            merge.append(word2[0])
            word2 = word2[1:]
    return ''.join(merge)
```
The algorithm iterates through both `word1` and `word2` until they are both empty. At each step, it compares the two strings and appends the first character of the lexicographically larger string to the `result` string. It then removes that character from its respective string (using `erase` in C++, `substring` in Java, slicing in Python, and `slice` in JavaScript). Once both `word1` and `word2` are empty, the loop ends, and the constructed `result` string is returned.

This algorithm ensures that we prioritize the lexicographically larger character when appending to the result, always creating the largest possible merged string.

## A solution in Javascript

```javascript
function largestMerge(word1, word2) {
    let result = '';
    while (word1.length > 0 || word2.length > 0) {
        if (word1 > word2) {
            result += word1[0];
            word1 = word1.slice(1);
        } else {
            result += word2[0];
            word2 = word2.slice(1);
        }
    }
    return result;
}
```
The algorithm iterates through both `word1` and `word2` until they are both empty. At each step, it compares the two strings and appends the first character of the lexicographically larger string to the `result` string. It then removes that character from its respective string (using `erase` in C++, `substring` in Java, slicing in Python, and `slice` in JavaScript). Once both `word1` and `word2` are empty, the loop ends, and the constructed `result` string is returned.

This algorithm ensures that we prioritize the lexicographically larger character when appending to the result, always creating the largest possible merged string.


# Closest Subsequence Sum

- slug: closest-subsequence-sum
- difficulty: Hard

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

You want to choose a subsequence of `nums` such that the sum of its elements is the closest possible to `goal`. That is, if the sum of the subsequence's elements is `sum`, then you want to **minimize the absolute difference** `abs(sum - goal)`.

Return _the **minimum** possible value of_ `abs(sum - goal)`.

Note that a subsequence of an array is an array formed by removing some elements **(possibly all or none)** of the original array.

**Example 1:**

**Input:** nums = \[5,-7,3,5\], goal = 6
**Output:** 0
**Explanation:** Choose the whole array as a subsequence, with a sum of 6.
This is equal to the goal, so the absolute difference is 0.

**Example 2:**

**Input:** nums = \[7,-9,15,-2\], goal = -5
**Output:** 1
**Explanation:** Choose the subsequence \[7,-9,-2\], with a sum of -4.
The absolute difference is abs(-4 - (-5)) = abs(1) = 1, which is the minimum.

**Example 3:**

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

**Constraints:**

*   `1 <= nums.length <= 40`
*   `-107 <= nums[i] <= 107`
*   `-109 <= goal <= 109`

## A solution in Java

```java
public int[] decrypt(int[] code, int k) {
    int n = code.length;
    int[] result = new int[n];
    if (k == 0) return result;

    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 1; j <= Math.abs(k); j++) {
            sum += k > 0 ? code[(i + j) % n] : code[(i - j + n) % n];
        }
        result[i] = sum;
    }
    return result;
}
```
The given problem requires iterating through each element of the circular array code and, depending on the value of key k, summing up either the k next or k previous elements, and storing the sums into a new array called result. The new array represents the decrypted code.
1. Create an array called 'result' of the same length as code and initialized with zeros in all fields. If k equals to 0, return the result immediately as all elements are already 0.
2. Iterate through each element in code (use variable i as index). For each element, let sum be zero.
3. Nested loop: iterate starting from j = 1 to abs(k), where abs() represents the absolute value. Add code elements to sum depending on k value:
   - If k is greater than 0, add code[(i + j) % n].
   - If k is less than 0, add code[(i - j + n) % n].
4. Store sum in result array at index i.
5. After iterating through all code elements, return the result array.

## A solution in C++

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

vector<int> decrypt(vector<int>& code, int k) {
    int n = code.size();
    vector<int> result(n);
    if (k == 0) return vector<int>(n, 0);

    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 1; j <= abs(k); j++) {
            sum += k > 0 ? code[(i + j) % n] : code[(i - j + n) % n];
        }
        result[i] = sum;
    }
    return result;
}
```
The given problem requires iterating through each element of the circular array code and, depending on the value of key k, summing up either the k next or k previous elements, and storing the sums into a new array called result. The new array represents the decrypted code.
1. Create an array called 'result' of the same length as code and initialized with zeros in all fields. If k equals to 0, return the result immediately as all elements are already 0.
2. Iterate through each element in code (use variable i as index). For each element, let sum be zero.
3. Nested loop: iterate starting from j = 1 to abs(k), where abs() represents the absolute value. Add code elements to sum depending on k value:
   - If k is greater than 0, add code[(i + j) % n].
   - If k is less than 0, add code[(i - j + n) % n].
4. Store sum in result array at index i.
5. After iterating through all code elements, return the result array.

## A solution in Python

```python
def decrypt(code, k):
    n = len(code)
    result = [0] * n
    if k == 0: return result

    for i in range(n):
        sum = 0
        for j in range(1, abs(k) + 1):
            sum += code[(i + j) % n] if k > 0 else code[(i - j + n) % n]
        result[i] = sum
    return result
```
The given problem requires iterating through each element of the circular array code and, depending on the value of key k, summing up either the k next or k previous elements, and storing the sums into a new array called result. The new array represents the decrypted code.
1. Create an array called 'result' of the same length as code and initialized with zeros in all fields. If k equals to 0, return the result immediately as all elements are already 0.
2. Iterate through each element in code (use variable i as index). For each element, let sum be zero.
3. Nested loop: iterate starting from j = 1 to abs(k), where abs() represents the absolute value. Add code elements to sum depending on k value:
   - If k is greater than 0, add code[(i + j) % n].
   - If k is less than 0, add code[(i - j + n) % n].
4. Store sum in result array at index i.
5. After iterating through all code elements, return the result array.

## A solution in Javascript

```javascript
function decrypt(code, k) {
    const n = code.length;
    const result = new Array(n).fill(0);
    if (k === 0) return result;

    for (let i = 0; i < n; i++) {
        let sum = 0;
        for (let j = 1; j <= Math.abs(k); j++) {
            sum += k > 0 ? code[(i + j) % n] : code[(i - j + n) % n];
        }
        result[i] = sum;
    }
    return result;
}
```
The given problem requires iterating through each element of the circular array code and, depending on the value of key k, summing up either the k next or k previous elements, and storing the sums into a new array called result. The new array represents the decrypted code.
1. Create an array called 'result' of the same length as code and initialized with zeros in all fields. If k equals to 0, return the result immediately as all elements are already 0.
2. Iterate through each element in code (use variable i as index). For each element, let sum be zero.
3. Nested loop: iterate starting from j = 1 to abs(k), where abs() represents the absolute value. Add code elements to sum depending on k value:
   - If k is greater than 0, add code[(i + j) % n].
   - If k is less than 0, add code[(i - j + n) % n].
4. Store sum in result array at index i.
5. After iterating through all code elements, return the result array.