# Swim in Rising Water

- slug: swim-in-rising-water
- difficulty: Hard

You are given an `n x n` integer matrix `grid` where each value `grid[i][j]` represents the elevation at that point `(i, j)`.

The rain starts to fall. At time `t`, the depth of the water everywhere is `t`. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most `t`. You can swim infinite distances in zero time. Of course, you must stay within the boundaries of the grid during your swim.

Return _the least time until you can reach the bottom right square_ `(n - 1, n - 1)` _if you start at the top left square_ `(0, 0)`.

**Example 1:**

**Input:** grid = \[\[0,2\],\[1,3\]\]
**Output:** 3
Explanation:
At time 0, you are in grid location (0, 0).
You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0.
You cannot reach point (1, 1) until time 3.
When the depth of water is 3, we can swim anywhere inside the grid.

**Example 2:**

**Input:** grid = \[\[0,1,2,3,4\],\[24,23,22,21,5\],\[12,13,14,15,16\],\[11,17,18,19,20\],\[10,9,8,7,6\]\]
**Output:** 16
**Explanation:** The final route is shown.
We need to wait until time 16 so that (0, 0) and (4, 4) are connected.

**Constraints:**

*   `n == grid.length`
*   `n == grid[i].length`
*   `1 <= n <= 50`
*   `0 <= grid[i][j] < n2`
*   Each value `grid[i][j]` is **unique**.

## A solution in Java

```java
import java.util.PriorityQueue;
import java.util.HashMap;

public String rearrangeString(String s) {
    HashMap<Character, Integer> counts = new HashMap<>();
    for (char c : s.toCharArray()) {
        counts.put(c, counts.getOrDefault(c, 0) + 1);
    }

    PriorityQueue<Character> pq = new PriorityQueue<>((a, b) -> counts.get(b) - counts.get(a));
    pq.addAll(counts.keySet());

    StringBuilder result = new StringBuilder();
    Character previous = null;

    while (!pq.isEmpty()) {
        char current = pq.remove();
        result.append(current);

        if (previous != null && counts.get(previous) > 0) {
            pq.add(previous);
        }

        counts.put(current, counts.get(current) - 1);
        previous = current;
    }

    return result.length() == s.length() ? result.toString() : "";
}
```
The algorithm uses a priority queue to store characters and their counts in descending order based on the counts. Then, it iterates over the priority queue, adding the character with the highest count to the result string. After adding a character to the result, its count is decremented. If the previously added character's count is still positive, it is added back to the priority queue.

The priority queue is used to ensure that the characters with the highest counts are placed as far apart as possible in the resultant string. If it is possible to rearrange the string, the length of the result will be equal to the length of the input string. If not, we return an empty string, as it is not possible to form a valid rearrangement.

## A solution in C++

```cpp
#include <queue>

std::string rearrangeString(std::string s) {
    std::unordered_map<char, int> counts;
    for (char c : s) {
        counts[c]++;
    }

    auto cmp = [](const auto& a, const auto& b) {
        return a.second < b.second;
    };

    std::priority_queue<std::pair<char, int>, std::vector<std::pair<char, int>>, decltype(cmp)> pq(cmp);

    for (auto& count : counts) {
        pq.push(count);
    }

    std::string result;
    std::pair<char, int> previous = {-1, 0};

    while (!pq.empty()) {
        auto current = pq.top();
        pq.pop();
        result += current.first;

        if (previous.second > 0) {
            pq.push(previous);
        }

        current.second--;
        previous = current;
    }

    return result.size() == s.size() ? result : "";
}
```
The algorithm uses a priority queue to store characters and their counts in descending order based on the counts. Then, it iterates over the priority queue, adding the character with the highest count to the result string. After adding a character to the result, its count is decremented. If the previously added character's count is still positive, it is added back to the priority queue.

The priority queue is used to ensure that the characters with the highest counts are placed as far apart as possible in the resultant string. If it is possible to rearrange the string, the length of the result will be equal to the length of the input string. If not, we return an empty string, as it is not possible to form a valid rearrangement.

## A solution in Python

```python
import heapq

def rearrange_string(s):
    counts = {}
    for c in s:
        counts[c] = counts.get(c, 0) + 1

    pq = [(-count, char) for char, count in counts.items()]
    heapq.heapify(pq)

    result = []
    previous = (0, '')

    while pq:
        count, char = heapq.heappop(pq)
        result.append(char)

        if previous[0] < 0:
            heapq.heappush(pq, previous)

        count += 1
        previous = (count, char)

    result_str = ''.join(result)
    return result_str if len(result_str) == len(s) else ""
```
The algorithm uses a priority queue to store characters and their counts in descending order based on the counts. Then, it iterates over the priority queue, adding the character with the highest count to the result string. After adding a character to the result, its count is decremented. If the previously added character's count is still positive, it is added back to the priority queue.

The priority queue is used to ensure that the characters with the highest counts are placed as far apart as possible in the resultant string. If it is possible to rearrange the string, the length of the result will be equal to the length of the input string. If not, we return an empty string, as it is not possible to form a valid rearrangement.

## A solution in Javascript

```javascript
function rearrangeString(s) {
    const counts = new Map();
    for (const c of s) {
        counts.set(c, (counts.get(c) || 0) + 1);
    }

    const pq = Array.from(counts.entries()).sort((a, b) => b[1] - a[1]);

    const result = [];
    let previous = [-1, null];

    while (pq.length) {
        const current = pq.shift();
        result.push(current[0]);

        if (previous[0] > 0) {
            pq.push(previous);
        }

        current[1]--;
        previous = current;
        pq.sort((a, b) => b[1] - a[1]);
    }

    const resultStr = result.join('');
    return resultStr.length === s.length ? resultStr : "";
}
```
The algorithm uses a priority queue to store characters and their counts in descending order based on the counts. Then, it iterates over the priority queue, adding the character with the highest count to the result string. After adding a character to the result, its count is decremented. If the previously added character's count is still positive, it is added back to the priority queue.

The priority queue is used to ensure that the characters with the highest counts are placed as far apart as possible in the resultant string. If it is possible to rearrange the string, the length of the result will be equal to the length of the input string. If not, we return an empty string, as it is not possible to form a valid rearrangement.


# K-th Symbol in Grammar

- slug: k-th-symbol-in-grammar
- difficulty: Medium

We build a table of `n` rows (**1-indexed**). We start by writing `0` in the `1st` row. Now in every subsequent row, we look at the previous row and replace each occurrence of `0` with `01`, and each occurrence of `1` with `10`.

*   For example, for `n = 3`, the `1st` row is `0`, the `2nd` row is `01`, and the `3rd` row is `0110`.

Given two integer `n` and `k`, return the `kth` (**1-indexed**) symbol in the `nth` row of a table of `n` rows.

**Example 1:**

**Input:** n = 1, k = 1
**Output:** 0
**Explanation:** row 1: 0

**Example 2:**

**Input:** n = 2, k = 1
**Output:** 0
**Explanation:**
row 1: 0
row 2: 01

**Example 3:**

**Input:** n = 2, k = 2
**Output:** 1
**Explanation:**
row 1: 0
row 2: 01

**Constraints:**

*   `1 <= n <= 30`
*   `1 <= k <= 2n - 1`

## A solution in Java

```java
public int maxChunksToSorted(int[] arr) {
    int max_val = 0, chunks = 0;
    for (int i = 0; i < arr.length; i++) {
        max_val = Math.max(max_val, arr[i]);
        if (max_val == i) {
            chunks++;
        }
    }
    return chunks;
}
```
We maintain a variable `max_val` that keeps track of the current maximum value in the array till index `i`. If the current maximum value is equal to the index, that means all elements from the beginning to the current index can be considered a chunk. We increment the `chunks` counter in that case. At the end, the counter `chunks` represents the maximum number of chunks we can make to sort the array.

## A solution in C++

```cpp
int maxChunksToSorted(vector<int>& arr) {
    int max_val = 0, chunks = 0;
    for (int i = 0; i < arr.size(); ++i) {
        max_val = max(max_val, arr[i]);
        if (max_val == i) {
            chunks++;
        }
    }
    return chunks;
}
```
We maintain a variable `max_val` that keeps track of the current maximum value in the array till index `i`. If the current maximum value is equal to the index, that means all elements from the beginning to the current index can be considered a chunk. We increment the `chunks` counter in that case. At the end, the counter `chunks` represents the maximum number of chunks we can make to sort the array.

## A solution in Python

```python
def max_chunks_to_sorted(arr):
    max_val, chunks = 0, 0
    for i, value in enumerate(arr):
        max_val = max(max_val, value)
        if max_val == i:
            chunks += 1
    return chunks
```
We maintain a variable `max_val` that keeps track of the current maximum value in the array till index `i`. If the current maximum value is equal to the index, that means all elements from the beginning to the current index can be considered a chunk. We increment the `chunks` counter in that case. At the end, the counter `chunks` represents the maximum number of chunks we can make to sort the array.

## A solution in Javascript

```javascript
function maxChunksToSorted(arr) {
    let max_val = 0, chunks = 0;
    for (let i = 0; i < arr.length; i++) {
        max_val = Math.max(max_val, arr[i]);
        if (max_val === i) {
            chunks++;
        }
    }
    return chunks;
}
```
We maintain a variable `max_val` that keeps track of the current maximum value in the array till index `i`. If the current maximum value is equal to the index, that means all elements from the beginning to the current index can be considered a chunk. We increment the `chunks` counter in that case. At the end, the counter `chunks` represents the maximum number of chunks we can make to sort the array.


# Reaching Points

- slug: reaching-points
- difficulty: Hard

Given four integers `sx`, `sy`, `tx`, and `ty`, return `true` _if it is possible to convert the point_ `(sx, sy)` _to the point_ `(tx, ty)` _through some operations__, or_ `false` _otherwise_.

The allowed operation on some point `(x, y)` is to convert it to either `(x, x + y)` or `(x + y, y)`.

**Example 1:**

**Input:** sx = 1, sy = 1, tx = 3, ty = 5
**Output:** true
**Explanation:**
One series of moves that transforms the starting point to the target is:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)

**Example 2:**

**Input:** sx = 1, sy = 1, tx = 2, ty = 2
**Output:** false

**Example 3:**

**Input:** sx = 1, sy = 1, tx = 1, ty = 1
**Output:** true

**Constraints:**

*   `1 <= sx, sy, tx, ty <= 109`

## A solution in Java

```java
public int maxChunksToSorted(int[] arr) {
    int max_so_far = 0, count = 0;
    for (int i = 0; i < arr.length; i++) {
        max_so_far = Math.max(max_so_far, arr[i]);
        if (max_so_far == i) {
            count++;
        }
    }
    return count;
}
```
Iterate through the array and track the maximum value found so far (max_so_far), as well as the number of chunks (count). For each element in the array, update the max_so_far to the maximum of its current value and the current element. If the max_so_far is equal to the current index, it means that it is possible to create a sorted chunk from the starting index to the current index. Increase the count and continue iterating through the array until the end. Finally, return the count.

## A solution in C++

```cpp
int maxChunksToSorted(vector<int>& arr) {
    int max_so_far = 0, count = 0;
    for (int i = 0; i < arr.size(); i++) {
        max_so_far = max(max_so_far, arr[i]);
        if (max_so_far == i) {
            count++;
        }
    }
    return count;
}
```
Iterate through the array and track the maximum value found so far (max_so_far), as well as the number of chunks (count). For each element in the array, update the max_so_far to the maximum of its current value and the current element. If the max_so_far is equal to the current index, it means that it is possible to create a sorted chunk from the starting index to the current index. Increase the count and continue iterating through the array until the end. Finally, return the count.

## A solution in Python

```python
def max_chunks_to_sorted(arr):
    max_so_far, count = 0, 0
    for i, val in enumerate(arr):
        max_so_far = max(max_so_far, val)
        if max_so_far == i:
            count += 1
    return count
```
Iterate through the array and track the maximum value found so far (max_so_far), as well as the number of chunks (count). For each element in the array, update the max_so_far to the maximum of its current value and the current element. If the max_so_far is equal to the current index, it means that it is possible to create a sorted chunk from the starting index to the current index. Increase the count and continue iterating through the array until the end. Finally, return the count.

## A solution in Javascript

```javascript
function maxChunksToSorted(arr) {
    let max_so_far = 0, count = 0;
    for (let i = 0; i < arr.length; i++) {
        max_so_far = Math.max(max_so_far, arr[i]);
        if (max_so_far === i) {
            count++;
        }
    }
    return count;
}
```
Iterate through the array and track the maximum value found so far (max_so_far), as well as the number of chunks (count). For each element in the array, update the max_so_far to the maximum of its current value and the current element. If the max_so_far is equal to the current index, it means that it is possible to create a sorted chunk from the starting index to the current index. Increase the count and continue iterating through the array until the end. Finally, return the count.


# Rabbits in Forest

- slug: rabbits-in-forest
- difficulty: Medium

There is a forest with an unknown number of rabbits. We asked n rabbits **"How many rabbits have the same color as you? "** and collected the answers in an integer array `answers` where `answers[i]` is the answer of the `ith` rabbit.

Given the array `answers`, return _the minimum number of rabbits that could be in the forest_.

**Example 1:**

**Input:** answers = \[1,1,2\]
**Output:** 5
**Explanation:**
The two rabbits that answered  "1 " could both be the same color, say red.
The rabbit that answered  "2 " can't be red or the answers would be inconsistent.
Say the rabbit that answered  "2 " was blue.
Then there should be 2 other blue rabbits in the forest that didn't answer into the array.
The smallest possible number of rabbits in the forest is therefore 5: 3 that answered plus 2 that didn't.

**Example 2:**

**Input:** answers = \[10,10,10\]
**Output:** 11

**Constraints:**

*   `1 <= answers.length <= 1000`
*   `0 <= answers[i] < 1000`

## A solution in Java

```java
import java.util.HashMap;

public int numRabbits(int[] answers) {
    HashMap<Integer, Integer> count = new HashMap<>();
    int rabbits = 0;
    for(int ans : answers) {
        count.put(ans, count.getOrDefault(ans, 0) + 1);
    }
    for(int key : count.keySet()) {
        int cnt = count.get(key);
        rabbits += (key + cnt) / (key + 1) * (key + 1);
    }
    return rabbits;
}
```
The algorithm uses a hashmap (Counter in python) to count the frequency of each answer. For each answer, because rabbits of the same color give the same answer `k`, there can be `k+1` rabbits, i.e., if they all belong to the same group, there can be `k+1` rabbits of the same color. The algorithm calculates the total number of rabbits i.e. total_rabbits = required number of rabbits in each answer group * number of groups (calculated by dividing the count of the answer by k+1) * (k + 1).

## A solution in C++

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

int numRabbits(vector<int>& answers) {
    unordered_map<int, int> count;
    int rabbits = 0;
    for (int ans : answers) {
        count[ans]++;
    }
    for (auto& [ans, cnt] : count) {
        rabbits += (ans + cnt) / (ans + 1) * (ans + 1);
    }
    return rabbits;
}
```
The algorithm uses a hashmap (Counter in python) to count the frequency of each answer. For each answer, because rabbits of the same color give the same answer `k`, there can be `k+1` rabbits, i.e., if they all belong to the same group, there can be `k+1` rabbits of the same color. The algorithm calculates the total number of rabbits i.e. total_rabbits = required number of rabbits in each answer group * number of groups (calculated by dividing the count of the answer by k+1) * (k + 1).

## A solution in Python

```python
from collections import Counter

def numRabbits(answers):
    count = Counter(answers)
    rabbits = 0
    for ans, cnt in count.items():
        rabbits += (ans + cnt)//(ans + 1) * (ans + 1)
    return rabbits
```
The algorithm uses a hashmap (Counter in python) to count the frequency of each answer. For each answer, because rabbits of the same color give the same answer `k`, there can be `k+1` rabbits, i.e., if they all belong to the same group, there can be `k+1` rabbits of the same color. The algorithm calculates the total number of rabbits i.e. total_rabbits = required number of rabbits in each answer group * number of groups (calculated by dividing the count of the answer by k+1) * (k + 1).

## A solution in Javascript

```javascript
function numRabbits(answers) {
    const count = new Map();
    let rabbits = 0;
    for(let ans of answers) {
        count.set(ans, (count.get(ans) || 0) + 1);
    }
    for(let [ans, cnt] of count.entries()) {
        rabbits += Math.floor((ans + cnt) / (ans + 1)) * (ans + 1);
    }
    return rabbits;
}
```
The algorithm uses a hashmap (Counter in python) to count the frequency of each answer. For each answer, because rabbits of the same color give the same answer `k`, there can be `k+1` rabbits, i.e., if they all belong to the same group, there can be `k+1` rabbits of the same color. The algorithm calculates the total number of rabbits i.e. total_rabbits = required number of rabbits in each answer group * number of groups (calculated by dividing the count of the answer by k+1) * (k + 1).


# Transform to Chessboard

- slug: transform-to-chessboard
- difficulty: Hard

You are given an `n x n` binary grid `board`. In each move, you can swap any two rows with each other, or any two columns with each other.

Return _the minimum number of moves to transform the board into a **chessboard board**_. If the task is impossible, return `-1`.

A **chessboard board** is a board where no `0`'s and no `1`'s are 4-directionally adjacent.

**Example 1:**

**Input:** board = \[\[0,1,1,0\],\[0,1,1,0\],\[1,0,0,1\],\[1,0,0,1\]\]
**Output:** 2
**Explanation:** One potential sequence of moves is shown.
The first move swaps the first and second column.
The second move swaps the second and third row.

**Example 2:**

**Input:** board = \[\[0,1\],\[1,0\]\]
**Output:** 0
**Explanation:** Also note that the board with 0 in the top left corner, is also a valid chessboard.

**Example 3:**

**Input:** board = \[\[1,0\],\[1,0\]\]
**Output:** -1
**Explanation:** No matter what sequence of moves you make, you cannot end with a valid chessboard.

**Constraints:**

*   `n == board.length`
*   `n == board[i].length`
*   `2 <= n <= 30`
*   `board[i][j]` is either `0` or `1`.

## A solution in Java

```java
public int numJewelsInStones(String jewels, String stones) {
    int count = 0;
    for (char s : stones.toCharArray()) {
        if (jewels.indexOf(s) != -1) {
            count++;
        }
    }
    return count;
}
```
The algorithm takes two strings as input, `jewels` and `stones`. For each character `s` in the `stones` string, check whether the character `s` exists in the `jewels` string. If it exists, that means the stone is a jewel, so we increment the count. After iterating through all characters in the `stones` string, we return the count, which represents the total number of jewels in the stones.

Each respective implementation in C++, Java, Python, and JavaScript showcases the same algorithm adjusted for language-specific syntax differences. In all cases, the key aspect is to loop through the `stones` and check for membership within the string `jewels`, incrementing the count for each found jewel.

## A solution in C++

```cpp
int numJewelsInStones(string jewels, string stones) {
    int count = 0;
    for (char s : stones) {
        if (jewels.find(s) != string::npos) {
            count++;
        }
    }
    return count;
}
```
The algorithm takes two strings as input, `jewels` and `stones`. For each character `s` in the `stones` string, check whether the character `s` exists in the `jewels` string. If it exists, that means the stone is a jewel, so we increment the count. After iterating through all characters in the `stones` string, we return the count, which represents the total number of jewels in the stones.

Each respective implementation in C++, Java, Python, and JavaScript showcases the same algorithm adjusted for language-specific syntax differences. In all cases, the key aspect is to loop through the `stones` and check for membership within the string `jewels`, incrementing the count for each found jewel.

## A solution in Python

```python
def numJewelsInStones(jewels, stones):
    count = 0
    for s in stones:
        if s in jewels:
            count += 1
    return count
```
The algorithm takes two strings as input, `jewels` and `stones`. For each character `s` in the `stones` string, check whether the character `s` exists in the `jewels` string. If it exists, that means the stone is a jewel, so we increment the count. After iterating through all characters in the `stones` string, we return the count, which represents the total number of jewels in the stones.

Each respective implementation in C++, Java, Python, and JavaScript showcases the same algorithm adjusted for language-specific syntax differences. In all cases, the key aspect is to loop through the `stones` and check for membership within the string `jewels`, incrementing the count for each found jewel.

## A solution in Javascript

```javascript
function numJewelsInStones(jewels, stones) {
    let count = 0;
    for (let s of stones) {
        if (jewels.includes(s)) {
            count++;
        }
    }
    return count;
}
```
The algorithm takes two strings as input, `jewels` and `stones`. For each character `s` in the `stones` string, check whether the character `s` exists in the `jewels` string. If it exists, that means the stone is a jewel, so we increment the count. After iterating through all characters in the `stones` string, we return the count, which represents the total number of jewels in the stones.

Each respective implementation in C++, Java, Python, and JavaScript showcases the same algorithm adjusted for language-specific syntax differences. In all cases, the key aspect is to loop through the `stones` and check for membership within the string `jewels`, incrementing the count for each found jewel.


# Minimum Distance Between BST Nodes

- slug: minimum-distance-between-bst-nodes
- difficulty: Easy

Given the `root` of a Binary Search Tree (BST), return _the minimum difference between the values of any two different nodes in the tree_.

**Example 1:**

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

**Example 2:**

**Input:** root = \[1,0,48,null,null,12,49\]
**Output:** 1

**Constraints:**

*   The number of nodes in the tree is in the range `[2, 100]`.
*   `0 <= Node.val <= 105`

**Note:** This question is the same as 530: [https://leetcode.com/problems/minimum-absolute-difference-in-bst/](https://leetcode.com/problems/minimum-absolute-difference-in-bst/)

## A solution in Java

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

public TreeNode searchBST(TreeNode root, int val) {
    if (root == null || root.val == val) {
        return root;
    }
    return (root.val > val) ? searchBST(root.left, val) : searchBST(root.right, val);
}
```
We are given a binary search tree (BST) and an integer value `val`. Our task is to find the node in the tree with the same value as `val` and return the subtree rooted at that node. If there is no such node, we should return null.

To solve this problem, we use a recursive function `searchBST`. We first check whether the current `root` is null or has the value we are searching for. If either condition is true, we return the root.

Otherwise, we compare the given `val` with the current node's value. If `val` is less than the current node's value, we proceed to search the left subtree. Otherwise, we search the right subtree, and we return the result of either search.

This algorithm leverages the properties of a binary search tree, which ensures that for each node, all elements in the left subtree are less than the node, and all elements in the right subtree are greater than the node, enabling efficient search.

## A solution in C++

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

TreeNode* searchBST(TreeNode* root, int val) {
    if (!root || root->val == val) {
        return root;
    }
    return (root->val > val) ? searchBST(root->left, val) : searchBST(root->right, val);
}
```
We are given a binary search tree (BST) and an integer value `val`. Our task is to find the node in the tree with the same value as `val` and return the subtree rooted at that node. If there is no such node, we should return null.

To solve this problem, we use a recursive function `searchBST`. We first check whether the current `root` is null or has the value we are searching for. If either condition is true, we return the root.

Otherwise, we compare the given `val` with the current node's value. If `val` is less than the current node's value, we proceed to search the left subtree. Otherwise, we search the right subtree, and we return the result of either search.

This algorithm leverages the properties of a binary search tree, which ensures that for each node, all elements in the left subtree are less than the node, and all elements in the right subtree are greater than the node, enabling efficient search.

## 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 searchBST(root: TreeNode, val: int) -> TreeNode:
    if not root or root.val == val:
        return root
    return searchBST(root.left, val) if root.val > val else searchBST(root.right, val)
```
We are given a binary search tree (BST) and an integer value `val`. Our task is to find the node in the tree with the same value as `val` and return the subtree rooted at that node. If there is no such node, we should return null.

To solve this problem, we use a recursive function `searchBST`. We first check whether the current `root` is null or has the value we are searching for. If either condition is true, we return the root.

Otherwise, we compare the given `val` with the current node's value. If `val` is less than the current node's value, we proceed to search the left subtree. Otherwise, we search the right subtree, and we return the result of either search.

This algorithm leverages the properties of a binary search tree, which ensures that for each node, all elements in the left subtree are less than the node, and all elements in the right subtree are greater than the node, enabling efficient search.

## A solution in Javascript

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

function searchBST(root, val) {
    if (!root || root.val === val) {
        return root;
    }
    return (root.val > val) ? searchBST(root.left, val) : searchBST(root.right, val);
}
```
We are given a binary search tree (BST) and an integer value `val`. Our task is to find the node in the tree with the same value as `val` and return the subtree rooted at that node. If there is no such node, we should return null.

To solve this problem, we use a recursive function `searchBST`. We first check whether the current `root` is null or has the value we are searching for. If either condition is true, we return the root.

Otherwise, we compare the given `val` with the current node's value. If `val` is less than the current node's value, we proceed to search the left subtree. Otherwise, we search the right subtree, and we return the result of either search.

This algorithm leverages the properties of a binary search tree, which ensures that for each node, all elements in the left subtree are less than the node, and all elements in the right subtree are greater than the node, enabling efficient search.


# Letter Case Permutation

- slug: letter-case-permutation
- difficulty: Medium

Given a string `s`, you can transform every letter individually to be lowercase or uppercase to create another string.

Return _a list of all possible strings we could create_. Return the output in **any order**.

**Example 1:**

**Input:** s =  "a1b2 "
**Output:** \[ "a1b2 ", "a1B2 ", "A1b2 ", "A1B2 "\]

**Example 2:**

**Input:** s =  "3z4 "
**Output:** \[ "3z4 ", "3Z4 "\]

**Constraints:**

*   `1 <= s.length <= 12`
*   `s` consists of lowercase English letters, uppercase English letters, and digits.

## A solution in Java

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

public TreeNode insertIntoBST(TreeNode root, int val) {
    if (root == null) {
        return new TreeNode(val);
    }

    if (val < root.val) {
        root.left = insertIntoBST(root.left, val);
    } else {
        root.right = insertIntoBST(root.right, val);
    }

    return root;
}
```
The algorithm inserts a value into a Binary Search Tree (BST). We begin by checking if the root node exists. If it does not exist, we create a new node with the given value and return it as the new root.

If the root exists, we check if the given value is less than the root node's value. If it is, we then recursively insert the value into the left subtree. Otherwise, we insert it into the right subtree.

Finally, we return the root of the updated BST. This algorithm works for all the languages specified, as the logic remains the same across them. The only difference is the syntax and TreeNode class/struct declarations. The time complexity is O(h), where h is the height of the BST.

## A solution in C++

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

TreeNode* insertIntoBST(TreeNode* root, int val) {
    if (root == NULL) {
        return new TreeNode(val);
    }

    if (val < root->val) {
        root->left = insertIntoBST(root->left, val);
    } else {
        root->right = insertIntoBST(root->right, val);
    }

    return root;
}
```
The algorithm inserts a value into a Binary Search Tree (BST). We begin by checking if the root node exists. If it does not exist, we create a new node with the given value and return it as the new root.

If the root exists, we check if the given value is less than the root node's value. If it is, we then recursively insert the value into the left subtree. Otherwise, we insert it into the right subtree.

Finally, we return the root of the updated BST. This algorithm works for all the languages specified, as the logic remains the same across them. The only difference is the syntax and TreeNode class/struct declarations. The time complexity is O(h), where h is the height of the BST.

## A solution in Python

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

def insertIntoBST(root, val):
    if root is None:
        return TreeNode(val)

    if val < root.val:
        root.left = insertIntoBST(root.left, val)
    else:
        root.right = insertIntoBST(root.right, val)

    return root
```
The algorithm inserts a value into a Binary Search Tree (BST). We begin by checking if the root node exists. If it does not exist, we create a new node with the given value and return it as the new root.

If the root exists, we check if the given value is less than the root node's value. If it is, we then recursively insert the value into the left subtree. Otherwise, we insert it into the right subtree.

Finally, we return the root of the updated BST. This algorithm works for all the languages specified, as the logic remains the same across them. The only difference is the syntax and TreeNode class/struct declarations. The time complexity is O(h), where h is the height of the BST.

## A solution in Javascript

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

function insertIntoBST(root, val) {
    if (root === null) {
        return new TreeNode(val);
    }

    if (val < root.val) {
        root.left = insertIntoBST(root.left, val);
    } else {
        root.right = insertIntoBST(root.right, val);
    }

    return root;
}
```
The algorithm inserts a value into a Binary Search Tree (BST). We begin by checking if the root node exists. If it does not exist, we create a new node with the given value and return it as the new root.

If the root exists, we check if the given value is less than the root node's value. If it is, we then recursively insert the value into the left subtree. Otherwise, we insert it into the right subtree.

Finally, we return the root of the updated BST. This algorithm works for all the languages specified, as the logic remains the same across them. The only difference is the syntax and TreeNode class/struct declarations. The time complexity is O(h), where h is the height of the BST.


# Is Graph Bipartite?

- slug: is-graph-bipartite
- difficulty: Medium

There is an **undirected** graph with `n` nodes, where each node is numbered between `0` and `n - 1`. You are given a 2D array `graph`, where `graph[u]` is an array of nodes that node `u` is adjacent to. More formally, for each `v` in `graph[u]`, there is an undirected edge between node `u` and node `v`. The graph has the following properties:

*   There are no self-edges (`graph[u]` does not contain `u`).
*   There are no parallel edges (`graph[u]` does not contain duplicate values).
*   If `v` is in `graph[u]`, then `u` is in `graph[v]` (the graph is undirected).
*   The graph may not be connected, meaning there may be two nodes `u` and `v` such that there is no path between them.

A graph is **bipartite** if the nodes can be partitioned into two independent sets `A` and `B` such that **every** edge in the graph connects a node in set `A` and a node in set `B`.

Return `true` _if and only if it is **bipartite**_.

**Example 1:**

**Input:** graph = \[\[1,2,3\],\[0,2\],\[0,1,3\],\[0,2\]\]
**Output:** false
**Explanation:** There is no way to partition the nodes into two independent sets such that every edge connects a node in one and a node in the other.

**Example 2:**

**Input:** graph = \[\[1,3\],\[0,2\],\[1,3\],\[0,2\]\]
**Output:** true
**Explanation:** We can partition the nodes into two sets: {0, 2} and {1, 3}.

**Constraints:**

*   `graph.length == n`
*   `1 <= n <= 100`
*   `0 <= graph[u].length < n`
*   `0 <= graph[u][i] <= n - 1`
*   `graph[u]` does not contain `u`.
*   All the values of `graph[u]` are **unique**.
*   If `graph[u]` contains `v`, then `graph[v]` contains `u`.

## A solution in Java

```java
import java.util.Arrays;

class Solution {
    public boolean isBipartite(int[][] graph) {
        int n = graph.length;
        int[] colors = new int[n];
        Arrays.fill(colors, 0);

        for (int i = 0; i < n; ++i) {
            if (colors[i] == 0 && !dfs(i, 1, colors, graph)) {
                return false;
            }
        }

        return true;
    }

    private boolean dfs(int node, int color, int[] colors, int[][] graph) {
        if (colors[node] != 0) {
            return colors[node] == color;
        }

        colors[node] = color;
        for (int neighbor : graph[node]) {
            if (!dfs(neighbor, 3 - color, colors, graph)) {
                return false;
            }
        }

        return true;
    }
}
```
The algorithm is based on a Depth First Search (DFS). We iterate over all nodes, performing a DFS on the nodes that have not been assigned a color yet.

In the DFS, we first check if the node has a color assigned. If it has, we return true if the assigned color matches the expected color. If the node does not have a color assigned, we assign the expected color to it, and perform the DFS on all its neighbors with the alternate color (3 - color). If any of these DFS return false, we return false. Otherwise, we return true.

After iterating all nodes, if none of them returned false, then the graph is bipartite.

This algorithm does not depend on the specific programming language, but the syntax for the DFS and color assignments will vary according to the language used.

## A solution in C++

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

bool dfs(int node, int color, vector<int>& colors, vector<vector<int>>& graph) {
    if (colors[node] != 0) {
        return colors[node] == color;
    }

    colors[node] = color;
    for (int neighbor : graph[node]) {
        if (!dfs(neighbor, 3 - color, colors, graph)) {
            return false;
        }
    }

    return true;
}

bool isBipartite(vector<vector<int>>& graph) {
    int n = graph.size();
    vector<int> colors(n, 0);

    for (int i = 0; i < n; ++i) {
        if (colors[i] == 0 && !dfs(i, 1, colors, graph)) {
            return false;
        }
    }

    return true;
}
```
The algorithm is based on a Depth First Search (DFS). We iterate over all nodes, performing a DFS on the nodes that have not been assigned a color yet.

In the DFS, we first check if the node has a color assigned. If it has, we return true if the assigned color matches the expected color. If the node does not have a color assigned, we assign the expected color to it, and perform the DFS on all its neighbors with the alternate color (3 - color). If any of these DFS return false, we return false. Otherwise, we return true.

After iterating all nodes, if none of them returned false, then the graph is bipartite.

This algorithm does not depend on the specific programming language, but the syntax for the DFS and color assignments will vary according to the language used.

## A solution in Python

```python
def isBipartite(graph: List[List[int]]) -> bool:
    def dfs(node: int, color: int) -> bool:
        if colors[node]:
            return colors[node] == color

        colors[node] = color
        for neighbor in graph[node]:
            if not dfs(neighbor, 3 - color):
                return False

        return True

    n = len(graph)
    colors = [0] * n

    for i in range(n):
        if not colors[i] and not dfs(i, 1):
            return False

    return True
```
The algorithm is based on a Depth First Search (DFS). We iterate over all nodes, performing a DFS on the nodes that have not been assigned a color yet.

In the DFS, we first check if the node has a color assigned. If it has, we return true if the assigned color matches the expected color. If the node does not have a color assigned, we assign the expected color to it, and perform the DFS on all its neighbors with the alternate color (3 - color). If any of these DFS return false, we return false. Otherwise, we return true.

After iterating all nodes, if none of them returned false, then the graph is bipartite.

This algorithm does not depend on the specific programming language, but the syntax for the DFS and color assignments will vary according to the language used.

## A solution in Javascript

```javascript
var isBipartite = function(graph) {
    function dfs(node, color) {
        if (colors[node] !== 0) {
            return colors[node] === color;
        }

        colors[node] = color;
        for (const neighbor of graph[node]) {
            if (!dfs(neighbor, 3 - color)) {
                return false;
            }
        }

        return true;
    }

    let n = graph.length;
    let colors = new Array(n).fill(0);

    for (let i = 0; i < n; ++i) {
        if (colors[i] === 0 && !dfs(i, 1)) {
            return false;
        }
    }

    return true;
};
```
The algorithm is based on a Depth First Search (DFS). We iterate over all nodes, performing a DFS on the nodes that have not been assigned a color yet.

In the DFS, we first check if the node has a color assigned. If it has, we return true if the assigned color matches the expected color. If the node does not have a color assigned, we assign the expected color to it, and perform the DFS on all its neighbors with the alternate color (3 - color). If any of these DFS return false, we return false. Otherwise, we return true.

After iterating all nodes, if none of them returned false, then the graph is bipartite.

This algorithm does not depend on the specific programming language, but the syntax for the DFS and color assignments will vary according to the language used.


# K-th Smallest Prime Fraction

- slug: k-th-smallest-prime-fraction
- difficulty: Medium

You are given a sorted integer array `arr` containing `1` and **prime** numbers, where all the integers of `arr` are unique. You are also given an integer `k`.

For every `i` and `j` where `0 <= i < j < arr.length`, we consider the fraction `arr[i] / arr[j]`.

Return _the_ `kth` _smallest fraction considered_. Return your answer as an array of integers of size `2`, where `answer[0] == arr[i]` and `answer[1] == arr[j]`.

**Example 1:**

**Input:** arr = \[1,2,3,5\], k = 3
**Output:** \[2,5\]
**Explanation:** The fractions to be considered in sorted order are:
1/5, 1/3, 2/5, 1/2, 3/5, and 2/3.
The third fraction is 2/5.

**Example 2:**

**Input:** arr = \[1,7\], k = 1
**Output:** \[1,7\]

**Constraints:**

*   `2 <= arr.length <= 1000`
*   `1 <= arr[i] <= 3 * 104`
*   `arr[0] == 1`
*   `arr[i]` is a **prime** number for `i > 0`.
*   All the numbers of `arr` are **unique** and sorted in **strictly increasing** order.
*   `1 <= k <= arr.length * (arr.length - 1) / 2`

**Follow up:** Can you solve the problem with better than `O(n2)` complexity?

## A solution in Java

```java
import java.util.PriorityQueue;

public int[] kthSmallestPrimeFraction(int[] arr, int k) {
    PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> arr[a[0]] * arr[b[1]] - arr[a[1]] * arr[b[0]]);
    for (int i = 0; i < arr.length - 1; i++) {
        pq.offer(new int[]{i, arr.length - 1});
    }
    while (--k > 0) {
        int[] tmp = pq.poll();
        if (--tmp[1] > tmp[0]) {
            pq.offer(tmp);
        }
    }
    return new int[]{arr[pq.peek()[0]], arr[pq.peek()[1]]};
}
```
1. Given array arr, we first consider the greatest fractions that could be generated using elements from arr (i.e., num/denom). The products of these fractions are stored in a priority queue (min-heap).
2. Then we iterate k-1 times to find the k-th smallest fraction from the priority queue:
  a. Pop the smallest fraction from the priority queue and decrease the denominator of that fraction.
  b. Push the new fraction back into the priority queue.
3. Finally, after iterating k-1 times, the current smallest fraction (top of priority queue) will be the k-th smallest fraction in the array. We return the corresponding numerator and denominator as the output.

## A solution in C++

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

vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {
    auto compare = [&](pair<int, int>& a, pair<int, int>& b) {
        return arr[a.first] * arr[b.second] > arr[a.second] * arr[b.first];
    };
    priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(compare)> pq(compare);
    for (int i = 0; i < arr.size() - 1; ++i) {
        pq.push({i, arr.size() - 1});
    }
    for (int i = 0; i < k - 1; ++i) {
        auto [row, col] = pq.top();
        pq.pop();
        if (--col > row) {
            pq.push({row, col});
        }
    }
    return {arr[pq.top().first], arr[pq.top().second]};
}
```
1. Given array arr, we first consider the greatest fractions that could be generated using elements from arr (i.e., num/denom). The products of these fractions are stored in a priority queue (min-heap).
2. Then we iterate k-1 times to find the k-th smallest fraction from the priority queue:
  a. Pop the smallest fraction from the priority queue and decrease the denominator of that fraction.
  b. Push the new fraction back into the priority queue.
3. Finally, after iterating k-1 times, the current smallest fraction (top of priority queue) will be the k-th smallest fraction in the array. We return the corresponding numerator and denominator as the output.

## A solution in Python

```python
import heapq
from typing import List

def kthSmallestPrimeFraction(arr: List[int], k: int) -> List[int]:
    pq = [(arr[i] / arr[j], i, j) for j in range(len(arr) - 1, 0, -1)]
    heapq.heapify(pq)
    for _ in range(k - 1):
        _, i, j = heapq.heappop(pq)
        if j != i + 1:
            heapq.heappush(pq, (arr[i] / arr[j - 1], i, j - 1))
    return [arr[pq[0][1]], arr[pq[0][2]]]
```
1. Given array arr, we first consider the greatest fractions that could be generated using elements from arr (i.e., num/denom). The products of these fractions are stored in a priority queue (min-heap).
2. Then we iterate k-1 times to find the k-th smallest fraction from the priority queue:
  a. Pop the smallest fraction from the priority queue and decrease the denominator of that fraction.
  b. Push the new fraction back into the priority queue.
3. Finally, after iterating k-1 times, the current smallest fraction (top of priority queue) will be the k-th smallest fraction in the array. We return the corresponding numerator and denominator as the output.

## A solution in Javascript

```javascript
function kthSmallestPrimeFraction(arr, k) {
    const pq = new PriorityQueue((a, b) => arr[a[0]] * arr[b[1]] - arr[a[1]] * arr[b[0]]);
    for (let i = 0; i < arr.length - 1; i++) {
        pq.push([i, arr.length - 1]);
    }
    while (--k > 0) {
        const tmp = pq.pop();
        if (--tmp[1] > tmp[0]) {
            pq.push(tmp);
        }
    }
    return [arr[pq.top()[0]], arr[pq.top()[1]]];
}

class PriorityQueue {
    constructor(comparator = (a, b) => a - b) {
        this._heap = [];
        this._comparator = comparator;
    }

    size() {
        return this._heap.length;
    }

    isEmpty() {
        return this.size() === 0;
    }

    top() {
        return this._heap[0];
    }

    push(value) {
        this._heap.push(value);
        this._siftUp();
    }

    pop(value) {
        const poppedValue = this.top();
        const bottom = this.size() - 1;
        if (bottom > 0) {
            this._swap(0, bottom);
        }
        this._heap.pop();
        this._siftDown();
        return poppedValue;
    }

    _siftUp() {
        let node = this.size() - 1;
        while (node > 0 && this._greater(node, Math.floor((node - 1) / 2))) {
            this._swap(node, Math.floor((node - 1) / 2));
            node = Math.floor((node - 1) / 2);
        }
    }

    _siftDown() {
        let node = 0;
        while (
            (2 * node + 1 < this.size() && this._greater(2 * node + 1, node)) ||
            (2 * node + 2 < this.size() && this._greater(2 * node + 2, node))
        ) {
            let maxChild = 2 * node + 1;
            if (2 * node + 2 < this.size() && this._greater(2 * node + 2, 2 * node + 1)) {
                maxChild = 2 * node + 2;
            }
            this._swap(node, maxChild);
            node = maxChild;
        }
    }

    _greater(i, j) {
        return this._comparator(this._heap[i], this._heap[j]) > 0;
    }

    _swap(i, j) {
        [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]];
        return this;
    }
}
```
1. Given array arr, we first consider the greatest fractions that could be generated using elements from arr (i.e., num/denom). The products of these fractions are stored in a priority queue (min-heap).
2. Then we iterate k-1 times to find the k-th smallest fraction from the priority queue:
  a. Pop the smallest fraction from the priority queue and decrease the denominator of that fraction.
  b. Push the new fraction back into the priority queue.
3. Finally, after iterating k-1 times, the current smallest fraction (top of priority queue) will be the k-th smallest fraction in the array. We return the corresponding numerator and denominator as the output.


# Cheapest Flights Within K Stops

- slug: cheapest-flights-within-k-stops
- difficulty: Medium

There are `n` cities connected by some number of flights. You are given an array `flights` where `flights[i] = [fromi, toi, pricei]` indicates that there is a flight from city `fromi` to city `toi` with cost `pricei`.

You are also given three integers `src`, `dst`, and `k`, return _**the cheapest price** from_ `src` _to_ `dst` _with at most_ `k` _stops._ If there is no such route, return `-1`.

**Example 1:**

**Input:** n = 4, flights = \[\[0,1,100\],\[1,2,100\],\[2,0,100\],\[1,3,600\],\[2,3,200\]\], src = 0, dst = 3, k = 1
**Output:** 700
**Explanation:**
The graph is shown above.
The optimal path with at most 1 stop from city 0 to 3 is marked in red and has cost 100 + 600 = 700.
Note that the path through cities \[0,1,2,3\] is cheaper but is invalid because it uses 2 stops.

**Example 2:**

**Input:** n = 3, flights = \[\[0,1,100\],\[1,2,100\],\[0,2,500\]\], src = 0, dst = 2, k = 1
**Output:** 200
**Explanation:**
The graph is shown above.
The optimal path with at most 1 stop from city 0 to 2 is marked in red and has cost 100 + 100 = 200.

**Example 3:**

**Input:** n = 3, flights = \[\[0,1,100\],\[1,2,100\],\[0,2,500\]\], src = 0, dst = 2, k = 0
**Output:** 500
**Explanation:**
The graph is shown above.
The optimal path with no stops from city 0 to 2 is marked in red and has cost 500.

**Constraints:**

*   `1 <= n <= 100`
*   `0 <= flights.length <= (n * (n - 1) / 2)`
*   `flights[i].length == 3`
*   `0 <= fromi, toi < n`
*   `fromi != toi`
*   `1 <= pricei <= 104`
*   There will not be any multiple flights between two cities.
*   `0 <= src, dst, k < n`
*   `src != dst`

## A solution in Java

```java
import java.util.*;

class Solution {
    public int slidingPuzzle(int[][] board) {
        int m = 2, n = 3;
        String target = "123450";
        String start = "";
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                start += board[i][j];
            }
        }
        int[][] dirs = {{1, 3}, {0, 2, 4}, {1, 5}, {0, 4}, {1, 3, 5}, {2, 4}};
        Queue<String> q = new LinkedList<>(Arrays.asList(A));
        int res = 0;
        Set<String> visited = new HashSet<>(q);
        while (!q.isEmpty()) {
            for (int k = q.size(); k > 0; --k) {
                String cur = q.poll();
                if (cur.equals(target)) return res;
                int zero_idx = cur.indexOf('0');
                for (int dir : dirs[zero_idx]) {
                    String neighbor = cur;
                    neighbor = neighbor.substring(0, zero_idx) + neighbor.charAt(dir) + neighbor.substring(zero_idx + 1);
                    neighbor = neighbor.substring(0, dir) + '0' + neighbor.substring(dir+1);
                    if (!visited.contains(neighbor)) {
                        visited.add(neighbor);
                        q.add(neighbor);
                    }
                }
            }
            ++res;
        }
        return -1;
    }
}
```
The algorithm can be explained as follows:

1. Convert the board 2D array into a string.
2. Initialize the target state, the visiting queue starting from the given board state, and a set containing visited states.
3. Create a directions array that represents the possible moves of the "0" tile for each of its positions.
4. Iterate through the visiting queue until it is empty, incrementing the move counter with each iteration.
5. For each visiting state, find the index of the "0" tile.
6. For each possible move of the "0" tile from its current index, swap it with the adjacent tile given by the directions array.
7. Check if the new state is the target state. If it is, return the current move counter value.
8. Otherwise, if the new state has not been visited, mark it as visited and add it to the visiting queue.
9. When the visiting queue is empty, if there was no target state found, return -1 as solving the puzzle is impossible.

## A solution in C++

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

using namespace std;

int slidingPuzzle(vector<vector<int>>& board) {
    int m = 2, n = 3;
    string target = "123450";
    string start = "";
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
            start += to_string(board[i][j]);
    vector<vector<int>> dirs{{1, 3}, {0, 2, 4}, {1, 5}, {0, 4}, {1, 3, 5}, {2, 4}};
    queue<string> q{{start}};
    int res = 0;
    unordered_set<string> visited{start};
    while (!q.empty()) {
        for (int k = q.size(); k > 0; --k) {
            string cur = q.front(); q.pop();
            if (cur == target) return res;
            int zero_idx = cur.find("0");
            for (int dir : dirs[zero_idx]) {
                string neighbor = cur;
                swap(neighbor[zero_idx], neighbor[dir]);
                if (!visited.count(neighbor)) {
                    visited.insert(neighbor);
                    q.push(neighbor);
                }
            }
        }
        ++res;
    }
    return -1;
}
```
The algorithm can be explained as follows:

1. Convert the board 2D array into a string.
2. Initialize the target state, the visiting queue starting from the given board state, and a set containing visited states.
3. Create a directions array that represents the possible moves of the "0" tile for each of its positions.
4. Iterate through the visiting queue until it is empty, incrementing the move counter with each iteration.
5. For each visiting state, find the index of the "0" tile.
6. For each possible move of the "0" tile from its current index, swap it with the adjacent tile given by the directions array.
7. Check if the new state is the target state. If it is, return the current move counter value.
8. Otherwise, if the new state has not been visited, mark it as visited and add it to the visiting queue.
9. When the visiting queue is empty, if there was no target state found, return -1 as solving the puzzle is impossible.

## A solution in Python

```python
from collections import deque

def slidingPuzzle(board):
    m, n = 2, 3
    target = "123450"
    start = "".join(str(num) for row in board for num in row)
    dirs = [[1, 3], [0, 2, 4], [1, 5], [0, 4], [1, 3, 5], [2, 4]]
    q = deque([start])
    res = 0
    visited = {start}
    while q:
        for _ in range(len(q)):
            cur = q.popleft()
            if cur == target:
                return res
            zero_idx = cur.index("0")
            for dir in dirs[zero_idx]:
                neighbor = list(cur)
                neighbor[zero_idx], neighbor[dir] = neighbor[dir], neighbor[zero_idx]
                neighbor = "".join(neighbor)
                if neighbor not in visited:
                    visited.add(neighbor)
                    q.append(neighbor)
        res += 1
    return -1
```
The algorithm can be explained as follows:

1. Convert the board 2D array into a string.
2. Initialize the target state, the visiting queue starting from the given board state, and a set containing visited states.
3. Create a directions array that represents the possible moves of the "0" tile for each of its positions.
4. Iterate through the visiting queue until it is empty, incrementing the move counter with each iteration.
5. For each visiting state, find the index of the "0" tile.
6. For each possible move of the "0" tile from its current index, swap it with the adjacent tile given by the directions array.
7. Check if the new state is the target state. If it is, return the current move counter value.
8. Otherwise, if the new state has not been visited, mark it as visited and add it to the visiting queue.
9. When the visiting queue is empty, if there was no target state found, return -1 as solving the puzzle is impossible.

## A solution in Javascript

```javascript
function slidingPuzzle(board) {
    const m = 2, n = 3;
    const target = "123450";
    let start = "";
    for (const row of board) {
        for (const num of row) {
            start += num;
        }
    }
    const dirs = [[1, 3], [0, 2, 4], [1, 5], [0, 4], [1, 3, 5], [2, 4]];
    const q = [start];
    let res = 0;
    const visited = new Set(q);
    while (q.length > 0) {
        for (let k = q.length; k > 0; --k) {
            const cur = q.shift();
            if (cur === target) return res;
            const zero_idx = cur.indexOf('0');
            for (const dir of dirs[zero_idx]) {
                let neighbor = cur.slice(0, zero_idx) + cur[dir] + cur.slice(zero_idx + 1);
                neighbor = neighbor.slice(0, dir) + '0' + neighbor.slice(dir + 1);
                if (!visited.has(neighbor)) {
                    visited.add(neighbor);
                    q.push(neighbor);
                }
            }
        }
        ++res;
    }
    return -1;
}
```
The algorithm can be explained as follows:

1. Convert the board 2D array into a string.
2. Initialize the target state, the visiting queue starting from the given board state, and a set containing visited states.
3. Create a directions array that represents the possible moves of the "0" tile for each of its positions.
4. Iterate through the visiting queue until it is empty, incrementing the move counter with each iteration.
5. For each visiting state, find the index of the "0" tile.
6. For each possible move of the "0" tile from its current index, swap it with the adjacent tile given by the directions array.
7. Check if the new state is the target state. If it is, return the current move counter value.
8. Otherwise, if the new state has not been visited, mark it as visited and add it to the visiting queue.
9. When the visiting queue is empty, if there was no target state found, return -1 as solving the puzzle is impossible.


# Rotated Digits

- slug: rotated-digits
- difficulty: Medium

An integer `x` is a **good** if after rotating each digit individually by 180 degrees, we get a valid number that is different from `x`. Each digit must be rotated - we cannot choose to leave it alone.

A number is valid if each digit remains a digit after rotation. For example:

*   `0`, `1`, and `8` rotate to themselves,
*   `2` and `5` rotate to each other (in this case they are rotated in a different direction, in other words, `2` or `5` gets mirrored),
*   `6` and `9` rotate to each other, and
*   the rest of the numbers do not rotate to any other number and become invalid.

Given an integer `n`, return _the number of **good** integers in the range_ `[1, n]`.

**Example 1:**

**Input:** n = 10
**Output:** 4
**Explanation:** There are four good numbers in the range \[1, 10\] : 2, 5, 6, 9.
Note that 1 and 10 are not good numbers, since they remain unchanged after rotating.

**Example 2:**

**Input:** n = 1
**Output:** 0

**Example 3:**

**Input:** n = 2
**Output:** 1

**Constraints:**

*   `1 <= n <= 104`

## A solution in Java

```java
public int rotatedDigits(int n) {
    int count = 0;
    for (int i = 1; i <= n; i++) {
        if (isGood(i))
            count++;
    }
    return count;
}

private boolean isGood(int num) {
    boolean changed = false;
    while (num != 0) {
        int digit = num % 10;
        if (digit == 3 || digit == 4 || digit == 7) return false;
        if (digit == 2 || digit == 5 || digit == 6 || digit == 9) changed = true;
        num /= 10;
    }
    return changed;
}
```
The algorithm will use two main functions, one to check if a number is a good number (`isGood`) and the main one to count such numbers (`rotatedDigits`).

1. Create a variable called `count` to store the count of good numbers.
2. Iterate from 1 to the given number `n`.
3. For each number, call the `isGood` function to check if it's a good number.
4. If it is a good number, increment the `count`.
5. The `isGood` function takes an integer as input and checks if it's a good number:
    - Check each digit of the number while the number is greater than 0.
    - If the digit is 3, 4 or 7, then the number is not a good number (return false).
    - If the digit is 2, 5, 6 or 9, then the number is changed after rotation, set the `changed` flag as true.
    - Remove the last digit of the number by dividing it by 10.
    - If the `changed` flag is true, then the number is a good number (return true), otherwise return false.
6. Return the `count`.

## A solution in C++

```cpp
int rotatedDigits(int n) {
    int count = 0;
    for (int i = 1; i <= n; i++) {
        if (isGood(i))
            count++;
    }
    return count;
}

bool isGood(int num) {
    bool changed = false;
    while (num) {
        int digit = num % 10;
        if (digit == 3 || digit == 4 || digit == 7) return false;
        if (digit == 2 || digit == 5 || digit == 6 || digit == 9) changed = true;
        num /= 10;
    }
    return changed;
}
```
The algorithm will use two main functions, one to check if a number is a good number (`isGood`) and the main one to count such numbers (`rotatedDigits`).

1. Create a variable called `count` to store the count of good numbers.
2. Iterate from 1 to the given number `n`.
3. For each number, call the `isGood` function to check if it's a good number.
4. If it is a good number, increment the `count`.
5. The `isGood` function takes an integer as input and checks if it's a good number:
    - Check each digit of the number while the number is greater than 0.
    - If the digit is 3, 4 or 7, then the number is not a good number (return false).
    - If the digit is 2, 5, 6 or 9, then the number is changed after rotation, set the `changed` flag as true.
    - Remove the last digit of the number by dividing it by 10.
    - If the `changed` flag is true, then the number is a good number (return true), otherwise return false.
6. Return the `count`.

## A solution in Python

```python
def rotatedDigits(n: int) -> int:
    count = 0
    for i in range(1, n + 1):
        if isGood(i):
            count += 1
    return count

def isGood(num: int) -> bool:
    changed = False
    while num:
        digit = num % 10
        if digit in (3, 4, 7):
            return False
        if digit in (2, 5, 6, 9):
            changed = True
        num //= 10
    return changed
```
The algorithm will use two main functions, one to check if a number is a good number (`isGood`) and the main one to count such numbers (`rotatedDigits`).

1. Create a variable called `count` to store the count of good numbers.
2. Iterate from 1 to the given number `n`.
3. For each number, call the `isGood` function to check if it's a good number.
4. If it is a good number, increment the `count`.
5. The `isGood` function takes an integer as input and checks if it's a good number:
    - Check each digit of the number while the number is greater than 0.
    - If the digit is 3, 4 or 7, then the number is not a good number (return false).
    - If the digit is 2, 5, 6 or 9, then the number is changed after rotation, set the `changed` flag as true.
    - Remove the last digit of the number by dividing it by 10.
    - If the `changed` flag is true, then the number is a good number (return true), otherwise return false.
6. Return the `count`.

## A solution in Javascript

```javascript
function rotatedDigits(n) {
    let count = 0;
    for (let i = 1; i <= n; i++) {
        if (isGood(i))
            count++;
    }
    return count;
}

function isGood(num) {
    let changed = false;
    while (num) {
        let digit = num % 10;
        if (digit === 3 || digit === 4 || digit === 7) return false;
        if (digit === 2 || digit === 5 || digit === 6 || digit === 9) changed = true;
        num = Math.floor(num / 10);
    }
    return changed;
}
```
The algorithm will use two main functions, one to check if a number is a good number (`isGood`) and the main one to count such numbers (`rotatedDigits`).

1. Create a variable called `count` to store the count of good numbers.
2. Iterate from 1 to the given number `n`.
3. For each number, call the `isGood` function to check if it's a good number.
4. If it is a good number, increment the `count`.
5. The `isGood` function takes an integer as input and checks if it's a good number:
    - Check each digit of the number while the number is greater than 0.
    - If the digit is 3, 4 or 7, then the number is not a good number (return false).
    - If the digit is 2, 5, 6 or 9, then the number is changed after rotation, set the `changed` flag as true.
    - Remove the last digit of the number by dividing it by 10.
    - If the `changed` flag is true, then the number is a good number (return true), otherwise return false.
6. Return the `count`.


# Escape The Ghosts

- slug: escape-the-ghosts
- difficulty: Medium

You are playing a simplified PAC-MAN game on an infinite 2-D grid. You start at the point `[0, 0]`, and you are given a destination point `target = [xtarget, ytarget]` that you are trying to get to. There are several ghosts on the map with their starting positions given as a 2D array `ghosts`, where `ghosts[i] = [xi, yi]` represents the starting position of the `ith` ghost. All inputs are **integral coordinates**.

Each turn, you and all the ghosts may independently choose to either **move 1 unit** in any of the four cardinal directions: north, east, south, or west, or **stay still**. All actions happen **simultaneously**.

You escape if and only if you can reach the target **before** any ghost reaches you. If you reach any square (including the target) at the **same time** as a ghost, it **does not** count as an escape.

Return `true` _if it is possible to escape regardless of how the ghosts move, otherwise return_ `false`_._

**Example 1:**

**Input:** ghosts = \[\[1,0\],\[0,3\]\], target = \[0,1\]
**Output:** true
**Explanation:** You can reach the destination (0, 1) after 1 turn, while the ghosts located at (1, 0) and (0, 3) cannot catch up with you.

**Example 2:**

**Input:** ghosts = \[\[1,0\]\], target = \[2,0\]
**Output:** false
**Explanation:** You need to reach the destination (2, 0), but the ghost at (1, 0) lies between you and the destination.

**Example 3:**

**Input:** ghosts = \[\[2,0\]\], target = \[1,0\]
**Output:** false
**Explanation:** The ghost can reach the target at the same time as you.

**Constraints:**

*   `1 <= ghosts.length <= 100`
*   `ghosts[i].length == 2`
*   `-104 <= xi, yi <= 104`
*   There can be **multiple ghosts** in the same location.
*   `target.length == 2`
*   `-104 <= xtarget, ytarget <= 104`

## A solution in Java

```java
import java.util.PriorityQueue;

public class KthLargest {
    private PriorityQueue<Integer> minHeap;
    private int k;

    public KthLargest(int k, int[] nums) {
        this.k = k;
        minHeap = new PriorityQueue<>();
        for (int num : nums) {
            add(num);
        }
    }

    public int add(int val) {
        minHeap.offer(val);
        if (minHeap.size() > k) {
            minHeap.poll();
        }
        return minHeap.peek();
    }
}
```
The algorithm uses a priority queue called a min heap to keep track of the top `k` largest elements of the stream. For each element added to the stream, it is added to the min heap. If the size of min heap exceeds `k`, then the smallest element in the min heap (which is the top of the min heap) is removed. This ensures that the min heap always contains the `k` largest elements in the stream. Finally, when we want to find the kth largest element, we simply return the smallest element in the min heap (i.e., the top of the min heap).

## A solution in C++

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

class KthLargest {
public:
    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;
    int k;

    KthLargest(int k, std::vector<int>& nums) {
        this->k = k;
        for (int num : nums) {
            add(num);
        }
    }

    int add(int val) {
        minHeap.push(val);
        if (minHeap.size() > k) {
            minHeap.pop();
        }
        return minHeap.top();
    }
};
```
The algorithm uses a priority queue called a min heap to keep track of the top `k` largest elements of the stream. For each element added to the stream, it is added to the min heap. If the size of min heap exceeds `k`, then the smallest element in the min heap (which is the top of the min heap) is removed. This ensures that the min heap always contains the `k` largest elements in the stream. Finally, when we want to find the kth largest element, we simply return the smallest element in the min heap (i.e., the top of the min heap).

## A solution in Python

```python
import heapq

class KthLargest:

    def __init__(self, k, nums):
        self.heap = []
        self.k = k
        for num in nums:
            self.add(num)

    def add(self, val):
        heapq.heappush(self.heap, val)
        if len(self.heap) > self.k:
            heapq.heappop(self.heap)
        return self.heap[0]
```
The algorithm uses a priority queue called a min heap to keep track of the top `k` largest elements of the stream. For each element added to the stream, it is added to the min heap. If the size of min heap exceeds `k`, then the smallest element in the min heap (which is the top of the min heap) is removed. This ensures that the min heap always contains the `k` largest elements in the stream. Finally, when we want to find the kth largest element, we simply return the smallest element in the min heap (i.e., the top of the min heap).

## A solution in Javascript

```javascript
class KthLargest {
    constructor(k, nums) {
        this.minHeap = new MinHeap();
        this.k = k;
        for (let num of nums) {
            this.add(num);
        }
    }

    add(val) {
        this.minHeap.offer(val);
        if (this.minHeap.size() > this.k) {
            this.minHeap.poll();
        }
        return this.minHeap.peek();
    }
}

class MinHeap {
    constructor() {
        this.heap = [];
    }

    offer(val) {
        this.heap.push(val);
        this.heap.sort((a, b) => a - b);
    }

    poll() {
        return this.heap.shift();
    }

    peek() {
        return this.heap[0];
    }

    size() {
        return this.heap.length;
    }
}
```
The algorithm uses a priority queue called a min heap to keep track of the top `k` largest elements of the stream. For each element added to the stream, it is added to the min heap. If the size of min heap exceeds `k`, then the smallest element in the min heap (which is the top of the min heap) is removed. This ensures that the min heap always contains the `k` largest elements in the stream. Finally, when we want to find the kth largest element, we simply return the smallest element in the min heap (i.e., the top of the min heap).


# Domino and Tromino Tiling

- slug: domino-and-tromino-tiling
- difficulty: Medium

You have two types of tiles: a `2 x 1` domino shape and a tromino shape. You may rotate these shapes.

Given an integer n, return _the number of ways to tile an_ `2 x n` _board_. Since the answer may be very large, return it **modulo** `109 + 7`.

In a tiling, every square must be covered by a tile. Two tilings are different if and only if there are two 4-directionally adjacent cells on the board such that exactly one of the tilings has both squares occupied by a tile.

**Example 1:**

**Input:** n = 3
**Output:** 5
**Explanation:** The five different ways are show above.

**Example 2:**

**Input:** n = 1
**Output:** 1

**Constraints:**

*   `1 <= n <= 1000`

## A solution in Java

```java
public boolean isIdealPermutation(int[] nums) {
    for (int i = 0; i < nums.length; ++i) {
        if (Math.abs(nums[i] - i) > 1) {
            return false;
        }
    }
    return true;
}
```
For the given question, we need to check if the number of global inversions is equal to the number of local inversions in the permutation. To do that, we can check if the absolute difference between the number at each index (`nums[i]`) and the index itself (`i`) is greater than 1. If it is, then it means the number of global inversions is not equal to the number of local inversions, and we can return false. If the loop completes without finding such a difference, we return true, which means the number of global inversions is equal to the number of local inversions.

## A solution in C++

```cpp
bool isIdealPermutation(vector<int>& nums) {
    for (int i = 0; i < nums.size(); ++i) {
        if (abs(nums[i] - i) > 1) {
            return false;
        }
    }
    return true;
}
```
For the given question, we need to check if the number of global inversions is equal to the number of local inversions in the permutation. To do that, we can check if the absolute difference between the number at each index (`nums[i]`) and the index itself (`i`) is greater than 1. If it is, then it means the number of global inversions is not equal to the number of local inversions, and we can return false. If the loop completes without finding such a difference, we return true, which means the number of global inversions is equal to the number of local inversions.

## A solution in Python

```python
def is_ideal_permutation(nums):
    for i, num in enumerate(nums):
        if abs(num - i) > 1:
            return False
    return True
```
For the given question, we need to check if the number of global inversions is equal to the number of local inversions in the permutation. To do that, we can check if the absolute difference between the number at each index (`nums[i]`) and the index itself (`i`) is greater than 1. If it is, then it means the number of global inversions is not equal to the number of local inversions, and we can return false. If the loop completes without finding such a difference, we return true, which means the number of global inversions is equal to the number of local inversions.

## A solution in Javascript

```javascript
function isIdealPermutation(nums) {
    for (let i = 0; i < nums.length; ++i) {
        if (Math.abs(nums[i] - i) > 1) {
            return false;
        }
    }
    return true;
}
```
For the given question, we need to check if the number of global inversions is equal to the number of local inversions in the permutation. To do that, we can check if the absolute difference between the number at each index (`nums[i]`) and the index itself (`i`) is greater than 1. If it is, then it means the number of global inversions is not equal to the number of local inversions, and we can return false. If the loop completes without finding such a difference, we return true, which means the number of global inversions is equal to the number of local inversions.


# Custom Sort String

- slug: custom-sort-string
- difficulty: Medium

You are given two strings order and s. All the characters of `order` are **unique** and were sorted in some custom order previously.

Permute the characters of `s` so that they match the order that `order` was sorted. More specifically, if a character `x` occurs before a character `y` in `order`, then `x` should occur before `y` in the permuted string.

Return _any permutation of_ `s` _that satisfies this property_.

**Example 1:**

**Input:** order =  "cba ", s =  "abcd "
**Output:**  "cbad "
**Explanation:**
 "a ",  "b ",  "c " appear in order, so the order of  "a ",  "b ",  "c " should be  "c ",  "b ", and  "a ".
Since  "d " does not appear in order, it can be at any position in the returned string.  "dcba ",  "cdba ",  "cbda " are also valid outputs.

**Example 2:**

**Input:** order =  "cbafg ", s =  "abcd "
**Output:**  "cbad "

**Constraints:**

*   `1 <= order.length <= 26`
*   `1 <= s.length <= 200`
*   `order` and `s` consist of lowercase English letters.
*   All the characters of `order` are **unique**.

## A solution in Java

```java
import java.util.HashMap;

public String customSortString(String order, String s) {
    HashMap<Character, Integer> priority = new HashMap<>();
    for (int i = 0; i < order.length(); i++) {
        priority.put(order.charAt(i), i);
    }

    Character[] sChars = s.chars().mapToObj(c -> (char) c).toArray(Character[]::new);
    Arrays.sort(sChars, (a, b) -> priority.getOrDefault(a, 0) - priority.getOrDefault(b, 0));
    return Arrays.stream(sChars).map(String::valueOf).collect(Collectors.joining());
}
```
1. Create a hash map or dictionary `priority`, where the key is the character from the `order` string, and the value is its position.
2. Sort the characters in the input string `s` based on the values in the `priority` hash map. If a character is not found in the map, set its priority to 0.
3. Join the sorted characters to form the resulting string and return it.

## A solution in C++

```cpp
#include <algorithm>
#include <string>
#include <unordered_map>

std::string customSortString(const std::string& order, std::string& s) {
    std::unordered_map<char, int> priority;
    for (int i = 0; i < order.size(); i++) {
        priority[order[i]] = i;
    }

    std::sort(s.begin(), s.end(), [&](char a, char b) {
        return priority[a] < priority[b];
    });

    return s;
}
```
1. Create a hash map or dictionary `priority`, where the key is the character from the `order` string, and the value is its position.
2. Sort the characters in the input string `s` based on the values in the `priority` hash map. If a character is not found in the map, set its priority to 0.
3. Join the sorted characters to form the resulting string and return it.

## A solution in Python

```python
def customSortString(order, s):
    priority = {char: idx for idx, char in enumerate(order)}
    return "".join(sorted(s, key=lambda x: priority.get(x, 0)))
```
1. Create a hash map or dictionary `priority`, where the key is the character from the `order` string, and the value is its position.
2. Sort the characters in the input string `s` based on the values in the `priority` hash map. If a character is not found in the map, set its priority to 0.
3. Join the sorted characters to form the resulting string and return it.

## A solution in Javascript

```javascript
function customSortString(order, s) {
    const priority = new Map();
    for (let i = 0; i < order.length; i++) {
        priority.set(order[i], i);
    }

    const sArr = Array.from(s);
    sArr.sort((a, b) => (priority.has(a) ? priority.get(a) : 0) - (priority.has(b) ? priority.get(b) : 0));
    return sArr.join('');
}
```
1. Create a hash map or dictionary `priority`, where the key is the character from the `order` string, and the value is its position.
2. Sort the characters in the input string `s` based on the values in the `priority` hash map. If a character is not found in the map, set its priority to 0.
3. Join the sorted characters to form the resulting string and return it.


# Number of Matching Subsequences

- slug: number-of-matching-subsequences
- difficulty: Medium

Given a string `s` and an array of strings `words`, return _the number of_ `words[i]` _that is a subsequence of_ `s`.

A **subsequence** of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

*   For example, `"ace "` is a subsequence of `"abcde "`.

**Example 1:**

**Input:** s =  "abcde ", words = \[ "a ", "bb ", "acd ", "ace "\]
**Output:** 3
**Explanation:** There are three strings in words that are a subsequence of s:  "a ",  "acd ",  "ace ".

**Example 2:**

**Input:** s =  "dsahjpjauf ", words = \[ "ahjpjau ", "ja ", "ahbwzgqnuk ", "tnmlanowax "\]
**Output:** 2

**Constraints:**

*   `1 <= s.length <= 5 * 104`
*   `1 <= words.length <= 5000`
*   `1 <= words[i].length <= 50`
*   `s` and `words[i]` consist of only lowercase English letters.

## A solution in Java

```java
public int search(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return -1;
}
```
The algorithm used in all four implementations is a Binary Search, which has a runtime complexity of O(log n). The binary search algorithm essentially divides the given sorted array in half with every iteration until the target value is found or the boundaries collapse.

1. Set left and right boundaries to the first and last indices of the nums array.
2. While the left boundary is less than or equal to the right boundary, perform the following steps:
   1. Calculate the mid index by taking the average of the left and right boundaries (making sure to account for integer division in Python).
   2. If the mid element matches the target, return the mid index.
   3. If the mid element is less than the target, update the left boundary to mid + 1.
   4. If the mid element is greater than the target, update the right boundary to mid - 1.
3. If the while loop ends and the target is not found, return -1.

## A solution in C++

```cpp
int search(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return -1;
}
```
The algorithm used in all four implementations is a Binary Search, which has a runtime complexity of O(log n). The binary search algorithm essentially divides the given sorted array in half with every iteration until the target value is found or the boundaries collapse.

1. Set left and right boundaries to the first and last indices of the nums array.
2. While the left boundary is less than or equal to the right boundary, perform the following steps:
   1. Calculate the mid index by taking the average of the left and right boundaries (making sure to account for integer division in Python).
   2. If the mid element matches the target, return the mid index.
   3. If the mid element is less than the target, update the left boundary to mid + 1.
   4. If the mid element is greater than the target, update the right boundary to mid - 1.
3. If the while loop ends and the target is not found, return -1.

## A solution in Python

```python
def search(nums, target):
    left = 0
    right = len(nums) - 1

    while left <= right:
        mid = left + (right - left) // 2

        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1
```
The algorithm used in all four implementations is a Binary Search, which has a runtime complexity of O(log n). The binary search algorithm essentially divides the given sorted array in half with every iteration until the target value is found or the boundaries collapse.

1. Set left and right boundaries to the first and last indices of the nums array.
2. While the left boundary is less than or equal to the right boundary, perform the following steps:
   1. Calculate the mid index by taking the average of the left and right boundaries (making sure to account for integer division in Python).
   2. If the mid element matches the target, return the mid index.
   3. If the mid element is less than the target, update the left boundary to mid + 1.
   4. If the mid element is greater than the target, update the right boundary to mid - 1.
3. If the while loop ends and the target is not found, return -1.

## A solution in Javascript

```javascript
function search(nums, target) {
    let left = 0;
    let right = nums.length - 1;

    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2);

        if (nums[mid] === target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return -1;
}
```
The algorithm used in all four implementations is a Binary Search, which has a runtime complexity of O(log n). The binary search algorithm essentially divides the given sorted array in half with every iteration until the target value is found or the boundaries collapse.

1. Set left and right boundaries to the first and last indices of the nums array.
2. While the left boundary is less than or equal to the right boundary, perform the following steps:
   1. Calculate the mid index by taking the average of the left and right boundaries (making sure to account for integer division in Python).
   2. If the mid element matches the target, return the mid index.
   3. If the mid element is less than the target, update the left boundary to mid + 1.
   4. If the mid element is greater than the target, update the right boundary to mid - 1.
3. If the while loop ends and the target is not found, return -1.


# Preimage Size of Factorial Zeroes Function

- slug: preimage-size-of-factorial-zeroes-function
- difficulty: Hard

Let `f(x)` be the number of zeroes at the end of `x!`. Recall that `x! = 1 * 2 * 3 * ... * x` and by convention, `0! = 1`.

*   For example, `f(3) = 0` because `3! = 6` has no zeroes at the end, while `f(11) = 2` because `11! = 39916800` has two zeroes at the end.

Given an integer `k`, return the number of non-negative integers `x` have the property that `f(x) = k`.

**Example 1:**

**Input:** k = 0
**Output:** 5
**Explanation:** 0!, 1!, 2!, 3!, and 4! end with k = 0 zeroes.

**Example 2:**

**Input:** k = 5
**Output:** 0
**Explanation:** There is no x such that x! ends in k = 5 zeroes.

**Example 3:**

**Input:** k = 3
**Output:** 5

**Constraints:**

*   `0 <= k <= 109`

## A solution in Java

```java
public boolean canTransform(String start, String end) {
    if (start.length() != end.length()) return false;

    int i = 0, j = 0;
    int n = start.length();
    while (i < n && j < n) {
        while (i < n && start.charAt(i) == 'X') i++;
        while (j < n && end.charAt(j) == 'X') j++;

        if (start.charAt(i) != end.charAt(j)) return false;

        if ((start.charAt(i) == 'R' && i > j) || (start.charAt(i) == 'L' && i < j)) return false;

        i++; j++;
    }
    return true;
}
```
The algorithm follows the following steps:

1. Check if the lengths of the `start` and `end` strings are the same, if they are not, return `false`.
2. Initialize two pointers `i` and `j`, representing the current position within the start and end strings, respectively.
3. Use a while loop to iterate through the characters in the strings:
   a. If the current character in `start` or `end` is `'X'`, increment the respective index.
   b. If the current characters in `start` and `end` are different, return `false`. This means the strings cannot be transformed into each other.
   c. If the current character in `start` is `'R'` and `i > j`, return `false`. This means we cannot move `'R'` to the left, as it violates the given moves.
   d. Similarly, if the current character in `start` is `'L'` and `i < j`, return `false`. This means we cannot move `'L'` to the right, as it violates the given moves.
   e. Increment `i` and `j`.
4. After the loop, return `true`, indicating that a sequence of moves exists to transform the `start` string into the `end` string.

## A solution in C++

```cpp
bool canTransform(string start, string end) {
    if (start.size() != end.size()) return false;

    int i = 0, j = 0;
    int n = start.size();
    while (i < n && j < n) {
        while (i < n && start[i] == 'X') i++;
        while (j < n && end[j] == 'X') j++;

        if (start[i] != end[j]) return false;

        if ((start[i] == 'R' && i > j) || (start[i] == 'L' && i < j)) return false;

        i++; j++;
    }
    return true;
}
```
The algorithm follows the following steps:

1. Check if the lengths of the `start` and `end` strings are the same, if they are not, return `false`.
2. Initialize two pointers `i` and `j`, representing the current position within the start and end strings, respectively.
3. Use a while loop to iterate through the characters in the strings:
   a. If the current character in `start` or `end` is `'X'`, increment the respective index.
   b. If the current characters in `start` and `end` are different, return `false`. This means the strings cannot be transformed into each other.
   c. If the current character in `start` is `'R'` and `i > j`, return `false`. This means we cannot move `'R'` to the left, as it violates the given moves.
   d. Similarly, if the current character in `start` is `'L'` and `i < j`, return `false`. This means we cannot move `'L'` to the right, as it violates the given moves.
   e. Increment `i` and `j`.
4. After the loop, return `true`, indicating that a sequence of moves exists to transform the `start` string into the `end` string.

## A solution in Python

```python
def canTransform(start: str, end: str) -> bool:
    if len(start) != len(end): return False

    i, j = 0, 0
    n = len(start)
    while i < n and j < n:
        while i < n and start[i] == 'X': i += 1
        while j < n and end[j] == 'X': j += 1

        if start[i] != end[j]: return False

        if (start[i] == 'R' and i > j) or (start[i] == 'L' and i < j): return False

        i += 1; j += 1
    return True
```
The algorithm follows the following steps:

1. Check if the lengths of the `start` and `end` strings are the same, if they are not, return `false`.
2. Initialize two pointers `i` and `j`, representing the current position within the start and end strings, respectively.
3. Use a while loop to iterate through the characters in the strings:
   a. If the current character in `start` or `end` is `'X'`, increment the respective index.
   b. If the current characters in `start` and `end` are different, return `false`. This means the strings cannot be transformed into each other.
   c. If the current character in `start` is `'R'` and `i > j`, return `false`. This means we cannot move `'R'` to the left, as it violates the given moves.
   d. Similarly, if the current character in `start` is `'L'` and `i < j`, return `false`. This means we cannot move `'L'` to the right, as it violates the given moves.
   e. Increment `i` and `j`.
4. After the loop, return `true`, indicating that a sequence of moves exists to transform the `start` string into the `end` string.

## A solution in Javascript

```javascript
function canTransform(start, end) {
    if (start.length !== end.length) return false;

    let i = 0, j = 0;
    const n = start.length;
    while (i < n && j < n) {
        while (i < n && start[i] === 'X') i++;
        while (j < n && end[j] === 'X') j++;

        if (start[i] !== end[j]) return false;

        if ((start[i] === 'R' && i > j) || (start[i] === 'L' && i < j)) return false;

        i++; j++;
    }
    return true;
}
```
The algorithm follows the following steps:

1. Check if the lengths of the `start` and `end` strings are the same, if they are not, return `false`.
2. Initialize two pointers `i` and `j`, representing the current position within the start and end strings, respectively.
3. Use a while loop to iterate through the characters in the strings:
   a. If the current character in `start` or `end` is `'X'`, increment the respective index.
   b. If the current characters in `start` and `end` are different, return `false`. This means the strings cannot be transformed into each other.
   c. If the current character in `start` is `'R'` and `i > j`, return `false`. This means we cannot move `'R'` to the left, as it violates the given moves.
   d. Similarly, if the current character in `start` is `'L'` and `i < j`, return `false`. This means we cannot move `'L'` to the right, as it violates the given moves.
   e. Increment `i` and `j`.
4. After the loop, return `true`, indicating that a sequence of moves exists to transform the `start` string into the `end` string.