# Construct the Rectangle

- slug: construct-the-rectangle
- difficulty: Easy

A web developer needs to know how to design a web page's size. So, given a specific rectangular web page's area, your job by now is to design a rectangular web page, whose length L and width W satisfy the following requirements:

1.  The area of the rectangular web page you designed must equal to the given target area.
2.  The width `W` should not be larger than the length `L`, which means `L >= W`.
3.  The difference between length `L` and width `W` should be as small as possible.

Return _an array `[L, W]` where `L` and `W` are the length and width of the web page you designed in sequence._

**Example 1:**

**Input:** area = 4
**Output:** \[2,2\]
**Explanation:** The target area is 4, and all the possible ways to construct it are \[1,4\], \[2,2\], \[4,1\].
But according to requirement 2, \[1,4\] is illegal; according to requirement 3,  \[4,1\] is not optimal compared to \[2,2\]. So the length L is 2, and the width W is 2.

**Example 2:**

**Input:** area = 37
**Output:** \[37,1\]

**Example 3:**

**Input:** area = 122122
**Output:** \[427,286\]

**Constraints:**

*   `1 <= area <= 107`

## A solution in Java

```java
public int[] constructRectangle(int area) {
    int width = (int)Math.sqrt(area);
    while(area % width != 0) {
        width--;
    }
    int length = area / width;
    return new int[]{length, width};
}
```
The algorithm starts by calculating the square root of the given area, using the sqrt function in each language. Since web pages with more rectangular shapes are preferred, we start the width from `sqrt(area)` and work our way down.

We initialize the variable width with the integer value of the square root of the area: `width = sqrt(area)`. This initialization ensures that our width and length will be as close as possible to each other.

We then use a while loop to check if the current width divides the area evenly (`area % width != 0`). If it doesn't, we decrement the width by one and repeat the loop until we find a width that divides the area evenly.

Finally, we calculate the length by dividing the area with the width: `length = area / width`. We return the length and width as an array in the required sequence: `[length, width]`.

## A solution in C++

```cpp
#include <vector>
#include <cmath>

std::vector<int> constructRectangle(int area) {
    int width = std::sqrt(area);
    while(area % width != 0) {
        width -= 1;
    }
    int length = area / width;
    return {length, width};
}
```
The algorithm starts by calculating the square root of the given area, using the sqrt function in each language. Since web pages with more rectangular shapes are preferred, we start the width from `sqrt(area)` and work our way down.

We initialize the variable width with the integer value of the square root of the area: `width = sqrt(area)`. This initialization ensures that our width and length will be as close as possible to each other.

We then use a while loop to check if the current width divides the area evenly (`area % width != 0`). If it doesn't, we decrement the width by one and repeat the loop until we find a width that divides the area evenly.

Finally, we calculate the length by dividing the area with the width: `length = area / width`. We return the length and width as an array in the required sequence: `[length, width]`.

## A solution in Python

```python
def constructRectangle(area: int) -> List[int]:
    width = int(area**0.5)
    while area % width != 0:
        width -= 1
    length = area // width
    return [length, width]
```
The algorithm starts by calculating the square root of the given area, using the sqrt function in each language. Since web pages with more rectangular shapes are preferred, we start the width from `sqrt(area)` and work our way down.

We initialize the variable width with the integer value of the square root of the area: `width = sqrt(area)`. This initialization ensures that our width and length will be as close as possible to each other.

We then use a while loop to check if the current width divides the area evenly (`area % width != 0`). If it doesn't, we decrement the width by one and repeat the loop until we find a width that divides the area evenly.

Finally, we calculate the length by dividing the area with the width: `length = area / width`. We return the length and width as an array in the required sequence: `[length, width]`.

## A solution in Javascript

```javascript
function constructRectangle(area) {
    let width = Math.floor(Math.sqrt(area));
    while(area % width !== 0) {
        width--;
    }
    let length = area / width;
    return [length, width];
}
```
The algorithm starts by calculating the square root of the given area, using the sqrt function in each language. Since web pages with more rectangular shapes are preferred, we start the width from `sqrt(area)` and work our way down.

We initialize the variable width with the integer value of the square root of the area: `width = sqrt(area)`. This initialization ensures that our width and length will be as close as possible to each other.

We then use a while loop to check if the current width divides the area evenly (`area % width != 0`). If it doesn't, we decrement the width by one and repeat the loop until we find a width that divides the area evenly.

Finally, we calculate the length by dividing the area with the width: `length = area / width`. We return the length and width as an array in the required sequence: `[length, width]`.


# Reverse Pairs

- slug: reverse-pairs
- difficulty: Hard

Given an integer array `nums`, return _the number of **reverse pairs** in the array_.

A **reverse pair** is a pair `(i, j)` where:

*   `0 <= i < j < nums.length` and
*   `nums[i] > 2 * nums[j]`.

**Example 1:**

**Input:** nums = \[1,3,2,3,1\]
**Output:** 2
**Explanation:** The reverse pairs are:
(1, 4) --> nums\[1\] = 3, nums\[4\] = 1, 3 > 2 \* 1
(3, 4) --> nums\[3\] = 3, nums\[4\] = 1, 3 > 2 \* 1

**Example 2:**

**Input:** nums = \[2,4,3,5,1\]
**Output:** 3
**Explanation:** The reverse pairs are:
(1, 4) --> nums\[1\] = 4, nums\[4\] = 1, 4 > 2 \* 1
(2, 4) --> nums\[2\] = 3, nums\[4\] = 1, 3 > 2 \* 1
(3, 4) --> nums\[3\] = 5, nums\[4\] = 1, 5 > 2 \* 1

**Constraints:**

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

## A solution in Java

```java
public int reversePairs(int[] nums) {
    return mergeSort(nums, 0, nums.length - 1, new int[nums.length]);
}

private int mergeSort(int[] nums, int left, int right, int[] temp) {
    if (left >= right) {
        return 0;
    }
    int mid = left + (right - left) / 2;
    int count = mergeSort(nums, left, mid, temp) + mergeSort(nums, mid + 1, right, temp);
    count += merge(nums, left, mid, right, temp);

    return count;
}

private int merge(int[] nums, int left, int mid, int right, int[] temp) {
    int count = 0;
    System.arraycopy(nums, left, temp, left, right - left + 1);
    int j = mid + 1;
    for (int i = left; i <= mid; i++) {
        while (j <= right && (long) nums[i] > 2L * nums[j]) {
            j++;
        }
        count += j - (mid + 1);
    }
    int i = left;
    j = mid + 1;
    int k = left;
    while (i <= mid && j <= right) {
        if (temp[i] <= temp[j]) {
            nums[k++] = temp[i++];
        } else {
            nums[k++] = temp[j++];
        }
    }
    while (i <= mid) {
        nums[k++] = temp[i++];
    }
    while (j <= right) {
        nums[k++] = temp[j++];
    }

    return count;
}
```
The algorithm uses a modified merge sort to solve the problem efficiently. It counts the number of reverse pairs during the merge process, compares the elements in the left subarray with those in the right subarray, and increments the count based on the condition `nums[i] > 2 * nums[j]`. The merge sort divides the array into smaller subarrays, which are recursively sorted and merged.

For each subarray, we use two pointers `i` and `j` to find out the number of reverse pairs that satisfy the condition `nums[i] > 2 * nums[j]`. When iterating through the left subarray with `i`, we move `j` from the right subarray until we find the first index that doesn't satisfy the condition or we reach the end of the right subarray. The difference between the current position of `j` and the starting position is the count of valid reverse pairs. To get the overall count, we sum up the count value from both the left and right subarrays and also add the count found during merging the subarrays.

Finally, we merge the sorted subarrays using built-in sort functions. The process is similar in all four languages: C++ uses `std::merge` and `std::copy`, Java uses `System.arraycopy`, Python uses list slicing with `sorted()`, and JavaScript uses `Array.prototype.sort()` and `Array.prototype.splice()`.

The time complexity of the algorithm is O(n log n), as it takes advantage of the merge sort structure.

## A solution in C++

```cpp
#include <vector>

int merge(std::vector<int>& nums, std::vector<int>& temp, int left, int mid, int right) {
    int count = 0;
    int j = mid;
    for (int i = left; i < mid; i++) {
        while (j <= right && (long long)nums[i] > 2LL * nums[j]) {
            j++;
        }
        count += j - mid;
    }
    std::merge(nums.begin() + left, nums.begin() + mid, nums.begin() + mid, nums.begin() + right + 1, temp.begin() + left);

    return count;
}

int countReversePairs(std::vector<int>& nums, std::vector<int>& temp, int left, int right) {
    if (left >= right) {
        return 0;
    }
    int mid = left + (right - left) / 2;
    int count = countReversePairs(nums, temp, left, mid) + countReversePairs(nums, temp, mid + 1, right);
    count += merge(nums, temp, left, mid + 1, right);
    std::copy(temp.begin() + left, temp.begin() + right + 1, nums.begin() + left);

    return count;
}

int reversePairs(std::vector<int>& nums) {
    std::vector<int> temp(nums.size());
    return countReversePairs(nums, temp, 0, nums.size() - 1);
}
```
The algorithm uses a modified merge sort to solve the problem efficiently. It counts the number of reverse pairs during the merge process, compares the elements in the left subarray with those in the right subarray, and increments the count based on the condition `nums[i] > 2 * nums[j]`. The merge sort divides the array into smaller subarrays, which are recursively sorted and merged.

For each subarray, we use two pointers `i` and `j` to find out the number of reverse pairs that satisfy the condition `nums[i] > 2 * nums[j]`. When iterating through the left subarray with `i`, we move `j` from the right subarray until we find the first index that doesn't satisfy the condition or we reach the end of the right subarray. The difference between the current position of `j` and the starting position is the count of valid reverse pairs. To get the overall count, we sum up the count value from both the left and right subarrays and also add the count found during merging the subarrays.

Finally, we merge the sorted subarrays using built-in sort functions. The process is similar in all four languages: C++ uses `std::merge` and `std::copy`, Java uses `System.arraycopy`, Python uses list slicing with `sorted()`, and JavaScript uses `Array.prototype.sort()` and `Array.prototype.splice()`.

The time complexity of the algorithm is O(n log n), as it takes advantage of the merge sort structure.

## A solution in Python

```python
def reversePairs(nums):
    def mergeSort(l, r):
        if l >= r:
            return 0

        mid = (l + r) // 2
        count = mergeSort(l, mid) + mergeSort(mid + 1, r)
        j = mid + 1
        for i in range(l, mid + 1):
            while j <= r and nums[i] > 2 * nums[j]:
                j += 1
            count += j - (mid + 1)

        nums[l:r + 1] = sorted(nums[l:r + 1])

        return count

    return mergeSort(0, len(nums) - 1)
```
The algorithm uses a modified merge sort to solve the problem efficiently. It counts the number of reverse pairs during the merge process, compares the elements in the left subarray with those in the right subarray, and increments the count based on the condition `nums[i] > 2 * nums[j]`. The merge sort divides the array into smaller subarrays, which are recursively sorted and merged.

For each subarray, we use two pointers `i` and `j` to find out the number of reverse pairs that satisfy the condition `nums[i] > 2 * nums[j]`. When iterating through the left subarray with `i`, we move `j` from the right subarray until we find the first index that doesn't satisfy the condition or we reach the end of the right subarray. The difference between the current position of `j` and the starting position is the count of valid reverse pairs. To get the overall count, we sum up the count value from both the left and right subarrays and also add the count found during merging the subarrays.

Finally, we merge the sorted subarrays using built-in sort functions. The process is similar in all four languages: C++ uses `std::merge` and `std::copy`, Java uses `System.arraycopy`, Python uses list slicing with `sorted()`, and JavaScript uses `Array.prototype.sort()` and `Array.prototype.splice()`.

The time complexity of the algorithm is O(n log n), as it takes advantage of the merge sort structure.

## A solution in Javascript

```javascript
function reversePairs(nums) {
    function mergeSort(l, r) {
        if (l >= r) {
            return 0;
        }

        const mid = Math.floor((l + r) / 2);
        let count = mergeSort(l, mid) + mergeSort(mid + 1, r);
        let j = mid + 1;
        for (let i = l; i <= mid; i++) {
            while (j <= r && nums[i] > 2 * nums[j]) {
                j++;
            }
            count += j - (mid + 1);
        }

        const merged = nums.slice(l, r + 1).sort((a, b) => a - b);
        nums.splice(l, merged.length, ...merged);

        return count;
    }

    return mergeSort(0, nums.length - 1);
}
```
The algorithm uses a modified merge sort to solve the problem efficiently. It counts the number of reverse pairs during the merge process, compares the elements in the left subarray with those in the right subarray, and increments the count based on the condition `nums[i] > 2 * nums[j]`. The merge sort divides the array into smaller subarrays, which are recursively sorted and merged.

For each subarray, we use two pointers `i` and `j` to find out the number of reverse pairs that satisfy the condition `nums[i] > 2 * nums[j]`. When iterating through the left subarray with `i`, we move `j` from the right subarray until we find the first index that doesn't satisfy the condition or we reach the end of the right subarray. The difference between the current position of `j` and the starting position is the count of valid reverse pairs. To get the overall count, we sum up the count value from both the left and right subarrays and also add the count found during merging the subarrays.

Finally, we merge the sorted subarrays using built-in sort functions. The process is similar in all four languages: C++ uses `std::merge` and `std::copy`, Java uses `System.arraycopy`, Python uses list slicing with `sorted()`, and JavaScript uses `Array.prototype.sort()` and `Array.prototype.splice()`.

The time complexity of the algorithm is O(n log n), as it takes advantage of the merge sort structure.


# Target Sum

- slug: target-sum
- difficulty: Medium

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

You want to build an **expression** out of nums by adding one of the symbols `'+'` and `'-'` before each integer in nums and then concatenate all the integers.

*   For example, if `nums = [2, 1]`, you can add a `'+'` before `2` and a `'-'` before `1` and concatenate them to build the expression `"+2-1 "`.

Return the number of different **expressions** that you can build, which evaluates to `target`.

**Example 1:**

**Input:** nums = \[1,1,1,1,1\], target = 3
**Output:** 5
**Explanation:** There are 5 ways to assign symbols to make the sum of nums be target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

**Example 2:**

**Input:** nums = \[1\], target = 1
**Output:** 1

**Constraints:**

*   `1 <= nums.length <= 20`
*   `0 <= nums[i] <= 1000`
*   `0 <= sum(nums[i]) <= 1000`
*   `-1000 <= target <= 1000`

## A solution in Java

```java
public int findTargetSumWays(int[] nums, int target) {
    int sum = 0;
    for (int num : nums) sum += num;
    if (sum < target || (sum + target) % 2 != 0) return 0;
    int target_sum = (sum + target) / 2;
    int[] dp = new int[target_sum + 1];
    dp[0] = 1;
    for (int num : nums) {
        for (int j = target_sum; j >= num; j--) {
            dp[j] += dp[j - num];
        }
    }
    return dp[target_sum];
}
```
The problem can be reduced to a subset sum problem by doing some simple math. First, calculate the sum of all numbers in the array. If the sum of integers is less than the target value or the total sum with target value is odd, there are no possible combinations.

The required subset sum is (sum + target) / 2. We will use dynamic programming to count the number of subsets with the target sum. Initialize a DP array of size `target_sum + 1` and set the first value to 1 because the empty subset adds up to 0.

Iterate through the given numbers and for each number, update the values in DP array by enumerating the subsets with the i-th number included as follows:

1. If the current number is less than or equal to the target_sum, calculate the new value of the current subset by adding the value at a position shifted by the current number.

2. Store the new value and the current number in the DP array.

Return the greater number of different target-sum expressions saved in the DP array.

## A solution in C++

```cpp
#include <vector>

int findTargetSumWays(std::vector<int>& nums, int target) {
    int sum = 0;
    for (int num : nums) sum += num;
    if (sum < target || (sum + target) % 2 != 0) return 0;
    int target_sum = (sum + target) / 2;
    std::vector<int> dp(target_sum + 1, 0);
    dp[0] = 1;
    for (int num : nums) {
        for (int j = target_sum; j >= num; j--) {
            dp[j] += dp[j - num];
        }
    }
    return dp[target_sum];
}
```
The problem can be reduced to a subset sum problem by doing some simple math. First, calculate the sum of all numbers in the array. If the sum of integers is less than the target value or the total sum with target value is odd, there are no possible combinations.

The required subset sum is (sum + target) / 2. We will use dynamic programming to count the number of subsets with the target sum. Initialize a DP array of size `target_sum + 1` and set the first value to 1 because the empty subset adds up to 0.

Iterate through the given numbers and for each number, update the values in DP array by enumerating the subsets with the i-th number included as follows:

1. If the current number is less than or equal to the target_sum, calculate the new value of the current subset by adding the value at a position shifted by the current number.

2. Store the new value and the current number in the DP array.

Return the greater number of different target-sum expressions saved in the DP array.

## A solution in Python

```python
def findTargetSumWays(nums, target):
    total_sum = sum(nums)
    if total_sum < target or (total_sum + target) % 2 != 0:
        return 0
    target_sum = (total_sum + target) // 2
    dp = [0] * (target_sum + 1)
    dp[0] = 1
    for num in nums:
        for j in range(target_sum, num - 1, -1):
            dp[j] += dp[j - num]
    return dp[target_sum]
```
The problem can be reduced to a subset sum problem by doing some simple math. First, calculate the sum of all numbers in the array. If the sum of integers is less than the target value or the total sum with target value is odd, there are no possible combinations.

The required subset sum is (sum + target) / 2. We will use dynamic programming to count the number of subsets with the target sum. Initialize a DP array of size `target_sum + 1` and set the first value to 1 because the empty subset adds up to 0.

Iterate through the given numbers and for each number, update the values in DP array by enumerating the subsets with the i-th number included as follows:

1. If the current number is less than or equal to the target_sum, calculate the new value of the current subset by adding the value at a position shifted by the current number.

2. Store the new value and the current number in the DP array.

Return the greater number of different target-sum expressions saved in the DP array.

## A solution in Javascript

```javascript
function findTargetSumWays(nums, target) {
    let sum = nums.reduce((a, b) => a + b);
    if (sum < target || (sum + target) % 2 !== 0) return 0;
    let target_sum = (sum + target) >> 1;
    let dp = new Array(target_sum + 1).fill(0);
    dp[0] = 1;
    for (const num of nums) {
        for (let j = target_sum; j >= num; j--) {
            dp[j] += dp[j - num];
        }
    }
    return dp[target_sum];
}
```
The problem can be reduced to a subset sum problem by doing some simple math. First, calculate the sum of all numbers in the array. If the sum of integers is less than the target value or the total sum with target value is odd, there are no possible combinations.

The required subset sum is (sum + target) / 2. We will use dynamic programming to count the number of subsets with the target sum. Initialize a DP array of size `target_sum + 1` and set the first value to 1 because the empty subset adds up to 0.

Iterate through the given numbers and for each number, update the values in DP array by enumerating the subsets with the i-th number included as follows:

1. If the current number is less than or equal to the target_sum, calculate the new value of the current subset by adding the value at a position shifted by the current number.

2. Store the new value and the current number in the DP array.

Return the greater number of different target-sum expressions saved in the DP array.


# Teemo Attacking

- slug: teemo-attacking
- difficulty: Easy

Our hero Teemo is attacking an enemy Ashe with poison attacks! When Teemo attacks Ashe, Ashe gets poisoned for a exactly `duration` seconds. More formally, an attack at second `t` will mean Ashe is poisoned during the **inclusive** time interval `[t, t + duration - 1]`. If Teemo attacks again **before** the poison effect ends, the timer for it is **reset**, and the poison effect will end `duration` seconds after the new attack.

You are given a **non-decreasing** integer array `timeSeries`, where `timeSeries[i]` denotes that Teemo attacks Ashe at second `timeSeries[i]`, and an integer `duration`.

Return _the **total** number of seconds that Ashe is poisoned_.

**Example 1:**

**Input:** timeSeries = \[1,4\], duration = 2
**Output:** 4
**Explanation:** Teemo's attacks on Ashe go as follows:
- At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2.
- At second 4, Teemo attacks, and Ashe is poisoned for seconds 4 and 5.
Ashe is poisoned for seconds 1, 2, 4, and 5, which is 4 seconds in total.

**Example 2:**

**Input:** timeSeries = \[1,2\], duration = 2
**Output:** 3
**Explanation:** Teemo's attacks on Ashe go as follows:
- At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2.
- At second 2 however, Teemo attacks again and resets the poison timer. Ashe is poisoned for seconds 2 and 3.
Ashe is poisoned for seconds 1, 2, and 3, which is 3 seconds in total.

**Constraints:**

*   `1 <= timeSeries.length <= 104`
*   `0 <= timeSeries[i], duration <= 107`
*   `timeSeries` is sorted in **non-decreasing** order.

## A solution in Java

```java
public int findPoisonedDuration(int[] timeSeries, int duration) {
    if (timeSeries.length == 0) return 0;
    int total = 0;
    for (int i = 1; i < timeSeries.length; ++i) {
        total += Math.min(timeSeries[i] - timeSeries[i - 1], duration);
    }
    return total + duration;
}
```
Iterate through the `timeSeries` array and for each element, calculate the difference between the current element and the previous element. If the difference is less than `duration`, add that difference to the total time poisoned; otherwise, add the `duration` to the total time poisoned. In the end, add one more `duration` to the total to account for the last attack.

By doing this, we ensure that we only count the poisoned time without overlapping, since consecutive poisoned times will add up to the original duration.

## A solution in C++

```cpp
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
    if (timeSeries.empty()) return 0;
    int total = 0;
    for (int i = 1; i < timeSeries.size(); ++i) {
        total += min(timeSeries[i] - timeSeries[i - 1], duration);
    }
    return total + duration;
}
```
Iterate through the `timeSeries` array and for each element, calculate the difference between the current element and the previous element. If the difference is less than `duration`, add that difference to the total time poisoned; otherwise, add the `duration` to the total time poisoned. In the end, add one more `duration` to the total to account for the last attack.

By doing this, we ensure that we only count the poisoned time without overlapping, since consecutive poisoned times will add up to the original duration.

## A solution in Python

```python
def find_poisoned_duration(time_series, duration):
    if not time_series:
        return 0
    total = 0
    for i in range(1, len(time_series)):
        total += min(time_series[i] - time_series[i - 1], duration)
    return total + duration
```
Iterate through the `timeSeries` array and for each element, calculate the difference between the current element and the previous element. If the difference is less than `duration`, add that difference to the total time poisoned; otherwise, add the `duration` to the total time poisoned. In the end, add one more `duration` to the total to account for the last attack.

By doing this, we ensure that we only count the poisoned time without overlapping, since consecutive poisoned times will add up to the original duration.

## A solution in Javascript

```javascript
function findPoisonedDuration(timeSeries, duration) {
    if (timeSeries.length === 0) return 0;
    let total = 0;
    for (let i = 1; i < timeSeries.length; ++i) {
        total += Math.min(timeSeries[i] - timeSeries[i - 1], duration);
    }
    return total + duration;
}
```
Iterate through the `timeSeries` array and for each element, calculate the difference between the current element and the previous element. If the difference is less than `duration`, add that difference to the total time poisoned; otherwise, add the `duration` to the total time poisoned. In the end, add one more `duration` to the total to account for the last attack.

By doing this, we ensure that we only count the poisoned time without overlapping, since consecutive poisoned times will add up to the original duration.


# Next Greater Element I

- slug: next-greater-element-i
- difficulty: Easy

The **next greater element** of some element `x` in an array is the **first greater** element that is **to the right** of `x` in the same array.

You are given two **distinct 0-indexed** integer arrays `nums1` and `nums2`, where `nums1` is a subset of `nums2`.

For each `0 <= i < nums1.length`, find the index `j` such that `nums1[i] == nums2[j]` and determine the **next greater element** of `nums2[j]` in `nums2`. If there is no next greater element, then the answer for this query is `-1`.

Return _an array_ `ans` _of length_ `nums1.length` _such that_ `ans[i]` _is the **next greater element** as described above._

**Example 1:**

**Input:** nums1 = \[4,1,2\], nums2 = \[1,3,4,2\]
**Output:** \[-1,3,-1\]
**Explanation:** The next greater element for each value of nums1 is as follows:
- 4 is underlined in nums2 = \[1,3,4,2\]. There is no next greater element, so the answer is -1.
- 1 is underlined in nums2 = \[1,3,4,2\]. The next greater element is 3.
- 2 is underlined in nums2 = \[1,3,4,2\]. There is no next greater element, so the answer is -1.

**Example 2:**

**Input:** nums1 = \[2,4\], nums2 = \[1,2,3,4\]
**Output:** \[3,-1\]
**Explanation:** The next greater element for each value of nums1 is as follows:
- 2 is underlined in nums2 = \[1,2,3,4\]. The next greater element is 3.
- 4 is underlined in nums2 = \[1,2,3,4\]. There is no next greater element, so the answer is -1.

**Constraints:**

*   `1 <= nums1.length <= nums2.length <= 1000`
*   `0 <= nums1[i], nums2[i] <= 104`
*   All integers in `nums1` and `nums2` are **unique**.
*   All the integers of `nums1` also appear in `nums2`.

**Follow up:** Could you find an `O(nums1.length + nums2.length)` solution?

## A solution in Java

```java
import java.util.HashMap;
import java.util.Stack;

public int[] nextGreaterElement(int[] nums1, int[] nums2) {
    HashMap<Integer, Integer> nextGreater = new HashMap<>();
    Stack<Integer> stack = new Stack<>();

    for (int num : nums2) {
        while (!stack.isEmpty() && stack.peek() < num) {
            nextGreater.put(stack.pop(), num);
        }
        stack.push(num);
    }

    int[] result = new int[nums1.length];
    for (int i = 0; i < nums1.length; i++) {
        result[i] = nextGreater.getOrDefault(nums1[i], -1);
    }

    return result;
}
```
The algorithm uses a stack, following these steps:
1. Initialize an empty stack.
2. Iterate through nums2 elements:
   a. While the stack is not empty and the top of the stack is less than the current nums2 element, add the next greater element of the top of the stack as the current nums2 element and pop it.
   b. Push the current nums2 element into the stack.
3. For every element in nums1, get the next greater element found in step 2 or -1 if no such element was found.
4. Return the result array.

The key point is using the stack to keep track of the previous elements that still need to find their next greater element while iterating nums2 in a single pass. This ensures that the algorithm runs in linear O(n) time complexity.

## A solution in C++

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

std::vector<int> nextGreaterElement(std::vector<int>& nums1, std::vector<int>& nums2) {
    std::unordered_map<int, int> nextGreater;
    std::stack<int> stk;

    for (int num : nums2) {
        while (!stk.empty() && stk.top() < num) {
            nextGreater[stk.top()] = num;
            stk.pop();
        }
        stk.push(num);
    }

    std::vector<int> result(nums1.size());
    for (size_t i = 0; i < nums1.size(); ++i) {
        result[i] = nextGreater.count(nums1[i]) ? nextGreater[nums1[i]] : -1;
    }

    return result;
}
```
The algorithm uses a stack, following these steps:
1. Initialize an empty stack.
2. Iterate through nums2 elements:
   a. While the stack is not empty and the top of the stack is less than the current nums2 element, add the next greater element of the top of the stack as the current nums2 element and pop it.
   b. Push the current nums2 element into the stack.
3. For every element in nums1, get the next greater element found in step 2 or -1 if no such element was found.
4. Return the result array.

The key point is using the stack to keep track of the previous elements that still need to find their next greater element while iterating nums2 in a single pass. This ensures that the algorithm runs in linear O(n) time complexity.

## A solution in Python

```python
def next_greater_element(nums1, nums2):
    next_greater = {}
    stack = []

    for num in nums2:
        while stack and stack[-1] < num:
            next_greater[stack.pop()] = num
        stack.append(num)

    return [next_greater.get(n, -1) for n in nums1]
```
The algorithm uses a stack, following these steps:
1. Initialize an empty stack.
2. Iterate through nums2 elements:
   a. While the stack is not empty and the top of the stack is less than the current nums2 element, add the next greater element of the top of the stack as the current nums2 element and pop it.
   b. Push the current nums2 element into the stack.
3. For every element in nums1, get the next greater element found in step 2 or -1 if no such element was found.
4. Return the result array.

The key point is using the stack to keep track of the previous elements that still need to find their next greater element while iterating nums2 in a single pass. This ensures that the algorithm runs in linear O(n) time complexity.

## A solution in Javascript

```javascript
function nextGreaterElement(nums1, nums2) {
    const nextGreater = new Map();
    const stack = [];

    nums2.forEach(num => {
        while (stack.length && stack[stack.length - 1] < num) {
            nextGreater.set(stack.pop(), num);
        }
        stack.push(num);
    });

    return nums1.map(n => nextGreater.get(n) || -1);
}
```
The algorithm uses a stack, following these steps:
1. Initialize an empty stack.
2. Iterate through nums2 elements:
   a. While the stack is not empty and the top of the stack is less than the current nums2 element, add the next greater element of the top of the stack as the current nums2 element and pop it.
   b. Push the current nums2 element into the stack.
3. For every element in nums1, get the next greater element found in step 2 or -1 if no such element was found.
4. Return the result array.

The key point is using the stack to keep track of the previous elements that still need to find their next greater element while iterating nums2 in a single pass. This ensures that the algorithm runs in linear O(n) time complexity.


# Random Point in Non-overlapping Rectangles

- slug: random-point-in-non-overlapping-rectangles
- difficulty: Medium

You are given an array of non-overlapping axis-aligned rectangles `rects` where `rects[i] = [ai, bi, xi, yi]` indicates that `(ai, bi)` is the bottom-left corner point of the `ith` rectangle and `(xi, yi)` is the top-right corner point of the `ith` rectangle. Design an algorithm to pick a random integer point inside the space covered by one of the given rectangles. A point on the perimeter of a rectangle is included in the space covered by the rectangle.

Any integer point inside the space covered by one of the given rectangles should be equally likely to be returned.

**Note** that an integer point is a point that has integer coordinates.

Implement the `Solution` class:

*   `Solution(int[][] rects)` Initializes the object with the given rectangles `rects`.
*   `int[] pick()` Returns a random integer point `[u, v]` inside the space covered by one of the given rectangles.

**Example 1:**

**Input**
\[ "Solution ",  "pick ",  "pick ",  "pick ",  "pick ",  "pick "\]
\[\[\[\[-2, -2, 1, 1\], \[2, 2, 4, 6\]\]\], \[\], \[\], \[\], \[\], \[\]\]
**Output**
\[null, \[1, -2\], \[1, -1\], \[-1, -2\], \[-2, -2\], \[0, 0\]\]

**Explanation**
Solution solution = new Solution(\[\[-2, -2, 1, 1\], \[2, 2, 4, 6\]\]);
solution.pick(); // return \[1, -2\]
solution.pick(); // return \[1, -1\]
solution.pick(); // return \[-1, -2\]
solution.pick(); // return \[-2, -2\]
solution.pick(); // return \[0, 0\]

**Constraints:**

*   `1 <= rects.length <= 100`
*   `rects[i].length == 4`
*   `-109 <= ai < xi <= 109`
*   `-109 <= bi < yi <= 109`
*   `xi - ai <= 2000`
*   `yi - bi <= 2000`
*   All the rectangles do not overlap.
*   At most `104` calls will be made to `pick`.

## A solution in Java

```java
import java.util.Random;
import java.util.List;

class Solution {
    int[][] rects;
    int[] areas;
    int totalArea;
    Random random;

    public Solution(int[][] rects) {
        this.rects = rects;
        this.areas = new int[rects.length];
        this.totalArea = 0;
        this.random = new Random();

        for (int i = 0; i < rects.length; i++) {
            int area = (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1);
            areas[i] = area;
            totalArea += area;
        }
    }

    public int[] pick() {
        int rnd = random.nextInt(totalArea);

        int idx = 0;
        while (rnd >= areas[idx]) {
            rnd -= areas[idx];
            idx++;
        }

        int x = rects[idx][0] + random.nextInt(rects[idx][2] - rects[idx][0] + 1);
        int y = rects[idx][1] + random.nextInt(rects[idx][3] - rects[idx][1] + 1);

        return new int[] {x, y};
    }
}
```
The algorithm consists of initializing a `Solution` object by storing the `rects` and calculating the area of each rectangle. The `areas` are stored, and the `total_area` is calculated by summing up all the rectangle areas.

When the `pick()` function is called, a random value, `rnd`, is generated within the range `[0, total_area-1]`. The index `idx` of the rectangle containing the point is found, adding the areas until `rnd` reaches a value less than the area of the rectangle with index `idx` (that means the rectangle at idx is the one we need).

Next, two random integer coordinates, `x` and `y`, are generated within the range of the selected rectangle, and the point `[x, y]` is returned.

This ensures that each integer point inside the space covered by one of the given rectangles will be equally likely to be returned.

## A solution in C++

```cpp
#include <random>
#include <vector>

class Solution {
    std::vector<std::vector<int>> rects;
    std::vector<int> areas;
    int total_area;

public:
    Solution(std::vector<std::vector<int>>& rects) :
        rects(rects),
        areas(rects.size()),
        total_area(0) {
        for (int i = 0; i < rects.size(); ++i) {
            int area = (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1);
            areas[i] = area;
            total_area += area;
        }
    }

    std::vector<int> pick() {
        std::default_random_engine generator;
        std::uniform_int_distribution<int> distribution(0, total_area - 1);
        int rnd = distribution(generator);

        int idx = 0;
        while (rnd >= areas[idx]) {
            rnd -= areas[idx];
            idx++;
        }

        std::uniform_int_distribution<int> x_distribution(rects[idx][0], rects[idx][2]);
        std::uniform_int_distribution<int> y_distribution(rects[idx][1], rects[idx][3]);

        return {
            x_distribution(generator),
            y_distribution(generator)
        };
    }
};
```
The algorithm consists of initializing a `Solution` object by storing the `rects` and calculating the area of each rectangle. The `areas` are stored, and the `total_area` is calculated by summing up all the rectangle areas.

When the `pick()` function is called, a random value, `rnd`, is generated within the range `[0, total_area-1]`. The index `idx` of the rectangle containing the point is found, adding the areas until `rnd` reaches a value less than the area of the rectangle with index `idx` (that means the rectangle at idx is the one we need).

Next, two random integer coordinates, `x` and `y`, are generated within the range of the selected rectangle, and the point `[x, y]` is returned.

This ensures that each integer point inside the space covered by one of the given rectangles will be equally likely to be returned.

## A solution in Python

```python
import random
from typing import List

class Solution:
    def __init__(self, rects: List[List[int]]):
        self.rects = rects
        self.areas = [0] * len(rects)
        self.total_area = 0

        for i, rect in enumerate(rects):
            area = (rect[2] - rect[0] + 1) * (rect[3] - rect[1] + 1)
            self.areas[i] = area
            self.total_area += area

    def pick(self) -> List[int]:
        rnd = random.randint(0, self.total_area - 1)
        idx = 0
        while rnd >= self.areas[idx]:
            rnd -= self.areas[idx]
            idx += 1

        x = random.randint(self.rects[idx][0], self.rects[idx][2])
        y = random.randint(self.rects[idx][1], self.rects[idx][3])

        return [x, y]
```
The algorithm consists of initializing a `Solution` object by storing the `rects` and calculating the area of each rectangle. The `areas` are stored, and the `total_area` is calculated by summing up all the rectangle areas.

When the `pick()` function is called, a random value, `rnd`, is generated within the range `[0, total_area-1]`. The index `idx` of the rectangle containing the point is found, adding the areas until `rnd` reaches a value less than the area of the rectangle with index `idx` (that means the rectangle at idx is the one we need).

Next, two random integer coordinates, `x` and `y`, are generated within the range of the selected rectangle, and the point `[x, y]` is returned.

This ensures that each integer point inside the space covered by one of the given rectangles will be equally likely to be returned.

## A solution in Javascript

```javascript
class Solution {
    constructor(rects) {
        this.rects = rects;
        this.areas = new Array(rects.length);
        this.totalArea = 0;

        for (let i = 0; i < rects.length; i++) {
            const area = (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1);
            this.areas[i] = area;
            this.totalArea += area;
        }
    }

    pick() {
        let rnd = Math.floor(Math.random() * this.totalArea);
        let idx = 0;

        while (rnd >= this.areas[idx]) {
            rnd -= this.areas[idx];
            idx++;
        }

        const x = this.rects[idx][0] + Math.floor(Math.random() * (this.rects[idx][2] - this.rects[idx][0] + 1));
        const y = this.rects[idx][1] + Math.floor(Math.random() * (this.rects[idx][3] - this.rects[idx][1] + 1));

        return [x, y];
    }
}
```
The algorithm consists of initializing a `Solution` object by storing the `rects` and calculating the area of each rectangle. The `areas` are stored, and the `total_area` is calculated by summing up all the rectangle areas.

When the `pick()` function is called, a random value, `rnd`, is generated within the range `[0, total_area-1]`. The index `idx` of the rectangle containing the point is found, adding the areas until `rnd` reaches a value less than the area of the rectangle with index `idx` (that means the rectangle at idx is the one we need).

Next, two random integer coordinates, `x` and `y`, are generated within the range of the selected rectangle, and the point `[x, y]` is returned.

This ensures that each integer point inside the space covered by one of the given rectangles will be equally likely to be returned.


# Diagonal Traverse

- slug: diagonal-traverse
- difficulty: Medium

Given an `m x n` matrix `mat`, return _an array of all the elements of the array in a diagonal order_.

**Example 1:**

**Input:** mat = \[\[1,2,3\],\[4,5,6\],\[7,8,9\]\]
**Output:** \[1,2,4,7,5,3,6,8,9\]

**Example 2:**

**Input:** mat = \[\[1,2\],\[3,4\]\]
**Output:** \[1,2,3,4\]

**Constraints:**

*   `m == mat.length`
*   `n == mat[i].length`
*   `1 <= m, n <= 104`
*   `1 <= m * n <= 104`
*   `-105 <= mat[i][j] <= 105`

## A solution in Java

```java
import java.util.Arrays;

public int[] findDiagonalOrder(int[][] mat) {
    int m = mat.length;
    int n = mat[0].length;
    int[] result = new int[m * n];
    int row = 0, col = 0;
    for (int i = 0; i < m * n; i++) {
        result[i] = mat[row][col];
        if ((row + col) % 2 == 0) {
            if (col == n - 1) {
                row++;
            } else if (row == 0) {
                col++;
            } else {
                row--;
                col++;
            }
        } else {
            if (row == m - 1) {
                col++;
            } else if (col == 0) {
                row++;
            } else {
                row++;
                col--;
            }
        }
    }
    return result;
}
```
The algorithm iterates through each element of the matrix in a diagonal order. We set up a double loop that runs through the total number of elements in the matrix (m * n). We keep track of the current row and column while iterating.

We use a conditional statement to check if the sum of the current row and column is even, which means we need to move up diagonally to the right. If we are at the right edge, we move down one row. If we are at the top edge, we move right one column. Otherwise, we move up diagonally (row - 1, col + 1).

If the sum of the current row and column is odd, it means we need to move down diagonally to the left. If we are at the bottom edge, we move right one column. If we are at the left edge, we move down one row. Otherwise, we move down diagonally (row + 1, col - 1).

## A solution in C++

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

vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
    int m = mat.size();
    int n = mat[0].size();
    vector<int> result(m * n);
    int row = 0, col = 0;
    for (int i = 0; i < m * n; i++) {
        result[i] = mat[row][col];
        if ((row + col) % 2 == 0) {
            if (col == n - 1) {
                row++;
            } else if (row == 0) {
                col++;
            } else {
                row--;
                col++;
            }
        } else {
            if (row == m - 1) {
                col++;
            } else if (col == 0) {
                row++;
            } else {
                row++;
                col--;
            }
        }
    }
    return result;
}
```
The algorithm iterates through each element of the matrix in a diagonal order. We set up a double loop that runs through the total number of elements in the matrix (m * n). We keep track of the current row and column while iterating.

We use a conditional statement to check if the sum of the current row and column is even, which means we need to move up diagonally to the right. If we are at the right edge, we move down one row. If we are at the top edge, we move right one column. Otherwise, we move up diagonally (row - 1, col + 1).

If the sum of the current row and column is odd, it means we need to move down diagonally to the left. If we are at the bottom edge, we move right one column. If we are at the left edge, we move down one row. Otherwise, we move down diagonally (row + 1, col - 1).

## A solution in Python

```python
from typing import List

def findDiagonalOrder(mat: List[List[int]]) -> List[int]:
    m, n = len(mat), len(mat[0])
    result = [0] * (m * n)
    row, col = 0, 0
    for i in range(m * n):
        result[i] = mat[row][col]
        if (row + col) % 2 == 0:
            if col == n - 1:
                row += 1
            elif row == 0:
                col += 1
            else:
                row -= 1
                col += 1
        else:
            if row == m - 1:
                col += 1
            elif col == 0:
                row += 1
            else:
                row += 1
                col -= 1
    return result
```
The algorithm iterates through each element of the matrix in a diagonal order. We set up a double loop that runs through the total number of elements in the matrix (m * n). We keep track of the current row and column while iterating.

We use a conditional statement to check if the sum of the current row and column is even, which means we need to move up diagonally to the right. If we are at the right edge, we move down one row. If we are at the top edge, we move right one column. Otherwise, we move up diagonally (row - 1, col + 1).

If the sum of the current row and column is odd, it means we need to move down diagonally to the left. If we are at the bottom edge, we move right one column. If we are at the left edge, we move down one row. Otherwise, we move down diagonally (row + 1, col - 1).

## A solution in Javascript

```javascript
function findDiagonalOrder(mat) {
    const m = mat.length;
    const n = mat[0].length;
    const result = new Array(m * n);
    let row = 0, col = 0;
    for (let i = 0; i < m * n; i++) {
        result[i] = mat[row][col];
        if ((row + col) % 2 === 0) {
            if (col === n - 1) {
                row++;
            } else if (row === 0) {
                col++;
            } else {
                row--;
                col++;
            }
        } else {
            if (row === m - 1) {
                col++;
            } else if (col === 0) {
                row++;
            } else {
                row++;
                col--;
            }
        }
    }
    return result;
}
```
The algorithm iterates through each element of the matrix in a diagonal order. We set up a double loop that runs through the total number of elements in the matrix (m * n). We keep track of the current row and column while iterating.

We use a conditional statement to check if the sum of the current row and column is even, which means we need to move up diagonally to the right. If we are at the right edge, we move down one row. If we are at the top edge, we move right one column. Otherwise, we move up diagonally (row - 1, col + 1).

If the sum of the current row and column is odd, it means we need to move down diagonally to the left. If we are at the bottom edge, we move right one column. If we are at the left edge, we move down one row. Otherwise, we move down diagonally (row + 1, col - 1).


# The Maze III

- slug: the-maze-iii
- difficulty: Hard

There is a ball in a `maze` with empty spaces (represented as `0`) and walls (represented as `1`). The ball can go through the empty spaces by rolling **up, down, left or right**, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. There is also a hole in this maze. The ball will drop into the hole if it rolls onto the hole.

Given the `m x n` `maze`, the ball's position `ball` and the hole's position `hole`, where `ball = [ballrow, ballcol]` and `hole = [holerow, holecol]`, return _a string_ `instructions` _of all the instructions that the ball should follow to drop in the hole with the **shortest distance** possible_. If there are multiple valid instructions, return the **lexicographically minimum** one. If the ball can't drop in the hole, return `"impossible "`.

If there is a way for the ball to drop in the hole, the answer `instructions` should contain the characters `'u'` (i.e., up), `'d'` (i.e., down), `'l'` (i.e., left), and `'r'` (i.e., right).

The **distance** is the number of **empty spaces** traveled by the ball from the start position (excluded) to the destination (included).

You may assume that **the borders of the maze are all walls** (see examples).

**Example 1:**

**Input:** maze = \[\[0,0,0,0,0\],\[1,1,0,0,1\],\[0,0,0,0,0\],\[0,1,0,0,1\],\[0,1,0,0,0\]\], ball = \[4,3\], hole = \[0,1\]
**Output:**  "lul "
**Explanation:** There are two shortest ways for the ball to drop into the hole.
The first way is left -> up -> left, represented by  "lul ".
The second way is up -> left, represented by 'ul'.
Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is  "lul ".

**Example 2:**

**Input:** maze = \[\[0,0,0,0,0\],\[1,1,0,0,1\],\[0,0,0,0,0\],\[0,1,0,0,1\],\[0,1,0,0,0\]\], ball = \[4,3\], hole = \[3,0\]
**Output:**  "impossible "
**Explanation:** The ball cannot reach the hole.

**Example 3:**

**Input:** maze = \[\[0,0,0,0,0,0,0\],\[0,0,1,0,0,1,0\],\[0,0,0,0,1,0,0\],\[0,0,0,0,0,0,1\]\], ball = \[0,4\], hole = \[3,5\]
**Output:**  "dldr "

**Constraints:**

*   `m == maze.length`
*   `n == maze[i].length`
*   `1 <= m, n <= 100`
*   `maze[i][j]` is `0` or `1`.
*   `ball.length == 2`
*   `hole.length == 2`
*   `0 <= ballrow, holerow <= m`
*   `0 <= ballcol, holecol <= n`
*   Both the ball and the hole exist in an empty space, and they will not be in the same position initially.
*   The maze contains **at least 2 empty spaces**.

## A solution in Java

```java
import java.util.*;

class Solution {
    public String findShortestWay(int[][] maze, int[] ball, int[] hole) {
        int m = maze.length, n = maze[0].length;
        int[][] dist = new int[m][n];
        for (int i = 0; i < m; ++i) Arrays.fill(dist[i], Integer.MAX_VALUE);
        String[] dirs = {"d", "l", "r", "u"};
        int[][] dirs_vector = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};
        dist[ball[0]][ball[1]] = 0;
        PriorityQueue<int[]> pq = new PriorityQueue<>((p1, p2) -> p1[0] != p2[0] ? p1[0] - p2[0] : p1[1] - p2[1]);
        pq.offer(new int[]{0, 0});

        while (!pq.isEmpty()) {
            int cur_dist = pq.peek()[0], cur_d = pq.peek()[1];
            String cur_path = pq.poll()[2];
            int x = ball[0], y = ball[1];
            for (char c : cur_path.toCharArray()) {
                if (c == 'd') x += dirs_vector[0][0];
                if (c == 'l') y += dirs_vector[1][1];
                if (c == 'r') y += dirs_vector[2][1];
                if (c == 'u') x += dirs_vector[3][0];
            }
            if (x == hole[0] && y == hole[1]) return cur_path;

            for (int k = 0; k < 4; ++k) {
                int dist_move = 0, r = x, c = y;
                while (r >= 0 && r < m && c >= 0 && c < n && maze[r][c] == 0 && (r != hole[0] || c != hole[1])) {
                    r += dirs_vector[k][0];
                    c += dirs_vector[k][1];
                    ++dist_move;
                }
                r -= dirs_vector[k][0];
                c -= dirs_vector[k][1];
                --dist_move;

                if (dist[x][y] + dist_move < dist[r][c]) {
                    dist[r][c] = dist[x][y] + dist_move;
                    pq.offer(new int[]{cur_dist + dist_move, cur_d * 4 + k, cur_path + dirs[k]});
                }
            }
        }

        return "impossible";
    }
}
```
The algorithm used to solve this problem is Dijkstra's shortest path algorithm with a priority queue. For each location in the maze, we store the minimal distance to reach that location along with the lexicographically smallest instructions.

We start at the ball's position and then simulate rolling it in all four directions. While rolling, we make sure that we don't go past the walls of the maze or hit a random wall, and we stop when the ball hits the hole. We update the distance and path to the location where the ball stops, only if it's shorter than the current recorded path for that location.

Since we're using a priority queue, we will always process the shortest distance location first (in case of a tie, we process the lexicographically smaller path first). This guarantees that if we reach the hole while processing a location, the resulting path will be the shortest and lexicographically smallest.

If we have visited all possible locations and don't find the hole, we return "impossible" as the answer.

The time complexity is O(m * n * log(m * n)) where m and n are the row and column size of the maze. The space complexity is O(m * n) since we are storing the distance and path for all the locations in the maze.

## A solution in C++

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

using namespace std;

class Solution {
public:
    string findShortestWay(vector<vector<int>>& maze, vector<int>& ball, vector<int>& hole) {
        int m = maze.size(), n = maze[0].size();
        vector<vector<int>> dist(m, vector<int>(n, INT_MAX));
        vector<string> dirs = {"d", "l", "r", "u"};
        vector<vector<int>> dirs_vector = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};
        string res = "";
        dist[ball[0]][ball[1]] = 0;
        auto cmp = [&](const auto& p1, const auto& p2){
            return p1.first > p2.first || (p1.first == p2.first && p1.second > p2.second);
        };
        priority_queue<pair<int, string>, vector<pair<int, string>>, decltype(cmp)> pq(cmp);
        pq.push({0, ""});

        while (!pq.empty()) {
            int cur_dist = pq.top().first;
            string cur_path = pq.top().second;
            int x = ball[0], y = ball[1];
            for (char c : cur_path) {
                if (c == 'd') x += dirs_vector[0][0];
                if (c == 'l') y += dirs_vector[1][1];
                if (c == 'r') y += dirs_vector[2][1];
                if (c == 'u') x += dirs_vector[3][0];
            }
            pq.pop();
            if (x == hole[0] && y == hole[1]) return cur_path;

            for (int k = 0; k < 4; ++k) {
                int dist_move = 0, r = x, c = y;
                while (r >= 0 && r < m && c >= 0 && c < n && maze[r][c] == 0 && (r != hole[0] || c != hole[1])) {
                    r += dirs_vector[k][0];
                    c += dirs_vector[k][1];
                    ++dist_move;
                }
                r -= dirs_vector[k][0];
                c -= dirs_vector[k][1];
                --dist_move;

                if (dist[x][y] + dist_move < dist[r][c]) {
                    dist[r][c] = dist[x][y] + dist_move;
                    pq.push({cur_dist + dist_move, cur_path + dirs[k]});
                }
            }
        }

        return "impossible";
    }
};
```
The algorithm used to solve this problem is Dijkstra's shortest path algorithm with a priority queue. For each location in the maze, we store the minimal distance to reach that location along with the lexicographically smallest instructions.

We start at the ball's position and then simulate rolling it in all four directions. While rolling, we make sure that we don't go past the walls of the maze or hit a random wall, and we stop when the ball hits the hole. We update the distance and path to the location where the ball stops, only if it's shorter than the current recorded path for that location.

Since we're using a priority queue, we will always process the shortest distance location first (in case of a tie, we process the lexicographically smaller path first). This guarantees that if we reach the hole while processing a location, the resulting path will be the shortest and lexicographically smallest.

If we have visited all possible locations and don't find the hole, we return "impossible" as the answer.

The time complexity is O(m * n * log(m * n)) where m and n are the row and column size of the maze. The space complexity is O(m * n) since we are storing the distance and path for all the locations in the maze.

## A solution in Python

```python
from heapq import heappush, heappop

class Solution:
    def findShortestWay(self, maze: List[List[int]], ball: List[int], hole: List[int]) -> str:
        m, n = len(maze), len(maze[0])
        dist = [[float("inf")] * n for _ in range(m)]
        dirs = ["d", "l", "r", "u"]
        dirs_vector = [[1, 0], [0, -1], [0, 1], [-1, 0]]
        dist[ball[0]][ball[1]] = 0
        pq = [(0, "", ball[0], ball[1])]

        while pq:
            cur_dist, cur_path, x, y = heappop(pq)
            if [x, y] == hole:
                return cur_path

            for k, d in enumerate(dirs):
                dist_move, r, c = 0, x + dirs_vector[k][0], y + dirs_vector[k][1]
                while 0 <= r < m and 0 <= c < n and maze[r][c] == 0 and [r, c] != hole:
                    r += dirs_vector[k][0]
                    c += dirs_vector[k][1]
                    dist_move += 1
                r -= dirs_vector[k][0]
                c -= dirs_vector[k][1]
                dist_move -= 1

                if dist[x][y] + dist_move < dist[r][c]:
                    dist[r][c] = dist[x][y] + dist_move
                    heappush(pq, (cur_dist + dist_move, cur_path + d, r, c))

        return "impossible"
```
The algorithm used to solve this problem is Dijkstra's shortest path algorithm with a priority queue. For each location in the maze, we store the minimal distance to reach that location along with the lexicographically smallest instructions.

We start at the ball's position and then simulate rolling it in all four directions. While rolling, we make sure that we don't go past the walls of the maze or hit a random wall, and we stop when the ball hits the hole. We update the distance and path to the location where the ball stops, only if it's shorter than the current recorded path for that location.

Since we're using a priority queue, we will always process the shortest distance location first (in case of a tie, we process the lexicographically smaller path first). This guarantees that if we reach the hole while processing a location, the resulting path will be the shortest and lexicographically smallest.

If we have visited all possible locations and don't find the hole, we return "impossible" as the answer.

The time complexity is O(m * n * log(m * n)) where m and n are the row and column size of the maze. The space complexity is O(m * n) since we are storing the distance and path for all the locations in the maze.

## A solution in Javascript

```javascript
class Solution {
    findShortestWay(maze, ball, hole) {
        const m = maze.length, n = maze[0].length;
        const dist = Array.from({ length: m }, () => Array(n).fill(Infinity));
        const dirs = ["d", "l", "r", "u"];
        const dirs_vector = [[1, 0], [0, -1], [0, 1], [-1, 0]];
        dist[ball[0]][ball[1]] = 0;
        const pq = [[0, "", ball[0], ball[1]]];

        while (pq.length > 0) {
            pq.sort((a, b) => a[0] - b[0] || a[1].localeCompare(b[1]));
            const [cur_dist, cur_path, x, y] = pq.shift();
            if (x === hole[0] && y === hole[1]) return cur_path;

            for (let k = 0; k < 4; ++k) {
                let dist_move = 0, r = x, c = y;
                while (r >= 0 && r < m && c >= 0 && c < n && maze[r][c] === 0 && (r !== hole[0] || c !== hole[1])) {
                    r += dirs_vector[k][0];
                    c += dirs_vector[k][1];
                    ++dist_move;
                }
                r -= dirs_vector[k][0];
                c -= dirs_vector[k][1];
                --dist_move;

                if (dist[x][y] + dist_move < dist[r][c]) {
                    dist[r][c] = dist[x][y] + dist_move;
                    pq.push([cur_dist + dist_move, cur_path + dirs[k], r, c]);
                }
            }
        }

        return "impossible";
    }
}
```
The algorithm used to solve this problem is Dijkstra's shortest path algorithm with a priority queue. For each location in the maze, we store the minimal distance to reach that location along with the lexicographically smallest instructions.

We start at the ball's position and then simulate rolling it in all four directions. While rolling, we make sure that we don't go past the walls of the maze or hit a random wall, and we stop when the ball hits the hole. We update the distance and path to the location where the ball stops, only if it's shorter than the current recorded path for that location.

Since we're using a priority queue, we will always process the shortest distance location first (in case of a tie, we process the lexicographically smaller path first). This guarantees that if we reach the hole while processing a location, the resulting path will be the shortest and lexicographically smallest.

If we have visited all possible locations and don't find the hole, we return "impossible" as the answer.

The time complexity is O(m * n * log(m * n)) where m and n are the row and column size of the maze. The space complexity is O(m * n) since we are storing the distance and path for all the locations in the maze.


# Keyboard Row

- slug: keyboard-row
- difficulty: Easy

Given an array of strings `words`, return _the words that can be typed using letters of the alphabet on only one row of American keyboard like the image below_.

In the **American keyboard**:

*   the first row consists of the characters `"qwertyuiop "`,
*   the second row consists of the characters `"asdfghjkl "`, and
*   the third row consists of the characters `"zxcvbnm "`.

**Example 1:**

**Input:** words = \[ "Hello ", "Alaska ", "Dad ", "Peace "\]
**Output:** \[ "Alaska ", "Dad "\]

**Example 2:**

**Input:** words = \[ "omk "\]
**Output:** \[\]

**Example 3:**

**Input:** words = \[ "adsdf ", "sfd "\]
**Output:** \[ "adsdf ", "sfd "\]

**Constraints:**

*   `1 <= words.length <= 20`
*   `1 <= words[i].length <= 100`
*   `words[i]` consists of English letters (both lowercase and uppercase).

## A solution in Java

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

public class Solution {
    public String[] findWords(String[] words) {
        HashSet<Character>[] rows = new HashSet[] {
            new HashSet<Character>() {{
                add('q'); add('w'); add('e'); add('r'); add('t');
                add('y'); add('u'); add('i'); add('o'); add('p');
            }},
            new HashSet<Character>() {{
                add('a'); add('s'); add('d'); add('f'); add('g');
                add('h'); add('j'); add('k'); add('l');
            }},
            new HashSet<Character>() {{
                add('z'); add('x'); add('c'); add('v'); add('b');
                add('n'); add('m');
            }}
        };
        List<String> res = new ArrayList<>();

        for (String word : words) {
            int row = -1;
            for (int i = 0; i < 3; i++) {
                if (rows[i].contains(Character.toLowerCase(word.charAt(0)))) {
                    row = i;
                    break;
                }
            }

            boolean isOneRow = true;
            for (char letter : word.toCharArray()) {
                if (!rows[row].contains(Character.toLowerCase(letter))) {
                    isOneRow = false;
                    break;
                }
            }

            if (isOneRow)
                res.add(word);
        }

        return res.toArray(new String[0]);
    }
}
```
1. Create an array of sets representing each row of the American keyboard. Include both uppercase and lowercase letters in the set.
2. Initialize an empty result list.
3. Loop through the input words array.
4. Determine the row of the first character of the current word by checking which of the 3 rows contains it.
5. Check if all the characters in the current word belong to the same row found in step 4. If yes, append the word to the result list.
6. Once the loop is done, return the result list.

## A solution in C++

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

vector<string> findWords(vector<string>& words) {
    vector<unordered_set<char>> rows = {
        {'q','w','e','r','t','y','u','i','o','p'},
        {'a','s','d','f','g','h','j','k','l'},
        {'z','x','c','v','b','n','m'}
    };
    vector<string> result;

    for (const auto& word : words) {
        int row = -1;
        for (int i = 0; i < 3; ++i) {
            if (rows[i].count(tolower(word[0])) > 0) {
                row = i;
                break;
            }
        }

        bool isOneRow = true;
        for (const auto& letter : word) {
            if (rows[row].count(tolower(letter)) == 0) {
                isOneRow = false;
                break;
            }
        }

        if (isOneRow) {
            result.push_back(word);
        }
    }

    return result;
}
```
1. Create an array of sets representing each row of the American keyboard. Include both uppercase and lowercase letters in the set.
2. Initialize an empty result list.
3. Loop through the input words array.
4. Determine the row of the first character of the current word by checking which of the 3 rows contains it.
5. Check if all the characters in the current word belong to the same row found in step 4. If yes, append the word to the result list.
6. Once the loop is done, return the result list.

## A solution in Python

```python
def find_words(words):
    rows = [
        set("qwertyuiopQWERTYUIOP"),
        set("asdfghjklASDFGHJKL"),
        set("zxcvbnmZXCVBNM")
    ]
    res = []

    for word in words:
        row = -1
        for i in range(3):
            if word[0] in rows[i]:
                row = i
                break

        if all(c in rows[row] for c in word):
            res.append(word)

    return res
```
1. Create an array of sets representing each row of the American keyboard. Include both uppercase and lowercase letters in the set.
2. Initialize an empty result list.
3. Loop through the input words array.
4. Determine the row of the first character of the current word by checking which of the 3 rows contains it.
5. Check if all the characters in the current word belong to the same row found in step 4. If yes, append the word to the result list.
6. Once the loop is done, return the result list.

## A solution in Javascript

```javascript
function findWords(words) {
    const rows = [
        new Set("qwertyuiopQWERTYUIOP".split('')),
        new Set("asdfghjklASDFGHJKL".split('')),
        new Set("zxcvbnmZXCVBNM".split(''))
    ];
    const res = [];

    for (const word of words) {
        let row = -1;
        for (let i = 0; i < 3; i++) {
            if (rows[i].has(word[0])) {
                row = i;
                break;
            }
        }

        if (word.split('').every(c => rows[row].has(c))) {
            res.push(word);
        }
    }

    return res;
}
```
1. Create an array of sets representing each row of the American keyboard. Include both uppercase and lowercase letters in the set.
2. Initialize an empty result list.
3. Loop through the input words array.
4. Determine the row of the first character of the current word by checking which of the 3 rows contains it.
5. Check if all the characters in the current word belong to the same row found in step 4. If yes, append the word to the result list.
6. Once the loop is done, return the result list.


# Find Mode in Binary Search Tree

- slug: find-mode-in-binary-search-tree
- difficulty: Easy

Given the `root` of a binary search tree (BST) with duplicates, return _all the [mode(s)](https://en.wikipedia.org/wiki/Mode_(statistics)) (i.e., the most frequently occurred element) in it_.

If the tree has more than one mode, return them in **any order**.

Assume a BST is defined as follows:

*   The left subtree of a node contains only nodes with keys **less than or equal to** the node's key.
*   The right subtree of a node contains only nodes with keys **greater than or equal to** the node's key.
*   Both the left and right subtrees must also be binary search trees.

**Example 1:**

**Input:** root = \[1,null,2,2\]
**Output:** \[2\]

**Example 2:**

**Input:** root = \[0\]
**Output:** \[0\]

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 104]`.
*   `-105 <= Node.val <= 105`

**Follow up:** Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).

## A solution in Java

```java
public List<Integer> findMode(TreeNode root) {
    List<Integer> modes = new ArrayList<>();
    if (root == null) return modes;

    Map<Integer, Integer> frequencyMap = new HashMap<>();
    Stack<TreeNode> stack = new Stack<>();
    TreeNode currentNode = root;
    int maxFrequency = 0;

    while (currentNode != null || !stack.isEmpty()) {
        while (currentNode != null) {
            stack.add(currentNode);
            currentNode = currentNode.left;
        }
        currentNode = stack.pop();
        frequencyMap.put(currentNode.val, frequencyMap.getOrDefault(currentNode.val, 0) + 1);
        maxFrequency = Math.max(maxFrequency, frequencyMap.get(currentNode.val));
        currentNode = currentNode.right;
    }

    for (Map.Entry<Integer, Integer> entry : frequencyMap.entrySet()) {
        if (entry.getValue() == maxFrequency) modes.add(entry.getKey());
    }

    return modes;
}
```
The algorithm is based on performing an in-order traversal of the binary search tree (BST). In-order traversal of a BST will visit nodes in ascending order. During the traversal, we count the frequency of each element using a HashMap (in C++ and Java), a Dictionary (in Python), or a Map (in JavaScript) and keep track of the maximum frequency.

Once the traversal is complete, we iterate through our frequency map/dictionary object, and if an element has a frequency equal to the maximum frequency, we add it to our result list/array.

The time complexity of this algorithm is O(n), where n is the number of nodes in the tree, since we visit each node once during the traversal.

## A solution in C++

```cpp
void InOrder(TreeNode* root, unordered_map<int, int>& frequencies, int& max_frequency) {
    if (!root) return;
    InOrder(root->left, frequencies, max_frequency);
    frequencies[root->val]++;
    max_frequency = max(max_frequency, frequencies[root->val]);
    InOrder(root->right, frequencies, max_frequency);
}

vector<int> findMode(TreeNode* root) {
    unordered_map<int, int> frequencies;
    int max_frequency = 0;
    InOrder(root, frequencies, max_frequency);
    vector<int> modes;

    for (const auto& freq : frequencies) {
        if (freq.second == max_frequency) modes.push_back(freq.first);
    }

    return modes;
}
```
The algorithm is based on performing an in-order traversal of the binary search tree (BST). In-order traversal of a BST will visit nodes in ascending order. During the traversal, we count the frequency of each element using a HashMap (in C++ and Java), a Dictionary (in Python), or a Map (in JavaScript) and keep track of the maximum frequency.

Once the traversal is complete, we iterate through our frequency map/dictionary object, and if an element has a frequency equal to the maximum frequency, we add it to our result list/array.

The time complexity of this algorithm is O(n), where n is the number of nodes in the tree, since we visit each node once during the traversal.

## A solution in Python

```python
def findMode(root):
    def InOrder(node):
        if not node: return
        yield from InOrder(node.left)
        yield node.val
        yield from InOrder(node.right)

    counts = collections.Counter(InOrder(root))
    max_count = max(counts.values(), default=0)
    return [k for k, v in counts.items() if v == max_count]
```
The algorithm is based on performing an in-order traversal of the binary search tree (BST). In-order traversal of a BST will visit nodes in ascending order. During the traversal, we count the frequency of each element using a HashMap (in C++ and Java), a Dictionary (in Python), or a Map (in JavaScript) and keep track of the maximum frequency.

Once the traversal is complete, we iterate through our frequency map/dictionary object, and if an element has a frequency equal to the maximum frequency, we add it to our result list/array.

The time complexity of this algorithm is O(n), where n is the number of nodes in the tree, since we visit each node once during the traversal.

## A solution in Javascript

```javascript
function findMode(root) {
    if (!root) return [];

    const frequencies = new Map();
    const stack = [];
    let maxFrequency = 0;
    let currentNode = root;

    while (currentNode || stack.length) {
        while (currentNode) {
            stack.push(currentNode);
            currentNode = currentNode.left;
        }
        currentNode = stack.pop();
        frequencies.set(currentNode.val, (frequencies.get(currentNode.val) || 0) + 1);
        maxFrequency = Math.max(maxFrequency, frequencies.get(currentNode.val));
        currentNode = currentNode.right;
    }

    const modes = [];
    for (const [key, value] of frequencies) {
        if (value === maxFrequency) modes.push(key);
    }

    return modes;
}
```
The algorithm is based on performing an in-order traversal of the binary search tree (BST). In-order traversal of a BST will visit nodes in ascending order. During the traversal, we count the frequency of each element using a HashMap (in C++ and Java), a Dictionary (in Python), or a Map (in JavaScript) and keep track of the maximum frequency.

Once the traversal is complete, we iterate through our frequency map/dictionary object, and if an element has a frequency equal to the maximum frequency, we add it to our result list/array.

The time complexity of this algorithm is O(n), where n is the number of nodes in the tree, since we visit each node once during the traversal.


# IPO

- slug: ipo
- difficulty: Hard

Suppose LeetCode will start its **IPO** soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the **IPO**. Since it has limited resources, it can only finish at most `k` distinct projects before the **IPO**. Help LeetCode design the best way to maximize its total capital after finishing at most `k` distinct projects.

You are given `n` projects where the `ith` project has a pure profit `profits[i]` and a minimum capital of `capital[i]` is needed to start it.

Initially, you have `w` capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.

Pick a list of **at most** `k` distinct projects from given projects to **maximize your final capital**, and return _the final maximized capital_.

The answer is guaranteed to fit in a 32-bit signed integer.

**Example 1:**

**Input:** k = 2, w = 0, profits = \[1,2,3\], capital = \[0,1,1\]
**Output:** 4
**Explanation:** Since your initial capital is 0, you can only start the project indexed 0.
After finishing it you will obtain profit 1 and your capital becomes 1.
With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.
Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.

**Example 2:**

**Input:** k = 3, w = 0, profits = \[1,2,3\], capital = \[0,1,2\]
**Output:** 6

**Constraints:**

*   `1 <= k <= 105`
*   `0 <= w <= 109`
*   `n == profits.length`
*   `n == capital.length`
*   `1 <= n <= 105`
*   `0 <= profits[i] <= 104`
*   `0 <= capital[i] <= 109`

## A solution in Java

```java
import java.util.PriorityQueue;
import java.util.Arrays;

public class Solution {
    public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
        int[][] project_pool = new int[profits.length][2];

        for (int i = 0; i < profits.length; i++) {
            project_pool[i] = new int[] {capital[i], profits[i]};
        }

        Arrays.sort(project_pool, (a, b) -> a[0] - b[0]);

        PriorityQueue<Integer> profit_pool = new PriorityQueue<>((a, b) -> b - a);
        int index = 0;

        for (int i = 0; i < k; i++) {
            while (index < project_pool.length &&
                   project_pool[index][0] <= w) {
                profit_pool.add(project_pool[index++][1]);
            }

            if (!profit_pool.isEmpty()) {
                w += profit_pool.poll();
            } else {
                break;
            }
        }

        return w;
    }
}
```
1. Create an array of project pool, where each element is a pair of (capital, profit).
2. Sort the project pool array by capital in ascending order.
3. Initialize a priority queue called profit pool to store the profits of projects based on which one has the highest profit.
4. Iterate through projects up to k times.
5. In each iteration, check projects with capitals less than or equal to w in the project pool, push their profits into the profit pool and remove them from the project pool.
6. If there is any profit in the profit pool, pop the one with the highest profit and add the profit to w.
7. Return the final maximized capital w after finishing at most k distinct projects.

## A solution in C++

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

using namespace std;

int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {
    vector<pair<int, int>> project_pool;

    for (size_t i = 0; i < profits.size(); i++) {
        project_pool.emplace_back(capital[i], profits[i]);
    }

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

    priority_queue<int> profit_pool;
    int index = 0;

    for (int i = 0; i < k; i++) {
        while (index < project_pool.size() &&
               project_pool[index].first <= w) {
            profit_pool.push(project_pool[index++].second);
        }

        if (!profit_pool.empty()) {
            w += profit_pool.top();
            profit_pool.pop();
        } else {
            break;
        }
    }

    return w;
}
```
1. Create an array of project pool, where each element is a pair of (capital, profit).
2. Sort the project pool array by capital in ascending order.
3. Initialize a priority queue called profit pool to store the profits of projects based on which one has the highest profit.
4. Iterate through projects up to k times.
5. In each iteration, check projects with capitals less than or equal to w in the project pool, push their profits into the profit pool and remove them from the project pool.
6. If there is any profit in the profit pool, pop the one with the highest profit and add the profit to w.
7. Return the final maximized capital w after finishing at most k distinct projects.

## A solution in Python

```python
import heapq

def findMaximizedCapital(k: int, w: int, profits, capital) -> int:
    project_pool = list(zip(capital, profits))
    project_pool.sort(reverse=True)

    profit_pool = []

    while k:
        while project_pool and project_pool[-1][0] <= w:
            heapq.heappush(profit_pool, -project_pool.pop()[1])

        if not profit_pool:
            break

        w -= heapq.heappop(profit_pool)
        k -= 1

    return w
```
1. Create an array of project pool, where each element is a pair of (capital, profit).
2. Sort the project pool array by capital in ascending order.
3. Initialize a priority queue called profit pool to store the profits of projects based on which one has the highest profit.
4. Iterate through projects up to k times.
5. In each iteration, check projects with capitals less than or equal to w in the project pool, push their profits into the profit pool and remove them from the project pool.
6. If there is any profit in the profit pool, pop the one with the highest profit and add the profit to w.
7. Return the final maximized capital w after finishing at most k distinct projects.

## A solution in Javascript

```javascript
function findMaximizedCapital(k, w, profits, capital) {
    const project_pool = profits.map((p, i) => [capital[i], p]).sort((a, b) => a[0] - b[0]);
    const profit_pool = new MaxPriorityQueue();
    let index = 0;

    for (let i = 0; i < k; i++) {
        while (index < project_pool.length && project_pool[index][0] <= w) {
            profit_pool.insert(project_pool[index++][1]);
        }

        if (!profit_pool.isEmpty()) {
            w += profit_pool.removeMax();
        } else {
            break;
        }
    }

    return w;
}

class MaxPriorityQueue {
    constructor() {
        this.queue = [];
    }

    insert(value) {
        this.queue.push(value);
        this.siftUp(this.queue.length - 1);
    }

    removeMax() {
        const maxValue = this.queue[0];
        const lastValue = this.queue.pop();

        if (this.queue.length) {
            this.queue[0] = lastValue;
            this.siftDown(0);
        }

        return maxValue;
    }

    siftUp(index) {
        while (index) {
            const parentIndex = (index - 1) >> 1;
            if (this.queue[parentIndex] >= this.queue[index]) break;
            [this.queue[parentIndex], this.queue[index]] = [this.queue[index], this.queue[parentIndex]];
            index = parentIndex;
        }
    }

    siftDown(index) {
        while (true) {
            const leftIndex = (index << 1) + 1;
            const rightIndex = leftIndex + 1;
            let maxIndex = index;
            if (leftIndex < this.queue.length && this.queue[leftIndex] > this.queue[maxIndex]) maxIndex = leftIndex;
            if (rightIndex < this.queue.length && this.queue[rightIndex] > this.queue[maxIndex]) maxIndex = rightIndex;
            if (maxIndex === index) break;
            [this.queue[index], this.queue[maxIndex]] = [this.queue[maxIndex], this.queue[index]];
            index = maxIndex;
        }
    }

    isEmpty() {
        return this.queue.length === 0;
    }
}
```
1. Create an array of project pool, where each element is a pair of (capital, profit).
2. Sort the project pool array by capital in ascending order.
3. Initialize a priority queue called profit pool to store the profits of projects based on which one has the highest profit.
4. Iterate through projects up to k times.
5. In each iteration, check projects with capitals less than or equal to w in the project pool, push their profits into the profit pool and remove them from the project pool.
6. If there is any profit in the profit pool, pop the one with the highest profit and add the profit to w.
7. Return the final maximized capital w after finishing at most k distinct projects.


# Next Greater Element II

- slug: next-greater-element-ii
- difficulty: Medium

Given a circular integer array `nums` (i.e., the next element of `nums[nums.length - 1]` is `nums[0]`), return _the **next greater number** for every element in_ `nums`.

The **next greater number** of a number `x` is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, return `-1` for this number.

**Example 1:**

**Input:** nums = \[1,2,1\]
**Output:** \[2,-1,2\]
Explanation: The first 1's next greater number is 2;
The number 2 can't find next greater number.
The second 1's next greater number needs to search circularly, which is also 2.

**Example 2:**

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

**Constraints:**

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

## A solution in Java

```java
import java.util.Stack;

public int[] nextGreaterElements(int[] nums) {
    int n = nums.length;
    int[] result = new int[n];
    Stack<Integer> stack = new Stack<>();

    for (int i = 0; i < n * 2; i++) {
        int index = i % n;
        while (!stack.isEmpty() && nums[stack.peek()] < nums[index]) {
            result[stack.pop()] = nums[index];
        }
        if (i < n) {
            stack.push(index);
        }
    }
    return result;
}
```
The algorithm uses a stack to keep track of the indices of the elements in the `nums` array. We traverse the array twice (using modulo operator) since it's circular. For each element, we check if it's greater than the top element (index) of the stack. If it is, we update the corresponding result for that index with the current element and pop the index from the stack. We push the current index onto the stack if we are still in the first traversal.

Finally, we return `result` list which holds the next greater element for all elements in the input list. If a greater element is not found for an element, its value in the result list will remain `-1`.

## A solution in C++

```cpp
#include <vector>
#include <stack>

std::vector<int> nextGreaterElements(std::vector<int>& nums) {
    std::vector<int> result(nums.size(), -1);
    std::stack<int> s;

    for (int i = 0; i < nums.size() * 2; ++i) {
        int index = i % nums.size();
        while (!s.empty() && nums[s.top()] < nums[index]) {
            result[s.top()] = nums[index];
            s.pop();
        }
        if (i < nums.size()) {
            s.push(index);
        }
    }
    return result;
}
```
The algorithm uses a stack to keep track of the indices of the elements in the `nums` array. We traverse the array twice (using modulo operator) since it's circular. For each element, we check if it's greater than the top element (index) of the stack. If it is, we update the corresponding result for that index with the current element and pop the index from the stack. We push the current index onto the stack if we are still in the first traversal.

Finally, we return `result` list which holds the next greater element for all elements in the input list. If a greater element is not found for an element, its value in the result list will remain `-1`.

## A solution in Python

```python
def nextGreaterElements(nums):
    result = [-1] * len(nums)
    stack = []

    for i in range(len(nums) * 2):
        index = i % len(nums)
        while stack and nums[stack[-1]] < nums[index]:
            result[stack.pop()] = nums[index]
        if i < len(nums):
            stack.append(index)

    return result
```
The algorithm uses a stack to keep track of the indices of the elements in the `nums` array. We traverse the array twice (using modulo operator) since it's circular. For each element, we check if it's greater than the top element (index) of the stack. If it is, we update the corresponding result for that index with the current element and pop the index from the stack. We push the current index onto the stack if we are still in the first traversal.

Finally, we return `result` list which holds the next greater element for all elements in the input list. If a greater element is not found for an element, its value in the result list will remain `-1`.

## A solution in Javascript

```javascript
function nextGreaterElements(nums) {
  const result = new Array(nums.length).fill(-1);
  const stack = [];

  for (let i = 0; i < nums.length * 2; i++) {
    const index = i % nums.length;
    while (stack.length > 0 && nums[stack[stack.length - 1]] < nums[index]) {
      result[stack.pop()] = nums[index];
    }
    if (i < nums.length) {
      stack.push(index);
    }
  }
  return result;
}
```
The algorithm uses a stack to keep track of the indices of the elements in the `nums` array. We traverse the array twice (using modulo operator) since it's circular. For each element, we check if it's greater than the top element (index) of the stack. If it is, we update the corresponding result for that index with the current element and pop the index from the stack. We push the current index onto the stack if we are still in the first traversal.

Finally, we return `result` list which holds the next greater element for all elements in the input list. If a greater element is not found for an element, its value in the result list will remain `-1`.


# Base 7

- slug: base-7
- difficulty: Easy

Given an integer `num`, return _a string of its **base 7** representation_.

**Example 1:**

**Input:** num = 100
**Output:** "202"

**Example 2:**

**Input:** num = -7
**Output:** "-10"

**Constraints:**

*   `-107 <= num <= 107`

## A solution in Java

```java
public String convertToBase7(int num) {
    if (num == 0) return "0";
    StringBuilder result = new StringBuilder();
    boolean negative = num < 0;
    if (negative) num *= -1;
    while (num > 0) {
        result.insert(0, num % 7);
        num /= 7;
    }
    return negative ? "-" + result.toString() : result.toString();
}
```
The algorithm first checks if the input number is 0, and if so, it simply returns the base-7 representation as "0". If the number is negative, it keeps track of the sign and converts the number to positive. Then, it iteratively divides the number by 7 (integer division) and prepends the remainder (modulus) to the result string. Finally, if the input number was negative, it adds the minus sign back to the result string. The same algorithm is implemented in C++, Java, Python, and JavaScript with minor syntax adjustments.

## A solution in C++

```cpp
std::string convertToBase7(int num) {
    if (num == 0) return "0";
    std::string result = "";
    bool negative = num < 0;
    if (negative) num *= -1;
    while (num > 0) {
        result = std::to_string(num % 7) + result;
        num /= 7;
    }
    return negative ? "-" + result : result;
}
```
The algorithm first checks if the input number is 0, and if so, it simply returns the base-7 representation as "0". If the number is negative, it keeps track of the sign and converts the number to positive. Then, it iteratively divides the number by 7 (integer division) and prepends the remainder (modulus) to the result string. Finally, if the input number was negative, it adds the minus sign back to the result string. The same algorithm is implemented in C++, Java, Python, and JavaScript with minor syntax adjustments.

## A solution in Python

```python
def convert_to_base7(num: int) -> str:
    if num == 0:
        return "0"
    result = ""
    negative = num < 0
    if negative:
        num *= -1
    while num > 0:
        result = str(num % 7) + result
        num //= 7
    return "-" + result if negative else result
```
The algorithm first checks if the input number is 0, and if so, it simply returns the base-7 representation as "0". If the number is negative, it keeps track of the sign and converts the number to positive. Then, it iteratively divides the number by 7 (integer division) and prepends the remainder (modulus) to the result string. Finally, if the input number was negative, it adds the minus sign back to the result string. The same algorithm is implemented in C++, Java, Python, and JavaScript with minor syntax adjustments.

## A solution in Javascript

```javascript
function convertToBase7(num) {
    if (num === 0) return "0";
    let result = "";
    let negative = num < 0;
    if (negative) num *= -1;
    while (num > 0) {
        result = (num % 7).toString() + result;
        num = Math.floor(num / 7);
    }
    return negative ? "-" + result : result;
}
```
The algorithm first checks if the input number is 0, and if so, it simply returns the base-7 representation as "0". If the number is negative, it keeps track of the sign and converts the number to positive. Then, it iteratively divides the number by 7 (integer division) and prepends the remainder (modulus) to the result string. Finally, if the input number was negative, it adds the minus sign back to the result string. The same algorithm is implemented in C++, Java, Python, and JavaScript with minor syntax adjustments.