# Sum of Left Leaves

- slug: sum-of-left-leaves
- difficulty: Easy

Given the `root` of a binary tree, return _the sum of all left leaves._

A **leaf** is a node with no children. A **left leaf** is a leaf that is the left child of another node.

**Example 1:**

**Input:** root = \[3,9,20,null,null,15,7\]
**Output:** 24
**Explanation:** There are two left leaves in the binary tree, with values 9 and 15 respectively.

**Example 2:**

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

**Constraints:**

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

## A solution in Java

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

public int sumOfLeftLeaves(TreeNode root) {
    if (root == null) return 0;
    int sum = 0;
    if (root.left != null && root.left.left == null && root.left.right == null) sum += root.left.val;
    return sum + sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
}
```
The algorithm uses a recursive approach. For every node in the tree, the program checks if the left child is a leaf node by verifying if it exists and if it has no children. If the left child is a leaf, add its value to the sum, and then call the function for both left and right children of the current node. Since the tree can have varying depths, recursion is useful to explore each subtree and accumulate the sum of all left leaves.

## A solution in C++

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

int sumOfLeftLeaves(TreeNode* root) {
    if (!root) return 0;
    int sum = 0;
    if (root->left && !root->left->left && !root->left->right) sum += root->left->val;
    return sum + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
```
The algorithm uses a recursive approach. For every node in the tree, the program checks if the left child is a leaf node by verifying if it exists and if it has no children. If the left child is a leaf, add its value to the sum, and then call the function for both left and right children of the current node. Since the tree can have varying depths, recursion is useful to explore each subtree and accumulate the sum of all left leaves.

## A solution in Python

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

def sum_of_left_leaves(root):
    if not root:
        return 0
    left_sum = 0
    if root.left and not root.left.left and not root.left.right:
        left_sum += root.left.val
    return left_sum + sum_of_left_leaves(root.left) + sum_of_left_leaves(root.right)
```
The algorithm uses a recursive approach. For every node in the tree, the program checks if the left child is a leaf node by verifying if it exists and if it has no children. If the left child is a leaf, add its value to the sum, and then call the function for both left and right children of the current node. Since the tree can have varying depths, recursion is useful to explore each subtree and accumulate the sum of all left leaves.

## A solution in Javascript

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

function sumOfLeftLeaves(root) {
    if (!root) return 0;
    let sum = 0;
    if (root.left && !root.left.left && !root.left.right) sum += root.left.val;
    return sum + sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
}
```
The algorithm uses a recursive approach. For every node in the tree, the program checks if the left child is a leaf node by verifying if it exists and if it has no children. If the left child is a leaf, add its value to the sum, and then call the function for both left and right children of the current node. Since the tree can have varying depths, recursion is useful to explore each subtree and accumulate the sum of all left leaves.


# Convert a Number to Hexadecimal

- slug: convert-a-number-to-hexadecimal
- difficulty: Easy

Given an integer `num`, return _a string representing its hexadecimal representation_. For negative integers, [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) method is used.

All the letters in the answer string should be lowercase characters, and there should not be any leading zeros in the answer except for the zero itself.

**Note:** You are not allowed to use any built-in library method to directly solve this problem.

**Example 1:**

**Input:** num = 26
**Output:** "1a"

**Example 2:**

**Input:** num = -1
**Output:** "ffffffff"

**Constraints:**

*   `-231 <= num <= 231 - 1`

## A solution in Java

```java
public String toHex(int num) {
    if (num == 0) return "0";
    String hex = "";
    char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    for (int i = 0; num != 0 && i < 8; ++i) {
        hex = hexDigits[num & 0xf] + hex;
        num >>>= 4;
    }
    return hex;
}
```
The algorithm for converting an integer to its hexadecimal representation follows these steps:

1. Check if the input number is 0, if so, return the string "0".
2. Initialize an empty string (hex) to store the hexadecimal representation of the integer.
3. Initialize an array or string (hexDigits) containing the characters representing the hexadecimal digits from 0 to 15 (0-9 and a-f).
4. If the input integer is negative, convert it to its unsigned 32-bit integer representation.
5. While the integer is not 0, extract the last 4 bits using a bitwise AND operation with the value `0xf` (15 in decimal) and use the result as an index to get the corresponding hexadecimal character from hexDigits. Append this character to the left side of the hex string.
6. Shift the integer right by 4 bits (n >>= 4) to move on to the next 4 bits.
7. Repeat steps 5 and 6 until the integer is 0.
8. Return the hex string as the final hexadecimal representation of the input integer.

## A solution in C++

```cpp
std::string toHex(int num) {
    if (num == 0) return "0";
    std::string hex = "";
    unsigned int n = num;
    char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    while (n) {
        hex = hexDigits[n & 15] + hex;
        n >>= 4;
    }
    return hex;
}
```
The algorithm for converting an integer to its hexadecimal representation follows these steps:

1. Check if the input number is 0, if so, return the string "0".
2. Initialize an empty string (hex) to store the hexadecimal representation of the integer.
3. Initialize an array or string (hexDigits) containing the characters representing the hexadecimal digits from 0 to 15 (0-9 and a-f).
4. If the input integer is negative, convert it to its unsigned 32-bit integer representation.
5. While the integer is not 0, extract the last 4 bits using a bitwise AND operation with the value `0xf` (15 in decimal) and use the result as an index to get the corresponding hexadecimal character from hexDigits. Append this character to the left side of the hex string.
6. Shift the integer right by 4 bits (n >>= 4) to move on to the next 4 bits.
7. Repeat steps 5 and 6 until the integer is 0.
8. Return the hex string as the final hexadecimal representation of the input integer.

## A solution in Python

```python
def to_hex(num: int) -> str:
    if num == 0:
        return '0'
    hex_str = ''
    hex_digits = '0123456789abcdef'
    n = num & 0xffffffff
    while n:
        hex_str = hex_digits[n & 0xf] + hex_str
        n >>= 4
    return hex_str
```
The algorithm for converting an integer to its hexadecimal representation follows these steps:

1. Check if the input number is 0, if so, return the string "0".
2. Initialize an empty string (hex) to store the hexadecimal representation of the integer.
3. Initialize an array or string (hexDigits) containing the characters representing the hexadecimal digits from 0 to 15 (0-9 and a-f).
4. If the input integer is negative, convert it to its unsigned 32-bit integer representation.
5. While the integer is not 0, extract the last 4 bits using a bitwise AND operation with the value `0xf` (15 in decimal) and use the result as an index to get the corresponding hexadecimal character from hexDigits. Append this character to the left side of the hex string.
6. Shift the integer right by 4 bits (n >>= 4) to move on to the next 4 bits.
7. Repeat steps 5 and 6 until the integer is 0.
8. Return the hex string as the final hexadecimal representation of the input integer.

## A solution in Javascript

```javascript
function toHex(num) {
  if (num === 0) return '0';
  const hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
  let hex = '';
  let n = num >>> 0;
  while (n) {
    hex = hexDigits[n & 0xf] + hex;
    n >>>= 4;
  }
  return hex;
}
```
The algorithm for converting an integer to its hexadecimal representation follows these steps:

1. Check if the input number is 0, if so, return the string "0".
2. Initialize an empty string (hex) to store the hexadecimal representation of the integer.
3. Initialize an array or string (hexDigits) containing the characters representing the hexadecimal digits from 0 to 15 (0-9 and a-f).
4. If the input integer is negative, convert it to its unsigned 32-bit integer representation.
5. While the integer is not 0, extract the last 4 bits using a bitwise AND operation with the value `0xf` (15 in decimal) and use the result as an index to get the corresponding hexadecimal character from hexDigits. Append this character to the left side of the hex string.
6. Shift the integer right by 4 bits (n >>= 4) to move on to the next 4 bits.
7. Repeat steps 5 and 6 until the integer is 0.
8. Return the hex string as the final hexadecimal representation of the input integer.


# Queue Reconstruction by Height

- slug: queue-reconstruction-by-height
- difficulty: Medium

You are given an array of people, `people`, which are the attributes of some people in a queue (not necessarily in order). Each `people[i] = [hi, ki]` represents the `ith` person of height `hi` with **exactly** `ki` other people in front who have a height greater than or equal to `hi`.

Reconstruct and return _the queue that is represented by the input array_ `people`. The returned queue should be formatted as an array `queue`, where `queue[j] = [hj, kj]` is the attributes of the `jth` person in the queue (`queue[0]` is the person at the front of the queue).

**Example 1:**

**Input:** people = \[\[7,0\],\[4,4\],\[7,1\],\[5,0\],\[6,1\],\[5,2\]\]
**Output:** \[\[5,0\],\[7,0\],\[5,2\],\[6,1\],\[4,4\],\[7,1\]\]
**Explanation:**
Person 0 has height 5 with no other people taller or the same height in front.
Person 1 has height 7 with no other people taller or the same height in front.
Person 2 has height 5 with two persons taller or the same height in front, which is person 0 and 1.
Person 3 has height 6 with one person taller or the same height in front, which is person 1.
Person 4 has height 4 with four people taller or the same height in front, which are people 0, 1, 2, and 3.
Person 5 has height 7 with one person taller or the same height in front, which is person 1.
Hence \[\[5,0\],\[7,0\],\[5,2\],\[6,1\],\[4,4\],\[7,1\]\] is the reconstructed queue.

**Example 2:**

**Input:** people = \[\[6,0\],\[5,0\],\[4,0\],\[3,2\],\[2,2\],\[1,4\]\]
**Output:** \[\[4,0\],\[5,0\],\[2,2\],\[3,2\],\[1,4\],\[6,0\]\]

**Constraints:**

*   `1 <= people.length <= 2000`
*   `0 <= hi <= 106`
*   `0 <= ki < people.length`
*   It is guaranteed that the queue can be reconstructed.

## A solution in Java

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

public int[][] reconstructQueue(int[][] people) {
    Arrays.sort(people, (a, b) -> a[0] == b[0] ? a[1] - b[1] : b[0] - a[0]);

    List<int[]> result = new ArrayList<>();
    for (int[] p : people) {
        result.add(p[1], p);
    }
    return result.toArray(new int[people.length][2]);
}
```
The algorithm to solve this problem can be broken down into the following steps:

1. Sort the input array of people in decreasing order of height (h). If two people have the same height, sort them in increasing order of the count of taller people in front (k).
2. Create an empty result array.
3. Iterate through the sorted input array, and insert each person at the index corresponding to the count of taller people in front (k) in the result array.

The time complexity of this algorithm is O(n^2) due to the insert operations, where n is the number of people in the input array. The space complexity is O(n), as we construct a new array for the result.

## A solution in C++

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

std::vector<std::vector<int>> reconstructQueue(std::vector<std::vector<int>>& people) {
    std::sort(people.begin(), people.end(), [](const std::vector<int>& a, const std::vector<int>& b) {
        return a[0] > b[0] || (a[0] == b[0] && a[1] < b[1]);
    });

    std::vector<std::vector<int>> result;
    for (const std::vector<int>& p : people) {
        result.insert(result.begin() + p[1], p);
    }
    return result;
}
```
The algorithm to solve this problem can be broken down into the following steps:

1. Sort the input array of people in decreasing order of height (h). If two people have the same height, sort them in increasing order of the count of taller people in front (k).
2. Create an empty result array.
3. Iterate through the sorted input array, and insert each person at the index corresponding to the count of taller people in front (k) in the result array.

The time complexity of this algorithm is O(n^2) due to the insert operations, where n is the number of people in the input array. The space complexity is O(n), as we construct a new array for the result.

## A solution in Python

```python
from typing import List

def reconstructQueue(people: List[List[int]]) -> List[List[int]]:
    people.sort(key=lambda x: (-x[0], x[1]))

    result = []
    for p in people:
        result.insert(p[1], p)
    return result
```
The algorithm to solve this problem can be broken down into the following steps:

1. Sort the input array of people in decreasing order of height (h). If two people have the same height, sort them in increasing order of the count of taller people in front (k).
2. Create an empty result array.
3. Iterate through the sorted input array, and insert each person at the index corresponding to the count of taller people in front (k) in the result array.

The time complexity of this algorithm is O(n^2) due to the insert operations, where n is the number of people in the input array. The space complexity is O(n), as we construct a new array for the result.

## A solution in Javascript

```javascript
function reconstructQueue(people) {
    people.sort((a, b) => {
        return a[0] !== b[0] ? b[0] - a[0] : a[1] - b[1];
    });

    const result = [];
    for (const p of people) {
        result.splice(p[1], 0, p);
    }
    return result;
}
```
The algorithm to solve this problem can be broken down into the following steps:

1. Sort the input array of people in decreasing order of height (h). If two people have the same height, sort them in increasing order of the count of taller people in front (k).
2. Create an empty result array.
3. Iterate through the sorted input array, and insert each person at the index corresponding to the count of taller people in front (k) in the result array.

The time complexity of this algorithm is O(n^2) due to the insert operations, where n is the number of people in the input array. The space complexity is O(n), as we construct a new array for the result.


# Trapping Rain Water II

- slug: trapping-rain-water-ii
- difficulty: Hard

Given an `m x n` integer matrix `heightMap` representing the height of each unit cell in a 2D elevation map, return _the volume of water it can trap after raining_.

**Example 1:**

**Input:** heightMap = \[\[1,4,3,1,3,2\],\[3,2,1,3,2,4\],\[2,3,3,2,3,1\]\]
**Output:** 4
**Explanation:** After the rain, water is trapped between the blocks.
We have two small ponds 1 and 3 units trapped.
The total volume of water trapped is 4.

**Example 2:**

**Input:** heightMap = \[\[3,3,3,3,3\],\[3,2,2,2,3\],\[3,2,1,2,3\],\[3,2,2,2,3\],\[3,3,3,3,3\]\]
**Output:** 10

**Constraints:**

*   `m == heightMap.length`
*   `n == heightMap[i].length`
*   `1 <= m, n <= 200`
*   `0 <= heightMap[i][j] <= 2 * 104`

## A solution in Java

```java
import java.util.PriorityQueue;

public int trapRainWater(int[][] heightMap) {
    int m = heightMap.length, n = heightMap[0].length;
    PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
    boolean[][] visited = new boolean[m][n];

    for (int i = 0; i < m; i++) {
        pq.offer(new int[]{heightMap[i][0], i, 0});
        pq.offer(new int[]{heightMap[i][n - 1], i, n - 1});
        visited[i][0] = visited[i][n - 1] = true;
    }

    for (int i = 1; i < n - 1; i++) {
        pq.offer(new int[]{heightMap[0][i], 0, i});
        pq.offer(new int[]{heightMap[m - 1][i], m - 1, i});
        visited[0][i] = visited[m - 1][i] = true;
    }

    int water = 0, maxHeight = 0;
    int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

    while (!pq.isEmpty()) {
        int[] t = pq.poll();
        int h = t[0], r = t[1], c = t[2];
        maxHeight = Math.max(maxHeight, h);
        for (int[] dir : dirs) {
            int x = r + dir[0], y = c + dir[1];
            if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y]) continue;
            if (heightMap[x][y] < maxHeight) water += maxHeight - heightMap[x][y];
            pq.offer(new int[]{heightMap[x][y], x, y});
            visited[x][y] = true;
        }
    }

    return water;
}
```
The algorithm uses a priority queue (min-heap) to store the lowest-height cell on the perimeter of the unvisited area. It processes the minimum height cell from the perimeter, and for each neighbor cell, it calculates the trapped water and updates the neighbor's height if necessary. It then adds the neighbor to the priority queue if it hasn't been visited before.

The algorithm visits each cell once, and the complexity of adding each cell to the priority queue is O(log(M*N)) where M and N are dimensions of the heightMap, so the overall time complexity is O(M * N * log(M * N)). The space complexity is O(M * N) as a result of the visited array and priority queue.

1. Create a priority queue to store `(height, row, col)` tuples and initialize it with the heightMap boundary cells.
2. Create a visited matrix of the same dimensions as the heightMap and mark the boundary cells as visited.
3. Process the cells in the priority queue in increasing order of height.
4. For each cell, compare its height with the current maxHeight. Calculate the trapped water by subtracting the cell's height from maxHeight if it is smaller.
5. For each neighbor cell that has not been visited, add the neighbor cell with its height to the priority queue and mark it as visited.
6. Return the total volume of trapped water.

## A solution in C++

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

using namespace std;

int trapRainWater(vector<vector<int>>& heightMap) {
    int m = heightMap.size(), n = heightMap[0].size();
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    vector<vector<int>> visited(m, vector<int>(n, 0));

    for (int i = 0; i < m; i++) {
        pq.push({heightMap[i][0], i * n});
        pq.push({heightMap[i][n - 1], i * n + n - 1});
        visited[i][0] = visited[i][n - 1] = 1;
    }

    for (int i = 1; i < n - 1; i++) {
        pq.push({heightMap[0][i], i});
        pq.push({heightMap[m - 1][i], (m - 1) * n + i});
        visited[0][i] = visited[m - 1][i] = 1;
    }

    int water = 0, maxHeight = 0;
    vector<vector<int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

    while (!pq.empty()) {
        auto t = pq.top(); pq.pop();
        int h = t.first, r = t.second / n, c = t.second % n;
        maxHeight = max(maxHeight, h);
        for (auto dir : dirs) {
            int x = r + dir[0], y = c + dir[1];
            if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y]) continue;
            if (heightMap[x][y] < maxHeight) water += maxHeight - heightMap[x][y];
            pq.push({heightMap[x][y], x * n + y});
            visited[x][y] = 1;
        }
    }

    return water;
}
```
The algorithm uses a priority queue (min-heap) to store the lowest-height cell on the perimeter of the unvisited area. It processes the minimum height cell from the perimeter, and for each neighbor cell, it calculates the trapped water and updates the neighbor's height if necessary. It then adds the neighbor to the priority queue if it hasn't been visited before.

The algorithm visits each cell once, and the complexity of adding each cell to the priority queue is O(log(M*N)) where M and N are dimensions of the heightMap, so the overall time complexity is O(M * N * log(M * N)). The space complexity is O(M * N) as a result of the visited array and priority queue.

1. Create a priority queue to store `(height, row, col)` tuples and initialize it with the heightMap boundary cells.
2. Create a visited matrix of the same dimensions as the heightMap and mark the boundary cells as visited.
3. Process the cells in the priority queue in increasing order of height.
4. For each cell, compare its height with the current maxHeight. Calculate the trapped water by subtracting the cell's height from maxHeight if it is smaller.
5. For each neighbor cell that has not been visited, add the neighbor cell with its height to the priority queue and mark it as visited.
6. Return the total volume of trapped water.

## A solution in Python

```python
import heapq

def trapRainWater(heightMap):
    m, n = len(heightMap), len(heightMap[0])
    pq = []
    visited = [[False] * n for _ in range(m)]

    for i in range(m):
        heapq.heappush(pq, (heightMap[i][0], i, 0))
        heapq.heappush(pq, (heightMap[i][n - 1], i, n - 1))
        visited[i][0] = visited[i][n - 1] = True

    for i in range(1, n - 1):
        heapq.heappush(pq, (heightMap[0][i], 0, i))
        heapq.heappush(pq, (heightMap[m - 1][i], m - 1, i))
        visited[0][i] = visited[m - 1][i] = True

    water, maxHeight = 0, 0
    dirs = ((0, 1), (0, -1), (1, 0), (-1, 0))

    while pq:
        h, r, c = heapq.heappop(pq)
        maxHeight = max(maxHeight, h)
        for dx, dy in dirs:
            x, y = r + dx, c + dy
            if x < 0 or x >= m or y < 0 or y >= n or visited[x][y]:
                continue
            if heightMap[x][y] < maxHeight:
                water += maxHeight - heightMap[x][y]
            heapq.heappush(pq, (heightMap[x][y], x, y))
            visited[x][y] = True

    return water
```
The algorithm uses a priority queue (min-heap) to store the lowest-height cell on the perimeter of the unvisited area. It processes the minimum height cell from the perimeter, and for each neighbor cell, it calculates the trapped water and updates the neighbor's height if necessary. It then adds the neighbor to the priority queue if it hasn't been visited before.

The algorithm visits each cell once, and the complexity of adding each cell to the priority queue is O(log(M*N)) where M and N are dimensions of the heightMap, so the overall time complexity is O(M * N * log(M * N)). The space complexity is O(M * N) as a result of the visited array and priority queue.

1. Create a priority queue to store `(height, row, col)` tuples and initialize it with the heightMap boundary cells.
2. Create a visited matrix of the same dimensions as the heightMap and mark the boundary cells as visited.
3. Process the cells in the priority queue in increasing order of height.
4. For each cell, compare its height with the current maxHeight. Calculate the trapped water by subtracting the cell's height from maxHeight if it is smaller.
5. For each neighbor cell that has not been visited, add the neighbor cell with its height to the priority queue and mark it as visited.
6. Return the total volume of trapped water.

## A solution in Javascript

```javascript
function trapRainWater(heightMap) {
    const m = heightMap.length;
    const n = heightMap[0].length;
    const pq = [];
    const visited = Array.from({ length: m }, () => Array(n).fill(false));

    const comparator = (a, b) => a[0] - b[0];

    for (let i = 0; i < m; i++) {
        pq.push([heightMap[i][0], i, 0], [heightMap[i][n - 1], i, n - 1]);
        visited[i][0] = visited[i][n - 1] = true;
    }

    for (let i = 1; i < n - 1; i++) {
        pq.push([heightMap[0][i], 0, i], [heightMap[m - 1][i], m - 1, i]);
        visited[0][i] = visited[m - 1][i] = true;
    }

    pq.sort(comparator);

    let water = 0;
    let maxHeight = 0;
    const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]];

    while (pq.length) {
        const [h, r, c] = pq.shift();
        maxHeight = Math.max(maxHeight, h);
        for (const [dx, dy] of dirs) {
            const x = r + dx;
            const y = c + dy;
            if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y]) continue;
            if (heightMap[x][y] < maxHeight) water += maxHeight - heightMap[x][y];
            pq.push([heightMap[x][y], x, y]);
            pq.sort(comparator);
            visited[x][y] = true;
        }
    }

    return water;
}
```
The algorithm uses a priority queue (min-heap) to store the lowest-height cell on the perimeter of the unvisited area. It processes the minimum height cell from the perimeter, and for each neighbor cell, it calculates the trapped water and updates the neighbor's height if necessary. It then adds the neighbor to the priority queue if it hasn't been visited before.

The algorithm visits each cell once, and the complexity of adding each cell to the priority queue is O(log(M*N)) where M and N are dimensions of the heightMap, so the overall time complexity is O(M * N * log(M * N)). The space complexity is O(M * N) as a result of the visited array and priority queue.

1. Create a priority queue to store `(height, row, col)` tuples and initialize it with the heightMap boundary cells.
2. Create a visited matrix of the same dimensions as the heightMap and mark the boundary cells as visited.
3. Process the cells in the priority queue in increasing order of height.
4. For each cell, compare its height with the current maxHeight. Calculate the trapped water by subtracting the cell's height from maxHeight if it is smaller.
5. For each neighbor cell that has not been visited, add the neighbor cell with its height to the priority queue and mark it as visited.
6. Return the total volume of trapped water.


# Valid Word Abbreviation

- slug: valid-word-abbreviation
- difficulty: Easy

A string can be **abbreviated** by replacing any number of **non-adjacent**, **non-empty** substrings with their lengths. The lengths **should not** have leading zeros.

For example, a string such as `"substitution "` could be abbreviated as (but not limited to):

*   `"s10n "` ( `"s ubstitutio n "`)
*   `"sub4u4 "` ( `"sub stit u tion "`)
*   `"12 "` ( `"substitution "`)
*   `"su3i1u2on "` ( `"su bst i t u ti on "`)
*   `"substitution "` (no substrings replaced)

The following are **not valid** abbreviations:

*   `"s55n "` ( `"s ubsti tutio n "`, the replaced substrings are adjacent)
*   `"s010n "` (has leading zeros)
*   `"s0ubstitution "` (replaces an empty substring)

Given a string `word` and an abbreviation `abbr`, return _whether the string **matches** the given abbreviation_.

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

**Example 1:**

**Input:** word =  "internationalization ", abbr =  "i12iz4n "
**Output:** true
**Explanation:** The word  "internationalization " can be abbreviated as  "i12iz4n " ( "i nternational iz atio n ").

**Example 2:**

**Input:** word =  "apple ", abbr =  "a2e "
**Output:** false
**Explanation:** The word  "apple " cannot be abbreviated as  "a2e ".

**Constraints:**

*   `1 <= word.length <= 20`
*   `word` consists of only lowercase English letters.
*   `1 <= abbr.length <= 10`
*   `abbr` consists of lowercase English letters and digits.
*   All the integers in `abbr` will fit in a 32-bit integer.

## A solution in Java

```java
public boolean validWordAbbreviation(String word, String abbr) {
    int i = 0, j = 0;
    while (i < word.length() && j < abbr.length()) {
        if (Character.isDigit(abbr.charAt(j))) {
            if (abbr.charAt(j) == '0') return false; // leading zero
            int num = 0;
            while (j < abbr.length() && Character.isDigit(abbr.charAt(j)))
                num = num * 10 + (abbr.charAt(j++) - '0');
            i += num;
        } else {
            if (word.charAt(i++) != abbr.charAt(j++)) return false;
        }
    }
    return i == word.length() && j == abbr.length();
}
```
The algorithm uses two pointers, i and j, to compare the characters in the word and the abbr. If the current character in abbr is a digit, we check if it's a leading zero and return false if so. Then, we sum all the consecutive digits to calculate the number and update i accordingly. If the current character is a letter, we compare the characters in word and abbr and return false if they're not equal. Finally, we check if we've reached the end of both the word and the abbr and return true if so.

## A solution in C++

```cpp
bool validWordAbbreviation(string word, string abbr) {
    int i = 0, j = 0;
    while (i < word.size() && j < abbr.size()) {
        if (isdigit(abbr[j])) {
            if (abbr[j] == '0') return false; // leading zero
            int num = 0;
            while (j < abbr.size() && isdigit(abbr[j]))
                num = num * 10 + (abbr[j++] - '0');
            i += num;
        } else {
            if (word[i++] != abbr[j++]) return false;
        }
    }
    return i == word.size() && j == abbr.size();
}
```
The algorithm uses two pointers, i and j, to compare the characters in the word and the abbr. If the current character in abbr is a digit, we check if it's a leading zero and return false if so. Then, we sum all the consecutive digits to calculate the number and update i accordingly. If the current character is a letter, we compare the characters in word and abbr and return false if they're not equal. Finally, we check if we've reached the end of both the word and the abbr and return true if so.

## A solution in Python

```python
def validWordAbbreviation(word, abbr):
    i, j = 0, 0
    while i < len(word) and j < len(abbr):
        if abbr[j].isdigit():
            if abbr[j] == '0': return False  # leading zero
            num = 0
            while j < len(abbr) and abbr[j].isdigit():
                num = num * 10 + int(abbr[j])
                j += 1
            i += num
        else:
            if word[i] != abbr[j]: return False
            i, j = i + 1, j + 1
    return i == len(word) and j == len(abbr)
```
The algorithm uses two pointers, i and j, to compare the characters in the word and the abbr. If the current character in abbr is a digit, we check if it's a leading zero and return false if so. Then, we sum all the consecutive digits to calculate the number and update i accordingly. If the current character is a letter, we compare the characters in word and abbr and return false if they're not equal. Finally, we check if we've reached the end of both the word and the abbr and return true if so.

## A solution in Javascript

```javascript
function validWordAbbreviation(word, abbr) {
    let i = 0, j = 0;
    while (i < word.length && j < abbr.length) {
        if (!isNaN(abbr[j])) {
            if (abbr[j] === '0') return false; // leading zero
            let num = 0;
            while (j < abbr.length && !isNaN(abbr[j])) {
                num = num * 10 + parseInt(abbr[j]);
                j++;
            }
            i += num;
        } else {
            if (word[i] !== abbr[j]) return false;
            i++; j++;
        }
    }
    return i === word.length && j === abbr.length;
}
```
The algorithm uses two pointers, i and j, to compare the characters in the word and the abbr. If the current character in abbr is a digit, we check if it's a leading zero and return false if so. Then, we sum all the consecutive digits to calculate the number and update i accordingly. If the current character is a letter, we compare the characters in word and abbr and return false if they're not equal. Finally, we check if we've reached the end of both the word and the abbr and return true if so.


# Longest Palindrome

- slug: longest-palindrome
- difficulty: Easy

Given a string `s` which consists of lowercase or uppercase letters, return _the length of the **longest palindrome**_ that can be built with those letters.

Letters are **case sensitive**, for example, `"Aa "` is not considered a palindrome here.

**Example 1:**

**Input:** s =  "abccccdd "
**Output:** 7
**Explanation:** One longest palindrome that can be built is  "dccaccd ", whose length is 7.

**Example 2:**

**Input:** s =  "a "
**Output:** 1
**Explanation:** The longest palindrome that can be built is  "a ", whose length is 1.

**Constraints:**

*   `1 <= s.length <= 2000`
*   `s` consists of lowercase **and/or** uppercase English letters only.

## A solution in Java

```java
public int longestPalindrome(String s) {
    int[] charCount = new int[128];
    int result = 0;
    for (char c : s.toCharArray())
        charCount[c]++;
    for (int count : charCount) {
        result += count / 2 * 2;
        if (result % 2 == 0 && count % 2 == 1)
            result++;
    }
    return result;
}
```
1. Create an array `charCount` of size 128 (to cover the ASCII range of characters) initialized with zeros.
2. Iterate through each character in the input string `s` and increment the corresponding count in the `charCount` array.
3. Initialize a variable `result` to store the length of the longest palindrome to be built.
4. Iterate through the `charCount` array and for each count, add the count divided by 2 (integer division) times 2 to the `result`. This adds the number of pairs of characters that can be used in the palindrome.
5. If the result so far is even and the count has an odd value, increment the result by 1. This accounts for the center character in an odd-length palindrome.
6. Return the final result, which is the length of the longest palindrome that can be built.

## A solution in C++

```cpp
int longestPalindrome(string s) {
    int charCount[128] = {0};
    int result = 0;
    for (char c : s)
        charCount[c]++;
    for (int count : charCount) {
        result += count / 2 * 2;
        if (result % 2 == 0 && count % 2 == 1)
            result++;
    }
    return result;
}
```
1. Create an array `charCount` of size 128 (to cover the ASCII range of characters) initialized with zeros.
2. Iterate through each character in the input string `s` and increment the corresponding count in the `charCount` array.
3. Initialize a variable `result` to store the length of the longest palindrome to be built.
4. Iterate through the `charCount` array and for each count, add the count divided by 2 (integer division) times 2 to the `result`. This adds the number of pairs of characters that can be used in the palindrome.
5. If the result so far is even and the count has an odd value, increment the result by 1. This accounts for the center character in an odd-length palindrome.
6. Return the final result, which is the length of the longest palindrome that can be built.

## A solution in Python

```python
def longestPalindrome(s: str) -> int:
    charCount = [0] * 128
    result = 0
    for c in s:
        charCount[ord(c)] += 1
    for count in charCount:
        result += count // 2 * 2
        if result % 2 == 0 and count % 2 == 1:
            result += 1
    return result
```
1. Create an array `charCount` of size 128 (to cover the ASCII range of characters) initialized with zeros.
2. Iterate through each character in the input string `s` and increment the corresponding count in the `charCount` array.
3. Initialize a variable `result` to store the length of the longest palindrome to be built.
4. Iterate through the `charCount` array and for each count, add the count divided by 2 (integer division) times 2 to the `result`. This adds the number of pairs of characters that can be used in the palindrome.
5. If the result so far is even and the count has an odd value, increment the result by 1. This accounts for the center character in an odd-length palindrome.
6. Return the final result, which is the length of the longest palindrome that can be built.

## A solution in Javascript

```javascript
function longestPalindrome(s) {
    let charCount = new Array(128).fill(0);
    let result = 0;
    for (let c of s)
        charCount[c.charCodeAt(0)]++;
    for (let count of charCount) {
        result += Math.floor(count / 2) * 2;
        if (result % 2 === 0 && count % 2 === 1)
            result++;
    }
    return result;
}
```
1. Create an array `charCount` of size 128 (to cover the ASCII range of characters) initialized with zeros.
2. Iterate through each character in the input string `s` and increment the corresponding count in the `charCount` array.
3. Initialize a variable `result` to store the length of the longest palindrome to be built.
4. Iterate through the `charCount` array and for each count, add the count divided by 2 (integer division) times 2 to the `result`. This adds the number of pairs of characters that can be used in the palindrome.
5. If the result so far is even and the count has an odd value, increment the result by 1. This accounts for the center character in an odd-length palindrome.
6. Return the final result, which is the length of the longest palindrome that can be built.


# Split Array Largest Sum

- slug: split-array-largest-sum
- difficulty: Hard

Given an integer array `nums` and an integer `k`, split `nums` into `k` non-empty subarrays such that the largest sum of any subarray is **minimized**.

Return _the minimized largest sum of the split_.

A **subarray** is a contiguous part of the array.

**Example 1:**

**Input:** nums = \[7,2,5,10,8\], k = 2
**Output:** 18
**Explanation:** There are four ways to split nums into two subarrays.
The best way is to split it into \[7,2,5\] and \[10,8\], where the largest sum among the two subarrays is only 18.

**Example 2:**

**Input:** nums = \[1,2,3,4,5\], k = 2
**Output:** 9
**Explanation:** There are four ways to split nums into two subarrays.
The best way is to split it into \[1,2,3\] and \[4,5\], where the largest sum among the two subarrays is only 9.

**Constraints:**

*   `1 <= nums.length <= 1000`
*   `0 <= nums[i] <= 106`
*   `1 <= k <= min(50, nums.length)`

## A solution in Java

```java
public int splitArray(int[] nums, int m) {
    long left = 0, right = 0;
    for (int num : nums) {
        left = Math.max(left, num);
        right += num;
    }

    while (left < right) {
        long mid = (left + right) / 2;
        int count = 1;
        long curSum = 0;
        for (int num : nums) {
            curSum += num;
            if (curSum > mid) {
                curSum = num;
                count++;
            }
        }

        if (count > m) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }

    return (int)left;
}
```
The algorithm to solve this problem is to use a binary search approach. We first initialize the minimum and maximum possible values for the largest sum. The minimum value is initialized to the maximum integer value in the given array, and the maximum value is initialized to the sum of all the integer values in the array. These values are assigned to the variables `left` and `right` respectively.

We then perform a binary search to find the smallest largest sum. In each iteration, we calculate the mid value between left and right (`(left + right) / 2`). Then, we iterate through the array and sum the integers, counting how many subarrays are needed to fit the running sum without exceeding the mid value.

After iterating through the array, if the count of subarrays needed is greater than `m`, it means the mid value is too small. In this case, we update the left value to `mid + 1`. Otherwise, if the count is less than or equal to `m`, we update the right value to `mid`. The process continues until left is equal to or greater than right.

Finally, we return the left value as the minimized largest sum among the m subarrays.

## A solution in C++

```cpp
int splitArray(vector<int>& nums, int m) {
    long long left = 0, right = 0;
    for (int num : nums) {
        left = max(left, (long long)num);
        right += num;
    }

    while (left < right) {
        long long mid = (left + right) / 2;
        int count = 1;
        long long curSum = 0;
        for (int num : nums) {
            curSum += num;
            if (curSum > mid) {
                curSum = num;
                count++;
            }
        }

        if (count > m) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }

    return (int)left;
}
```
The algorithm to solve this problem is to use a binary search approach. We first initialize the minimum and maximum possible values for the largest sum. The minimum value is initialized to the maximum integer value in the given array, and the maximum value is initialized to the sum of all the integer values in the array. These values are assigned to the variables `left` and `right` respectively.

We then perform a binary search to find the smallest largest sum. In each iteration, we calculate the mid value between left and right (`(left + right) / 2`). Then, we iterate through the array and sum the integers, counting how many subarrays are needed to fit the running sum without exceeding the mid value.

After iterating through the array, if the count of subarrays needed is greater than `m`, it means the mid value is too small. In this case, we update the left value to `mid + 1`. Otherwise, if the count is less than or equal to `m`, we update the right value to `mid`. The process continues until left is equal to or greater than right.

Finally, we return the left value as the minimized largest sum among the m subarrays.

## A solution in Python

```python
def splitArray(nums, m):
    left, right = max(nums), sum(nums)

    while left < right:
        mid = (left + right) // 2
        count, cur_sum = 1, 0
        for num in nums:
            cur_sum += num
            if cur_sum > mid:
                cur_sum = num
                count += 1

        if count > m:
            left = mid + 1
        else:
            right = mid

    return left
```
The algorithm to solve this problem is to use a binary search approach. We first initialize the minimum and maximum possible values for the largest sum. The minimum value is initialized to the maximum integer value in the given array, and the maximum value is initialized to the sum of all the integer values in the array. These values are assigned to the variables `left` and `right` respectively.

We then perform a binary search to find the smallest largest sum. In each iteration, we calculate the mid value between left and right (`(left + right) / 2`). Then, we iterate through the array and sum the integers, counting how many subarrays are needed to fit the running sum without exceeding the mid value.

After iterating through the array, if the count of subarrays needed is greater than `m`, it means the mid value is too small. In this case, we update the left value to `mid + 1`. Otherwise, if the count is less than or equal to `m`, we update the right value to `mid`. The process continues until left is equal to or greater than right.

Finally, we return the left value as the minimized largest sum among the m subarrays.

## A solution in Javascript

```javascript
function splitArray(nums, m) {
    let left = 0, right = 0;
    for (let num of nums) {
        left = Math.max(left, num);
        right += num;
    }

    while (left < right) {
        let mid = Math.floor((left + right) / 2);
        let count = 1;
        let curSum = 0;
        for (let num of nums) {
            curSum += num;
            if (curSum > mid) {
                curSum = num;
                count++;
            }
        }

        if (count > m) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }

    return left;
}
```
The algorithm to solve this problem is to use a binary search approach. We first initialize the minimum and maximum possible values for the largest sum. The minimum value is initialized to the maximum integer value in the given array, and the maximum value is initialized to the sum of all the integer values in the array. These values are assigned to the variables `left` and `right` respectively.

We then perform a binary search to find the smallest largest sum. In each iteration, we calculate the mid value between left and right (`(left + right) / 2`). Then, we iterate through the array and sum the integers, counting how many subarrays are needed to fit the running sum without exceeding the mid value.

After iterating through the array, if the count of subarrays needed is greater than `m`, it means the mid value is too small. In this case, we update the left value to `mid + 1`. Otherwise, if the count is less than or equal to `m`, we update the right value to `mid`. The process continues until left is equal to or greater than right.

Finally, we return the left value as the minimized largest sum among the m subarrays.


# Minimum Unique Word Abbreviation

- slug: minimum-unique-word-abbreviation
- difficulty: Hard

A string can be **abbreviated** by replacing any number of **non-adjacent** substrings with their lengths. For example, a string such as `"substitution "` could be abbreviated as (but not limited to):

*   `"s10n "` ( `"s ubstitutio n "`)
*   `"sub4u4 "` ( `"sub stit u tion "`)
*   `"12 "` ( `"substitution "`)
*   `"su3i1u2on "` ( `"su bst i t u ti on "`)
*   `"substitution "` (no substrings replaced)

Note that `"s55n "` ( `"s ubsti tutio n "`) is not a valid abbreviation of `"substitution "` because the replaced substrings are adjacent.

The **length** of an abbreviation is the number of letters that were not replaced plus the number of substrings that were replaced. For example, the abbreviation `"s10n "` has a length of `3` (`2` letters + `1` substring) and `"su3i1u2on "` has a length of `9` (`6` letters + `3` substrings).

Given a target string `target` and an array of strings `dictionary`, return _an **abbreviation** of_ `target` _with the **shortest possible length** such that it is **not an abbreviation** of **any** string in_ `dictionary`_. If there are multiple shortest abbreviations, return any of them_.

**Example 1:**

**Input:** target =  "apple ", dictionary = \[ "blade "\]
**Output:**  "a4 "
**Explanation:** The shortest abbreviation of  "apple " is  "5 ", but this is also an abbreviation of  "blade ".
The next shortest abbreviations are  "a4 " and  "4e ".  "4e " is an abbreviation of blade while  "a4 " is not.
Hence, return  "a4 ".

**Example 2:**

**Input:** target =  "apple ", dictionary = \[ "blade ", "plain ", "amber "\]
**Output:**  "1p3 "
**Explanation:**  "5 " is an abbreviation of both  "apple " but also every word in the dictionary.
 "a4 " is an abbreviation of  "apple " but also  "amber ".
 "4e " is an abbreviation of  "apple " but also  "blade ".
 "1p3 ",  "2p2 ", and  "3l1 " are the next shortest abbreviations of  "apple ".
Since none of them are abbreviations of words in the dictionary, returning any of them is correct.

**Constraints:**

*   `m == target.length`
*   `n == dictionary.length`
*   `1 <= m <= 21`
*   `0 <= n <= 1000`
*   `1 <= dictionary[i].length <= 100`
*   `log2(n) + m <= 21` if `n > 0`
*   `target` and `dictionary[i]` consist of lowercase English letters.
*   `dictionary` does not contain `target`.

## A solution in Java

```java
import java.util.List;

public class Solution {
    private static String abbreviate(String s, int k, int i) {
        if (i == s.length()) {
            return (k > 0) ? String.valueOf(k) : "";
        }
        if (k == 0) {
            return s.substring(i) + (i + 1 < s.length() ? abbreviate(s, 1, i + 1) : "");
        }
        return String.valueOf(k) + s.charAt(i) + (i + 1 < s.length() ? abbreviate(s, 1, i + 1) : "");
    }

    private static boolean isAbbreviation(String target, String word) {
        int i = 0, j = 0;
        while (i < target.length() && j < word.length()) {
            if (target.charAt(i) == word.charAt(j)) {
                i++; j++;
            } else if (Character.isDigit(target.charAt(i))) {
                int k = 0;
                while (i < target.length() && Character.isDigit(target.charAt(i))) {
                    k = k * 10 + target.charAt(i++) - '0';
                }
                j += k;
            } else {
                return false;
            }
        }
        return (i == target.length() && j == word.length());
    }

    public static String minAbbreviation(String target, List<String> dictionary) {
        String ans = target;
        for (int k = 0; k <= target.length(); k++) {
            for (int i = 0; i <= target.length() - k; i++) {
                String current = abbreviate(target, k, i);
                if (current.length() < ans.length()) {
                    boolean valid = true;
                    for (String word : dictionary) {
                        if (isAbbreviation(current, word)) {
                            valid = false;
                            break;
                        }
                    }
                    if (valid) {
                        ans = current;
                    }
                }
            }
        }
        return ans;
    }
}
```
The algorithm first defines a helper function `abbreviate` to generate the abbreviations of the input string. It takes in a string, an abbreviation position, and a counter. This function generates abbreviated strings by recursively replacing substrings at the abbreviation position with their lengths, and concatenating the output.

The main function then iterates through all possible abbreviation lengths, from 0 up to the length of the target string, and for each length, it calculates the abbreviation using the helper function `abbreviate`. For each abbreviation, it checks if this abbreviation is valid, i.e., it's not an abbreviation of any word in the dictionary. If it's not an abbreviation of any word in the dictionary and its length is less than the current answer, it updates the answer.

The validation of an abbreviation is done using another helper function `isAbbreviation`. It takes in a target abbreviation and a dictionary word and checks if the target abbreviation is an abbreviation of the dictionary word by iterating through both strings and comparing characters. If the characters at the current positions match, it moves to the next positions in both strings. If the character in the target string is a digit, it's considered as an abbreviation of part of the dictionary word, and the current position in the dictionary word is updated accordingly. If the characters don't match and the target character is not a digit, it means the target abbreviation is not an abbreviation of the dictionary word.

The time complexity is of the algorithm is O(n * m * 2^m), where n is the length of the dictionary and m is the length of the target string, because there are 2^m possible abbreviations for each string, and for each abbreviation, it checks n words in the dictionary. The space complexity is O(m) for the recursive `abbreviate` function.

## A solution in C++

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

std::string abbreviate(const std::string& s, int k, int i) {
    if (i == s.length()) {
        return (k > 0) ? std::to_string(k) : "";
    }
    if (k == 0) {
        return s.substr(i) + (i + 1 < s.length() ? abbreviate(s, 1, i + 1) : "");
    }
    return std::to_string(k) + s[i] + (i + 1 < s.length() ? abbreviate(s, 1, i + 1) : "");
}

bool isAbbreviation(const std::string& target, const std::string& word) {
    int i = 0, j = 0;
    while (i < target.length() && j < word.length()) {
        if (target[i] == word[j]) {
            i++; j++;
        } else if (isdigit(target[i])) {
            int k = 0;
            while (i < target.length() && isdigit(target[i])) {
                k = k * 10 + target[i++] - '0';
            }
            j += k;
        } else {
            return false;
        }
    }
    return (i == target.length() && j == word.length());
}

std::string minAbbreviation(std::string target, std::vector<std::string>& dictionary) {
    std::string ans = target;
    for (int k = 0; k <= target.length(); k++) {
        for (int i = 0; i <= target.length() - k; i++) {
            std::string current = abbreviate(target, k, i);
            if (current.length() < ans.length()) {
                bool valid = true;
                for (const std::string& word : dictionary) {
                    if (isAbbreviation(current, word)) {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    ans = current;
                }
            }
        }
    }
    return ans;
}
```
The algorithm first defines a helper function `abbreviate` to generate the abbreviations of the input string. It takes in a string, an abbreviation position, and a counter. This function generates abbreviated strings by recursively replacing substrings at the abbreviation position with their lengths, and concatenating the output.

The main function then iterates through all possible abbreviation lengths, from 0 up to the length of the target string, and for each length, it calculates the abbreviation using the helper function `abbreviate`. For each abbreviation, it checks if this abbreviation is valid, i.e., it's not an abbreviation of any word in the dictionary. If it's not an abbreviation of any word in the dictionary and its length is less than the current answer, it updates the answer.

The validation of an abbreviation is done using another helper function `isAbbreviation`. It takes in a target abbreviation and a dictionary word and checks if the target abbreviation is an abbreviation of the dictionary word by iterating through both strings and comparing characters. If the characters at the current positions match, it moves to the next positions in both strings. If the character in the target string is a digit, it's considered as an abbreviation of part of the dictionary word, and the current position in the dictionary word is updated accordingly. If the characters don't match and the target character is not a digit, it means the target abbreviation is not an abbreviation of the dictionary word.

The time complexity is of the algorithm is O(n * m * 2^m), where n is the length of the dictionary and m is the length of the target string, because there are 2^m possible abbreviations for each string, and for each abbreviation, it checks n words in the dictionary. The space complexity is O(m) for the recursive `abbreviate` function.

## A solution in Python

```python
def abbreviate(s, k, i):
    if i == len(s):
        return str(k) if k > 0 else ""
    if k == 0:
        return s[i:] + (abbreviate(s, 1, i + 1) if i + 1 < len(s) else "")
    return str(k) + s[i] + (abbreviate(s, 1, i + 1) if i + 1 < len(s) else "")

def is_abbreviation(target, word):
    i, j = 0, 0
    while i < len(target) and j < len(word):
        if target[i] == word[j]:
            i, j = i + 1, j + 1
        elif target[i].isdigit():
            k = 0
            while i < len(target) and target[i].isdigit():
                k = k * 10 + int(target[i])
                i += 1
            j += k
        else:
            return False
    return i == len(target) and j == len(word)

def min_abbreviation(target, dictionary):
    ans = target
    for k in range(0, len(target) + 1):
        for i in range(0, len(target) - k + 1):
            current = abbreviate(target, k, i)
            if len(current) < len(ans):
                valid = True
                for word in dictionary:
                    if is_abbreviation(current, word):
                        valid = False
                        break
                if valid:
                    ans = current
    return ans
```
The algorithm first defines a helper function `abbreviate` to generate the abbreviations of the input string. It takes in a string, an abbreviation position, and a counter. This function generates abbreviated strings by recursively replacing substrings at the abbreviation position with their lengths, and concatenating the output.

The main function then iterates through all possible abbreviation lengths, from 0 up to the length of the target string, and for each length, it calculates the abbreviation using the helper function `abbreviate`. For each abbreviation, it checks if this abbreviation is valid, i.e., it's not an abbreviation of any word in the dictionary. If it's not an abbreviation of any word in the dictionary and its length is less than the current answer, it updates the answer.

The validation of an abbreviation is done using another helper function `isAbbreviation`. It takes in a target abbreviation and a dictionary word and checks if the target abbreviation is an abbreviation of the dictionary word by iterating through both strings and comparing characters. If the characters at the current positions match, it moves to the next positions in both strings. If the character in the target string is a digit, it's considered as an abbreviation of part of the dictionary word, and the current position in the dictionary word is updated accordingly. If the characters don't match and the target character is not a digit, it means the target abbreviation is not an abbreviation of the dictionary word.

The time complexity is of the algorithm is O(n * m * 2^m), where n is the length of the dictionary and m is the length of the target string, because there are 2^m possible abbreviations for each string, and for each abbreviation, it checks n words in the dictionary. The space complexity is O(m) for the recursive `abbreviate` function.

## A solution in Javascript

```javascript
function abbreviate(s, k, i) {
    if (i === s.length) {
        return (k > 0) ? String(k) : "";
    }
    if (k === 0) {
        return s.slice(i) + (i + 1 < s.length ? abbreviate(s, 1, i + 1) : "");
    }
    return String(k) + s[i] + (i + 1 < s.length ? abbreviate(s, 1, i + 1) : "");
}

function isAbbreviation(target, word) {
    let i = 0, j = 0;
    while (i < target.length && j < word.length) {
        if (target[i] === word[j]) {
            i++; j++;
        } else if (target[i] >= '0' && target[i] <= '9') {
            let k = 0;
            while (i < target.length && target[i] >= '0' && target[i] <= '9') {
                k = k * 10 + parseInt(target[i++]);
            }
            j += k;
        } else {
            return false;
        }
    }
    return (i === target.length && j === word.length);
}

function minAbbreviation(target, dictionary) {
    let ans = target;
    for (let k = 0; k <= target.length; k++) {
        for (let i = 0; i <= target.length - k; i++) {
            let current = abbreviate(target, k, i);
            if (current.length < ans.length) {
                let valid = true;
                for (const word of dictionary) {
                    if (isAbbreviation(current, word)) {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    ans = current;
                }
            }
        }
    }
    return ans;
}
```
The algorithm first defines a helper function `abbreviate` to generate the abbreviations of the input string. It takes in a string, an abbreviation position, and a counter. This function generates abbreviated strings by recursively replacing substrings at the abbreviation position with their lengths, and concatenating the output.

The main function then iterates through all possible abbreviation lengths, from 0 up to the length of the target string, and for each length, it calculates the abbreviation using the helper function `abbreviate`. For each abbreviation, it checks if this abbreviation is valid, i.e., it's not an abbreviation of any word in the dictionary. If it's not an abbreviation of any word in the dictionary and its length is less than the current answer, it updates the answer.

The validation of an abbreviation is done using another helper function `isAbbreviation`. It takes in a target abbreviation and a dictionary word and checks if the target abbreviation is an abbreviation of the dictionary word by iterating through both strings and comparing characters. If the characters at the current positions match, it moves to the next positions in both strings. If the character in the target string is a digit, it's considered as an abbreviation of part of the dictionary word, and the current position in the dictionary word is updated accordingly. If the characters don't match and the target character is not a digit, it means the target abbreviation is not an abbreviation of the dictionary word.

The time complexity is of the algorithm is O(n * m * 2^m), where n is the length of the dictionary and m is the length of the target string, because there are 2^m possible abbreviations for each string, and for each abbreviation, it checks n words in the dictionary. The space complexity is O(m) for the recursive `abbreviate` function.


# Fizz Buzz

- slug: fizz-buzz
- difficulty: Easy

Given an integer `n`, return _a string array_ `answer` _(**1-indexed**) where_:

*   `answer[i] == "FizzBuzz "` if `i` is divisible by `3` and `5`.
*   `answer[i] == "Fizz "` if `i` is divisible by `3`.
*   `answer[i] == "Buzz "` if `i` is divisible by `5`.
*   `answer[i] == i` (as a string) if none of the above conditions are true.

**Example 1:**

**Input:** n = 3
**Output:** \["1","2","Fizz"\]

**Example 2:**

**Input:** n = 5
**Output:** \["1","2","Fizz","4","Buzz"\]

**Example 3:**

**Input:** n = 15
**Output:** \["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"\]

**Constraints:**

*   `1 <= n <= 104`

## A solution in Java

```java
import java.util.ArrayList;

public ArrayList<String> fizzBuzz(int n) {
    ArrayList<String> result = new ArrayList<>();
    for (int i = 1; i <= n; i++) {
        if (i % 15 == 0) result.add("FizzBuzz");
        else if (i % 3 == 0) result.add("Fizz");
        else if (i % 5 == 0) result.add("Buzz");
        else result.add(Integer.toString(i));
    }
    return result;
}
```
The algorithm for this problem simply consists of iterating over the integers from 1 to n, checking the divisibility rules for FizzBuzz, and inserting the appropriate string into the array for each index. For each number i in the range [1,n], we check if it's divisible by 3 and 5 (i % 15 == 0), just 3 (i % 3 == 0), just 5 (i % 5 == 0), or none of the above. Based on the conditions met, we append the corresponding string to the array (i.e., "FizzBuzz", "Fizz", "Buzz", or the number itself as a string).

The code implementations in each language follow their respective syntax, but the core logic is the same across all languages.

## A solution in C++

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

std::vector<std::string> fizzBuzz(int n) {
    std::vector<std::string> result(n);
    for(int i = 1; i <= n; ++i) {
        if (i % 15 == 0) result[i - 1] = "FizzBuzz";
        else if (i % 3 == 0) result[i - 1] = "Fizz";
        else if (i % 5 == 0) result[i - 1] = "Buzz";
        else result[i - 1] = std::to_string(i);
    }
    return result;
}
```
The algorithm for this problem simply consists of iterating over the integers from 1 to n, checking the divisibility rules for FizzBuzz, and inserting the appropriate string into the array for each index. For each number i in the range [1,n], we check if it's divisible by 3 and 5 (i % 15 == 0), just 3 (i % 3 == 0), just 5 (i % 5 == 0), or none of the above. Based on the conditions met, we append the corresponding string to the array (i.e., "FizzBuzz", "Fizz", "Buzz", or the number itself as a string).

The code implementations in each language follow their respective syntax, but the core logic is the same across all languages.

## A solution in Python

```python
def fizzBuzz(n):
    result = []
    for i in range(1, n + 1):
        if i % 15 == 0:
            result.append("FizzBuzz")
        elif i % 3 == 0:
            result.append("Fizz")
        elif i % 5 == 0:
            result.append("Buzz")
        else:
            result.append(str(i))
    return result
```
The algorithm for this problem simply consists of iterating over the integers from 1 to n, checking the divisibility rules for FizzBuzz, and inserting the appropriate string into the array for each index. For each number i in the range [1,n], we check if it's divisible by 3 and 5 (i % 15 == 0), just 3 (i % 3 == 0), just 5 (i % 5 == 0), or none of the above. Based on the conditions met, we append the corresponding string to the array (i.e., "FizzBuzz", "Fizz", "Buzz", or the number itself as a string).

The code implementations in each language follow their respective syntax, but the core logic is the same across all languages.

## A solution in Javascript

```javascript
function fizzBuzz(n) {
    let result = [];
    for (let i = 1; i <= n; i++) {
        if (i % 15 === 0) result.push("FizzBuzz");
        else if (i % 3 === 0) result.push("Fizz");
        else if (i % 5 === 0) result.push("Buzz");
        else result.push(String(i));
    }
    return result;
}
```
The algorithm for this problem simply consists of iterating over the integers from 1 to n, checking the divisibility rules for FizzBuzz, and inserting the appropriate string into the array for each index. For each number i in the range [1,n], we check if it's divisible by 3 and 5 (i % 15 == 0), just 3 (i % 3 == 0), just 5 (i % 5 == 0), or none of the above. Based on the conditions met, we append the corresponding string to the array (i.e., "FizzBuzz", "Fizz", "Buzz", or the number itself as a string).

The code implementations in each language follow their respective syntax, but the core logic is the same across all languages.


# Arithmetic Slices

- slug: arithmetic-slices
- difficulty: Medium

An integer array is called arithmetic if it consists of **at least three elements** and if the difference between any two consecutive elements is the same.

*   For example, `[1,3,5,7,9]`, `[7,7,7,7]`, and `[3,-1,-5,-9]` are arithmetic sequences.

Given an integer array `nums`, return _the number of arithmetic **subarrays** of_ `nums`.

A **subarray** is a contiguous subsequence of the array.

**Example 1:**

**Input:** nums = \[1,2,3,4\]
**Output:** 3
**Explanation:** We have 3 arithmetic slices in nums: \[1, 2, 3\], \[2, 3, 4\] and \[1,2,3,4\] itself.

**Example 2:**

**Input:** nums = \[1\]
**Output:** 0

**Constraints:**

*   `1 <= nums.length <= 5000`
*   `-1000 <= nums[i] <= 1000`

## A solution in Java

```java
public int numberOfArithmeticSlices(int[] nums) {
    int n = nums.length, count = 0, cur = 0;
    for (int i = 2; i < n; ++i) {
        if (nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]) {
            cur++;
            count += cur;
        } else {
            cur = 0;
        }
    }
    return count;
}
```
The algorithm iterates through the given integer array `nums`. Starting from the third element (index 2), for each element, it checks if the difference between the current and the previous element is the same as the difference between the previous and the element before the previous one. If the differences are the same, that means we have an arithmetic subarray, so we increment the `cur` value to keep track of the consecutive arithmetic subarrays, and then add `cur` to the `count` which tracks the total number of arithmetic subarrays. If the differences are not the same, we reset `cur` to 0. Finally, the `count` is returned as the result.

## A solution in C++

```cpp
int numberOfArithmeticSlices(vector<int>& nums) {
    int n = nums.size(), count = 0, cur = 0;
    for (int i = 2; i < n; ++i) {
        if (nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]) {
            cur++;
            count += cur;
        } else {
            cur = 0;
        }
    }
    return count;
}
```
The algorithm iterates through the given integer array `nums`. Starting from the third element (index 2), for each element, it checks if the difference between the current and the previous element is the same as the difference between the previous and the element before the previous one. If the differences are the same, that means we have an arithmetic subarray, so we increment the `cur` value to keep track of the consecutive arithmetic subarrays, and then add `cur` to the `count` which tracks the total number of arithmetic subarrays. If the differences are not the same, we reset `cur` to 0. Finally, the `count` is returned as the result.

## A solution in Python

```python
def numberOfArithmeticSlices(nums):
    n = len(nums)
    count, cur = 0, 0
    for i in range(2, n):
        if nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]:
            cur += 1
            count += cur
        else:
            cur = 0
    return count
```
The algorithm iterates through the given integer array `nums`. Starting from the third element (index 2), for each element, it checks if the difference between the current and the previous element is the same as the difference between the previous and the element before the previous one. If the differences are the same, that means we have an arithmetic subarray, so we increment the `cur` value to keep track of the consecutive arithmetic subarrays, and then add `cur` to the `count` which tracks the total number of arithmetic subarrays. If the differences are not the same, we reset `cur` to 0. Finally, the `count` is returned as the result.

## A solution in Javascript

```javascript
function numberOfArithmeticSlices(nums) {
    let n = nums.length, count = 0, cur = 0;
    for (let i = 2; i < n; ++i) {
        if (nums[i] - nums[i - 1] === nums[i - 1] - nums[i - 2]) {
            cur++;
            count += cur;
        } else {
            cur = 0;
        }
    }
    return count;
}
```
The algorithm iterates through the given integer array `nums`. Starting from the third element (index 2), for each element, it checks if the difference between the current and the previous element is the same as the difference between the previous and the element before the previous one. If the differences are the same, that means we have an arithmetic subarray, so we increment the `cur` value to keep track of the consecutive arithmetic subarrays, and then add `cur` to the `count` which tracks the total number of arithmetic subarrays. If the differences are not the same, we reset `cur` to 0. Finally, the `count` is returned as the result.


# Third Maximum Number

- slug: third-maximum-number
- difficulty: Easy

Given an integer array `nums`, return _the **third distinct maximum** number in this array. If the third maximum does not exist, return the **maximum** number_.

**Example 1:**

**Input:** nums = \[3,2,1\]
**Output:** 1
**Explanation:**
The first distinct maximum is 3.
The second distinct maximum is 2.
The third distinct maximum is 1.

**Example 2:**

**Input:** nums = \[1,2\]
**Output:** 2
**Explanation:**
The first distinct maximum is 2.
The second distinct maximum is 1.
The third distinct maximum does not exist, so the maximum (2) is returned instead.

**Example 3:**

**Input:** nums = \[2,2,3,1\]
**Output:** 1
**Explanation:**
The first distinct maximum is 3.
The second distinct maximum is 2 (both 2's are counted together since they have the same value).
The third distinct maximum is 1.

**Constraints:**

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

**Follow up:** Can you find an `O(n)` solution?

## A solution in Java

```java
import java.util.TreeSet;

public int thirdMax(int[] nums) {
    TreeSet<Integer> top3 = new TreeSet<>();
    for (int num : nums) {
        top3.add(num);
        if (top3.size() > 3) {
            top3.remove(top3.first());
        }
    }
    return top3.size() == 3 ? top3.first() : top3.last();
}
```
The algorithm to solve the problem is as follows:
1. Initialize an empty set called `top3` to keep track of the top 3 distinct maximum numbers in the array.
2. Iterate through the input array, `nums`.
3. For each number in `nums`, insert it into `top3`.
4. If the size of `top3` becomes greater than 3, remove the smallest number in `top3`.
5. If the size of `top3` is 3, which means there are three distinct maximum numbers, return the smallest number in `top3`. Otherwise, return the largest number in `top3`.

## A solution in C++

```cpp
#include <set>

int thirdMax(vector<int>& nums) {
    set<int> top3;
    for (int num : nums) {
        top3.insert(num);
        if (top3.size() > 3) {
            top3.erase(top3.begin());
        }
    }
    return top3.size() == 3 ? *top3.begin() : *top3.rbegin();
}
```
The algorithm to solve the problem is as follows:
1. Initialize an empty set called `top3` to keep track of the top 3 distinct maximum numbers in the array.
2. Iterate through the input array, `nums`.
3. For each number in `nums`, insert it into `top3`.
4. If the size of `top3` becomes greater than 3, remove the smallest number in `top3`.
5. If the size of `top3` is 3, which means there are three distinct maximum numbers, return the smallest number in `top3`. Otherwise, return the largest number in `top3`.

## A solution in Python

```python
def third_max(nums):
    top3 = set()
    for num in nums:
        top3.add(num)
        if len(top3) > 3:
            top3.remove(min(top3))
    return min(top3) if len(top3) == 3 else max(top3)
```
The algorithm to solve the problem is as follows:
1. Initialize an empty set called `top3` to keep track of the top 3 distinct maximum numbers in the array.
2. Iterate through the input array, `nums`.
3. For each number in `nums`, insert it into `top3`.
4. If the size of `top3` becomes greater than 3, remove the smallest number in `top3`.
5. If the size of `top3` is 3, which means there are three distinct maximum numbers, return the smallest number in `top3`. Otherwise, return the largest number in `top3`.

## A solution in Javascript

```javascript
function thirdMax(nums) {
    const top3 = new Set();
    for (const num of nums) {
        top3.add(num);
        if (top3.size > 3) {
            top3.delete(Math.min(...top3));
        }
    }
    return top3.size === 3 ? Math.min(...top3) : Math.max(...top3);
}
```
The algorithm to solve the problem is as follows:
1. Initialize an empty set called `top3` to keep track of the top 3 distinct maximum numbers in the array.
2. Iterate through the input array, `nums`.
3. For each number in `nums`, insert it into `top3`.
4. If the size of `top3` becomes greater than 3, remove the smallest number in `top3`.
5. If the size of `top3` is 3, which means there are three distinct maximum numbers, return the smallest number in `top3`. Otherwise, return the largest number in `top3`.


# Add Strings

- slug: add-strings
- difficulty: Easy

Given two non-negative integers, `num1` and `num2` represented as string, return _the sum of_ `num1` _and_ `num2` _as a string_.

You must solve the problem without using any built-in library for handling large integers (such as `BigInteger`). You must also not convert the inputs to integers directly.

**Example 1:**

**Input:** num1 =  "11 ", num2 =  "123 "
**Output:**  "134 "

**Example 2:**

**Input:** num1 =  "456 ", num2 =  "77 "
**Output:**  "533 "

**Example 3:**

**Input:** num1 =  "0 ", num2 =  "0 "
**Output:**  "0 "

**Constraints:**

*   `1 <= num1.length, num2.length <= 104`
*   `num1` and `num2` consist of only digits.
*   `num1` and `num2` don't have any leading zeros except for the zero itself.

## A solution in Java

```java
public String addStrings(String num1, String num2) {
    int i = num1.length() - 1, j = num2.length() - 1, carry = 0;
    StringBuilder result = new StringBuilder();

    while (i >= 0 || j >= 0 || carry != 0) {
        int sum = carry;

        if (i >= 0) {
            sum += num1.charAt(i) - '0';
            --i;
        }
        if (j >= 0) {
            sum += num2.charAt(j) - '0';
            --j;
        }

        carry = sum / 10;
        result.append(sum % 10);
    }

    return result.reverse().toString();
}
```
1. Initialize pointers `i` and `j` to the end of `num1` and `num2`, a `carry` variable to 0, and an empty `result` container.
2. While there are still digits to process or a carry to propagate:
   a. Initialize a `sum` variable with the current carry.
   b. Add the current digits from num`1[i]` and `num2[j]` to `sum` if exist, decreasing `i` and `j` respectively after each addition.
   c. Update the value of `carry` to be the integer division of `sum` by 10.
   d. Add the value of `sum % 10` to the `result` container.
3. Return the reversed `result` container as a string.

## A solution in C++

```cpp
std::string addStrings(std::string num1, std::string num2) {
    int i = num1.size() - 1, j = num2.size() - 1, carry = 0;
    std::string result;

    while (i >= 0 || j >= 0 || carry) {
        int sum = carry;

        if (i >= 0) {
            sum += num1[i] - '0';
            --i;
        }
        if (j >= 0) {
            sum += num2[j] - '0';
            --j;
        }

        carry = sum / 10;
        result.push_back(sum % 10 + '0');
    }

    std::reverse(result.begin(), result.end());
    return result;
}
```
1. Initialize pointers `i` and `j` to the end of `num1` and `num2`, a `carry` variable to 0, and an empty `result` container.
2. While there are still digits to process or a carry to propagate:
   a. Initialize a `sum` variable with the current carry.
   b. Add the current digits from num`1[i]` and `num2[j]` to `sum` if exist, decreasing `i` and `j` respectively after each addition.
   c. Update the value of `carry` to be the integer division of `sum` by 10.
   d. Add the value of `sum % 10` to the `result` container.
3. Return the reversed `result` container as a string.

## A solution in Python

```python
def addStrings(num1: str, num2: str) -> str:
    i, j, carry, result = len(num1) - 1, len(num2) - 1, 0, []

    while i >= 0 or j >= 0 or carry:
        sum = carry

        if i >= 0:
            sum += int(num1[i])
            i -= 1
        if j >= 0:
            sum += int(num2[j])
            j -= 1

        carry = sum // 10
        result.append(str(sum % 10))

    return ''.join(result[::-1])
```
1. Initialize pointers `i` and `j` to the end of `num1` and `num2`, a `carry` variable to 0, and an empty `result` container.
2. While there are still digits to process or a carry to propagate:
   a. Initialize a `sum` variable with the current carry.
   b. Add the current digits from num`1[i]` and `num2[j]` to `sum` if exist, decreasing `i` and `j` respectively after each addition.
   c. Update the value of `carry` to be the integer division of `sum` by 10.
   d. Add the value of `sum % 10` to the `result` container.
3. Return the reversed `result` container as a string.

## A solution in Javascript

```javascript
function addStrings(num1, num2) {
    let i = num1.length - 1, j = num2.length - 1, carry = 0;
    let result = [];

    while (i >= 0 || j >= 0 || carry) {
        let sum = carry;

        if (i >= 0) {
            sum += parseInt(num1[i]);
            --i;
        }
        if (j >= 0) {
            sum += parseInt(num2[j]);
            --j;
        }

        carry = Math.floor(sum / 10);
        result.push(sum % 10);
    }

    return result.reverse().join('');
}
```
1. Initialize pointers `i` and `j` to the end of `num1` and `num2`, a `carry` variable to 0, and an empty `result` container.
2. While there are still digits to process or a carry to propagate:
   a. Initialize a `sum` variable with the current carry.
   b. Add the current digits from num`1[i]` and `num2[j]` to `sum` if exist, decreasing `i` and `j` respectively after each addition.
   c. Update the value of `carry` to be the integer division of `sum` by 10.
   d. Add the value of `sum % 10` to the `result` container.
3. Return the reversed `result` container as a string.


# Partition Equal Subset Sum

- slug: partition-equal-subset-sum
- difficulty: Medium

Given an integer array `nums`, return `true` _if you can partition the array into two subsets such that the sum of the elements in both subsets is equal or_ `false` _otherwise_.

**Example 1:**

**Input:** nums = \[1,5,11,5\]
**Output:** true
**Explanation:** The array can be partitioned as \[1, 5, 5\] and \[11\].

**Example 2:**

**Input:** nums = \[1,2,3,5\]
**Output:** false
**Explanation:** The array cannot be partitioned into equal sum subsets.

**Constraints:**

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

## A solution in Java

```java
public boolean canPartition(int[] nums) {
    int sum = 0;
    for (int num : nums) sum += num;

    if (sum % 2 != 0) return false;

    int target = sum / 2;
    boolean[] dp = new boolean[target + 1];
    dp[0] = true;

    for (int num : nums) {
        for (int i = target; i >= num; i--) {
            dp[i] = dp[i] || dp[i - num];
        }
    }
    return dp[target];
}
```
The algorithm is using Dynamic Programming to solve the partition problem. To determine if the array can be divided into two subsets with equal sum, first find the total sum of the array. If the total sum is odd, it's not possible to divide it into two equal subsets, so return false. If the total sum is even, find the target sum by dividing the total sum by 2.

The key idea is to find if there is a subset whose sum is equal to the target sum. Create a boolean dp array, where dp[i] represents if there is a subset with sum i. Initialize dp[0] to true, since the sum of 0 can be achieved with an empty subset.

Iterate through each number in the array, and for each number, iterate through the dp array backwards starting from the target sum. Update dp[i] to be true if dp[i - num] is true, meaning a subset with sum i - num is possible, and adding the current number num results in a subset with sum i.

Finally, if dp[target] is true, it means there is a subset in the array with sum equal to target, so the array can be partitioned into two equal subsets. Otherwise, it cannot be partitioned.

## A solution in C++

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

bool canPartition(vector<int>& nums) {
    int sum = 0;
    for (int num : nums) sum += num;

    if (sum % 2 != 0) return false;

    int target = sum / 2;
    vector<bool> dp(target + 1, false);
    dp[0] = true;

    for (int num : nums) {
        for (int i = target; i >= num; i--) {
            dp[i] = dp[i] || dp[i - num];
        }
    }
    return dp[target];
}
```
The algorithm is using Dynamic Programming to solve the partition problem. To determine if the array can be divided into two subsets with equal sum, first find the total sum of the array. If the total sum is odd, it's not possible to divide it into two equal subsets, so return false. If the total sum is even, find the target sum by dividing the total sum by 2.

The key idea is to find if there is a subset whose sum is equal to the target sum. Create a boolean dp array, where dp[i] represents if there is a subset with sum i. Initialize dp[0] to true, since the sum of 0 can be achieved with an empty subset.

Iterate through each number in the array, and for each number, iterate through the dp array backwards starting from the target sum. Update dp[i] to be true if dp[i - num] is true, meaning a subset with sum i - num is possible, and adding the current number num results in a subset with sum i.

Finally, if dp[target] is true, it means there is a subset in the array with sum equal to target, so the array can be partitioned into two equal subsets. Otherwise, it cannot be partitioned.

## A solution in Python

```python
def canPartition(nums):
    total_sum = sum(nums)
    if total_sum % 2 != 0:
        return False

    target = total_sum // 2
    dp = [False] * (target + 1)
    dp[0] = True

    for num in nums:
        for i in range(target, num - 1, -1):
            dp[i] = dp[i] or dp[i - num]

    return dp[target]
```
The algorithm is using Dynamic Programming to solve the partition problem. To determine if the array can be divided into two subsets with equal sum, first find the total sum of the array. If the total sum is odd, it's not possible to divide it into two equal subsets, so return false. If the total sum is even, find the target sum by dividing the total sum by 2.

The key idea is to find if there is a subset whose sum is equal to the target sum. Create a boolean dp array, where dp[i] represents if there is a subset with sum i. Initialize dp[0] to true, since the sum of 0 can be achieved with an empty subset.

Iterate through each number in the array, and for each number, iterate through the dp array backwards starting from the target sum. Update dp[i] to be true if dp[i - num] is true, meaning a subset with sum i - num is possible, and adding the current number num results in a subset with sum i.

Finally, if dp[target] is true, it means there is a subset in the array with sum equal to target, so the array can be partitioned into two equal subsets. Otherwise, it cannot be partitioned.

## A solution in Javascript

```javascript
function canPartition(nums) {
    const sum = nums.reduce((a, b) => a + b);
    if (sum % 2 !== 0) return false;

    const target = sum / 2;
    const dp = new Array(target + 1).fill(false);
    dp[0] = true;

    for (const num of nums) {
        for (let i = target; i >= num; i--) {
            dp[i] = dp[i] || dp[i - num];
        }
    }
    return dp[target];
}
```
The algorithm is using Dynamic Programming to solve the partition problem. To determine if the array can be divided into two subsets with equal sum, first find the total sum of the array. If the total sum is odd, it's not possible to divide it into two equal subsets, so return false. If the total sum is even, find the target sum by dividing the total sum by 2.

The key idea is to find if there is a subset whose sum is equal to the target sum. Create a boolean dp array, where dp[i] represents if there is a subset with sum i. Initialize dp[0] to true, since the sum of 0 can be achieved with an empty subset.

Iterate through each number in the array, and for each number, iterate through the dp array backwards starting from the target sum. Update dp[i] to be true if dp[i - num] is true, meaning a subset with sum i - num is possible, and adding the current number num results in a subset with sum i.

Finally, if dp[target] is true, it means there is a subset in the array with sum equal to target, so the array can be partitioned into two equal subsets. Otherwise, it cannot be partitioned.


# Pacific Atlantic Water Flow

- slug: pacific-atlantic-water-flow
- difficulty: Medium

There is an `m x n` rectangular island that borders both the **Pacific Ocean** and **Atlantic Ocean**. The **Pacific Ocean** touches the island's left and top edges, and the **Atlantic Ocean** touches the island's right and bottom edges.

The island is partitioned into a grid of square cells. You are given an `m x n` integer matrix `heights` where `heights[r][c]` represents the **height above sea level** of the cell at coordinate `(r, c)`.

The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell's height is **less than or equal to** the current cell's height. Water can flow from any cell adjacent to an ocean into the ocean.

Return _a **2D list** of grid coordinates_ `result` _where_ `result[i] = [ri, ci]` _denotes that rain water can flow from cell_ `(ri, ci)` _to **both** the Pacific and Atlantic oceans_.

**Example 1:**

**Input:** heights = \[\[1,2,2,3,5\],\[3,2,3,4,4\],\[2,4,5,3,1\],\[6,7,1,4,5\],\[5,1,1,2,4\]\]
**Output:** \[\[0,4\],\[1,3\],\[1,4\],\[2,2\],\[3,0\],\[3,1\],\[4,0\]\]
**Explanation:** The following cells can flow to the Pacific and Atlantic oceans, as shown below:
\[0,4\]: \[0,4\] -> Pacific Ocean
       \[0,4\] -> Atlantic Ocean
\[1,3\]: \[1,3\] -> \[0,3\] -> Pacific Ocean
       \[1,3\] -> \[1,4\] -> Atlantic Ocean
\[1,4\]: \[1,4\] -> \[1,3\] -> \[0,3\] -> Pacific Ocean
       \[1,4\] -> Atlantic Ocean
\[2,2\]: \[2,2\] -> \[1,2\] -> \[0,2\] -> Pacific Ocean
       \[2,2\] -> \[2,3\] -> \[2,4\] -> Atlantic Ocean
\[3,0\]: \[3,0\] -> Pacific Ocean
       \[3,0\] -> \[4,0\] -> Atlantic Ocean
\[3,1\]: \[3,1\] -> \[3,0\] -> Pacific Ocean
       \[3,1\] -> \[4,1\] -> Atlantic Ocean
\[4,0\]: \[4,0\] -> Pacific Ocean
       \[4,0\] -> Atlantic Ocean
Note that there are other possible paths for these cells to flow to the Pacific and Atlantic oceans.

**Example 2:**

**Input:** heights = \[\[1\]\]
**Output:** \[\[0,0\]\]
**Explanation:** The water can flow from the only cell to the Pacific and Atlantic oceans.

**Constraints:**

*   `m == heights.length`
*   `n == heights[r].length`
*   `1 <= m, n <= 200`
*   `0 <= heights[r][c] <= 105`

## A solution in Java

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

public List<int[]> pacificAtlantic(int[][] heights) {
    int m = heights.length;
    int n = heights[0].length;
    boolean[][] pacific = new boolean[m][n];
    boolean[][] atlantic = new boolean[m][n];

    for (int r = 0; r < m; ++r) {
        dfs(heights, r, 0, -1, pacific);
        dfs(heights, r, n - 1, -1, atlantic);
    }
    for (int c = 0; c < n; ++c) {
        dfs(heights, 0, c, -1, pacific);
        dfs(heights, m - 1, c, -1, atlantic);
    }
    List<int[]> result = new ArrayList<>();
    for (int r = 0; r < m; ++r) {
        for (int c = 0; c < n; ++c) {
            if (pacific[r][c] && atlantic[r][c]) {
                result.add(new int[]{r, c});
            }
        }
    }
    return result;
}

private void dfs(int[][] heights, int r, int c, int prevHeight, boolean[][] visited) {
    if (r < 0 || r >= heights.length || c < 0 || c >= heights[0].length) return;
    if (heights[r][c] >= prevHeight && !visited[r][c]) {
        visited[r][c] = true;
        dfs(heights, r - 1, c, heights[r][c], visited);
        dfs(heights, r + 1, c, heights[r][c], visited);
        dfs(heights, r, c - 1, heights[r][c], visited);
        dfs(heights, r, c + 1, heights[r][c], visited);
    }
}
```
We use DFS to traverse the island, starting from the ocean borders. We create two separate matrices (`pacific` and `atlantic`) keeping track of which cells can flow water to the corresponding ocean. For each cell, we perform DFS in all 4 directions if the neighboring cell's height is less than or equal to the current cell's height.

After finishing the DFS search for both oceans, we iterate through the matrices to find the intersections (cells that can flow water to both oceans). If a cell can flow water to both oceans, we add its coordinates to the result list.

## A solution in C++

```cpp
#include <vector>

using namespace std;

void dfs(const vector<vector<int>>& heights, int r, int c, int prevHeight, vector<vector<bool>>& visited) {
    if (r < 0 || r >= heights.size() || c < 0 || c >= heights[0].size())
        return;
    if (heights[r][c] >= prevHeight && !visited[r][c]) {
        visited[r][c] = true;
        dfs(heights, r - 1, c, heights[r][c], visited);
        dfs(heights, r + 1, c, heights[r][c], visited);
        dfs(heights, r, c - 1, heights[r][c], visited);
        dfs(heights, r, c + 1, heights[r][c], visited);
    }
}

vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
    int m = heights.size();
    int n = heights[0].size();
    vector<vector<bool>> pacific(m, vector<bool>(n, false));
    vector<vector<bool>> atlantic(m, vector<bool>(n, false));

    for (int r = 0; r < m; ++r) {
        dfs(heights, r, 0, -1, pacific);
        dfs(heights, r, n - 1, -1, atlantic);
    }
    for (int c = 0; c < n; ++c) {
        dfs(heights, 0, c, -1, pacific);
        dfs(heights, m - 1, c, -1, atlantic);
    }
    vector<vector<int>> result;
    for (int r = 0; r < m; ++r) {
        for (int c = 0; c < n; ++c) {
            if (pacific[r][c] && atlantic[r][c]) {
                result.push_back({r, c});
            }
        }
    }
    return result;
}
```
We use DFS to traverse the island, starting from the ocean borders. We create two separate matrices (`pacific` and `atlantic`) keeping track of which cells can flow water to the corresponding ocean. For each cell, we perform DFS in all 4 directions if the neighboring cell's height is less than or equal to the current cell's height.

After finishing the DFS search for both oceans, we iterate through the matrices to find the intersections (cells that can flow water to both oceans). If a cell can flow water to both oceans, we add its coordinates to the result list.

## A solution in Python

```python
def pacificAtlantic(heights):
    def dfs(r, c, prev_height, visited):
        if not (0 <= r < len(heights)) or not (0 <= c < len(heights[0])):
            return
        if heights[r][c] >= prev_height and not visited[r][c]:
            visited[r][c] = True
            dfs(r - 1, c, heights[r][c], visited)
            dfs(r + 1, c, heights[r][c], visited)
            dfs(r, c - 1, heights[r][c], visited)
            dfs(r, c + 1, heights[r][c], visited)

    m, n = len(heights), len(heights[0])
    pacific = [[False] * n for _ in range(m)]
    atlantic = [[False] * n for _ in range(m)]

    for r in range(m):
        dfs(r, 0, -1, pacific)
        dfs(r, n - 1, -1, atlantic)
    for c in range(n):
        dfs(0, c, -1, pacific)
        dfs(m - 1, c, -1, atlantic)

    result = []
    for r in range(m):
        for c in range(n):
            if pacific[r][c] and atlantic[r][c]:
                result.append([r, c])
    return result
```
We use DFS to traverse the island, starting from the ocean borders. We create two separate matrices (`pacific` and `atlantic`) keeping track of which cells can flow water to the corresponding ocean. For each cell, we perform DFS in all 4 directions if the neighboring cell's height is less than or equal to the current cell's height.

After finishing the DFS search for both oceans, we iterate through the matrices to find the intersections (cells that can flow water to both oceans). If a cell can flow water to both oceans, we add its coordinates to the result list.

## A solution in Javascript

```javascript
function pacificAtlantic(heights) {
    function dfs(r, c, prevHeight, visited) {
        if (r < 0 || r >= heights.length || c < 0 || c >= heights[0].length) return;
        if (heights[r][c] >= prevHeight && !visited[r][c]) {
            visited[r][c] = true;
            dfs(r - 1, c, heights[r][c], visited);
            dfs(r + 1, c, heights[r][c], visited);
            dfs(r, c - 1, heights[r][c], visited);
            dfs(r, c + 1, heights[r][c], visited);
        }
    }

    const m = heights.length;
    const n = heights[0].length;
    const pacific = Array.from(Array(m), () => new Array(n).fill(false));
    const atlantic = Array.from(Array(m), () => new Array(n).fill(false));

    for (let r = 0; r < m; ++r) {
        dfs(r, 0, -1, pacific);
        dfs(r, n - 1, -1, atlantic);
    }
    for (let c = 0; c < n; ++c) {
        dfs(0, c, -1, pacific);
        dfs(m - 1, c, -1, atlantic);
    }
    const result = [];
    for (let r = 0; r < m; ++r) {
        for (let c = 0; c < n; ++c) {
            if (pacific[r][c] && atlantic[r][c]) {
                result.push([r, c]);
            }
        }
    }
    return result;
}
```
We use DFS to traverse the island, starting from the ocean borders. We create two separate matrices (`pacific` and `atlantic`) keeping track of which cells can flow water to the corresponding ocean. For each cell, we perform DFS in all 4 directions if the neighboring cell's height is less than or equal to the current cell's height.

After finishing the DFS search for both oceans, we iterate through the matrices to find the intersections (cells that can flow water to both oceans). If a cell can flow water to both oceans, we add its coordinates to the result list.