# Minimum Time to Make Rope Colorful

- slug: minimum-time-to-make-rope-colorful
- difficulty: Medium

Alice has `n` balloons arranged on a rope. You are given a **0-indexed** string `colors` where `colors[i]` is the color of the `ith` balloon.

Alice wants the rope to be **colorful**. She does not want **two consecutive balloons** to be of the same color, so she asks Bob for help. Bob can remove some balloons from the rope to make it **colorful**. You are given a **0-indexed** integer array `neededTime` where `neededTime[i]` is the time (in seconds) that Bob needs to remove the `ith` balloon from the rope.

Return _the **minimum time** Bob needs to make the rope **colorful**_.

**Example 1:**

**Input:** colors =  "abaac ", neededTime = \[1,2,3,4,5\]
**Output:** 3
**Explanation:** In the above image, 'a' is blue, 'b' is red, and 'c' is green.
Bob can remove the blue balloon at index 2. This takes 3 seconds.
There are no longer two consecutive balloons of the same color. Total time = 3.

**Example 2:**

**Input:** colors =  "abc ", neededTime = \[1,2,3\]
**Output:** 0
**Explanation:** The rope is already colorful. Bob does not need to remove any balloons from the rope.

**Example 3:**

**Input:** colors =  "aabaa ", neededTime = \[1,2,3,4,1\]
**Output:** 2
**Explanation:** Bob will remove the ballons at indices 0 and 4. Each ballon takes 1 second to remove.
There are no longer two consecutive balloons of the same color. Total time = 1 + 1 = 2.

**Constraints:**

*   `n == colors.length == neededTime.length`
*   `1 <= n <= 105`
*   `1 <= neededTime[i] <= 104`
*   `colors` contains only lowercase English letters.

## A solution in Java

```java
public int minTime(String colors, int[] neededTime) {
    int res = 0, prev = -1;
    for (int i = 0; i < colors.length() - 1; i++) {
        if (colors.charAt(i) == colors.charAt(i + 1)) {
            if (prev == -1 || neededTime[i] < neededTime[prev]) prev = i;
            if (neededTime[i + 1] < neededTime[prev]) prev = i + 1;
            res += neededTime[prev];
            neededTime[prev] = 1000000;
            prev = -1;
        }
    }
    return res;
}
```
The algorithm needs to find the minimum time to remove consecutive balloons with the same color. It iterates through the colors array, and for each pair of consecutive colors that are the same, it checks which of the two balloons takes the least time to remove, and removes it. Then, it updates the `neededTime` array by setting the removed balloon's needed time to a large number (1000000) and sums up the needed time for each removed balloon in the `res` variable. Finally, it returns the total time spent (the value of `res`).

## A solution in C++

```cpp
int minTime(string colors, vector<int>& neededTime) {
    int res = 0, prev = -1;
    for (int i = 0; i < colors.length() - 1; i++) {
        if (colors[i] == colors[i + 1]) {
            if (prev == -1 || neededTime[i] < neededTime[prev]) prev = i;
            if (neededTime[i + 1] < neededTime[prev]) prev = i + 1;
            res += neededTime[prev];
            neededTime[prev] = 1000000;
            prev = -1;
        }
    }
    return res;
}
```
The algorithm needs to find the minimum time to remove consecutive balloons with the same color. It iterates through the colors array, and for each pair of consecutive colors that are the same, it checks which of the two balloons takes the least time to remove, and removes it. Then, it updates the `neededTime` array by setting the removed balloon's needed time to a large number (1000000) and sums up the needed time for each removed balloon in the `res` variable. Finally, it returns the total time spent (the value of `res`).

## A solution in Python

```python
def minTime(colors: str, neededTime: List[int]) -> int:
    res, prev = 0, -1
    for i in range(len(colors) - 1):
        if colors[i] == colors[i + 1]:
            if prev == -1 or neededTime[i] < neededTime[prev]:
                prev = i
            if neededTime[i + 1] < neededTime[prev]:
                prev = i + 1
            res += neededTime[prev]
            neededTime[prev] = 1000000
            prev = -1
    return res
```
The algorithm needs to find the minimum time to remove consecutive balloons with the same color. It iterates through the colors array, and for each pair of consecutive colors that are the same, it checks which of the two balloons takes the least time to remove, and removes it. Then, it updates the `neededTime` array by setting the removed balloon's needed time to a large number (1000000) and sums up the needed time for each removed balloon in the `res` variable. Finally, it returns the total time spent (the value of `res`).

## A solution in Javascript

```javascript
function minTime(colors, neededTime) {
    let res = 0, prev = -1;
    for (let i = 0; i < colors.length - 1; i++) {
        if (colors[i] === colors[i + 1]) {
            if (prev === -1 || neededTime[i] < neededTime[prev]) prev = i;
            if (neededTime[i + 1] < neededTime[prev]) prev = i + 1;
            res += neededTime[prev];
            neededTime[prev] = 1000000;
            prev = -1;
        }
    }
    return res;
}
```
The algorithm needs to find the minimum time to remove consecutive balloons with the same color. It iterates through the colors array, and for each pair of consecutive colors that are the same, it checks which of the two balloons takes the least time to remove, and removes it. Then, it updates the `neededTime` array by setting the removed balloon's needed time to a large number (1000000) and sums up the needed time for each removed balloon in the `res` variable. Finally, it returns the total time spent (the value of `res`).


# Remove Max Number of Edges to Keep Graph Fully Traversable

- slug: remove-max-number-of-edges-to-keep-graph-fully-traversable
- difficulty: Hard

Alice and Bob have an undirected graph of `n` nodes and three types of edges:

*   Type 1: Can be traversed by Alice only.
*   Type 2: Can be traversed by Bob only.
*   Type 3: Can be traversed by both Alice and Bob.

Given an array `edges` where `edges[i] = [typei, ui, vi]` represents a bidirectional edge of type `typei` between nodes `ui` and `vi`, find the maximum number of edges you can remove so that after removing the edges, the graph can still be fully traversed by both Alice and Bob. The graph is fully traversed by Alice and Bob if starting from any node, they can reach all other nodes.

Return _the maximum number of edges you can remove, or return_ `-1` _if Alice and Bob cannot fully traverse the graph._

**Example 1:**

**Input:** n = 4, edges = \[\[3,1,2\],\[3,2,3\],\[1,1,3\],\[1,2,4\],\[1,1,2\],\[2,3,4\]\]
**Output:** 2
**Explanation:** If we remove the 2 edges \[1,1,2\] and \[1,1,3\]. The graph will still be fully traversable by Alice and Bob. Removing any additional edge will not make it so. So the maximum number of edges we can remove is 2.

**Example 2:**

**Input:** n = 4, edges = \[\[3,1,2\],\[3,2,3\],\[1,1,4\],\[2,1,4\]\]
**Output:** 0
**Explanation:** Notice that removing any edge will not make the graph fully traversable by Alice and Bob.

**Example 3:**

**Input:** n = 4, edges = \[\[3,2,3\],\[1,1,2\],\[2,3,4\]\]
**Output:** -1
**Explanation:** In the current graph, Alice cannot reach node 4 from the other nodes. Likewise, Bob cannot reach 1. Therefore it's impossible to make the graph fully traversable.

**Constraints:**

*   `1 <= n <= 105`
*   `1 <= edges.length <= min(105, 3 * n * (n - 1) / 2)`
*   `edges[i].length == 3`
*   `1 <= typei <= 3`
*   `1 <= ui < vi <= n`
*   All tuples `(typei, ui, vi)` are distinct.

## A solution in Java

```java
class UnionFind {
    int[] parent;
    int components;

    UnionFind(int size) {
        parent = new int[size];
        components = size;
        for (int i = 0; i < size; ++i) {
            parent[i] = i;
        }
    }

    int find(int x) {
        if (x != parent[x])
            parent[x] = find(parent[x]);
        return parent[x];
    }

    boolean unite(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            parent[rootX] = rootY;
            components--;
            return true;
        }
        return false;
    }
}

public int maxNumEdgesToRemove(int n, int[][] edges) {
    UnionFind ufA = new UnionFind(n + 1);
    UnionFind ufB = new UnionFind(n + 1);
    int common_edges = 0;

    for (int[] edge : edges) {
        if (edge[0] == 3) {
            if (ufA.unite(edge[1], edge[2])) {
                ufB.unite(edge[1], edge[2]);
                common_edges++;
            }
        }
    }

    int removed_edges = 0;
    for (int[] edge : edges) {
        UnionFind uf = (edge[0] == 1) ? ufA : (edge[0] == 2) ? ufB : null;
        if (uf != null && !uf.unite(edge[1], edge[2])) {
            removed_edges++;
        }
    }

    if (ufA.components != 2 || ufB.components != 2)
        return -1;
    return removed_edges - common_edges;
}
```
The algorithm first initializes one union-find data structure for Alice (ufA) and another for Bob (ufB).

In the first loop, the algorithm goes through all the edges and unites the endpoints of type 3 edges using both Alice's and Bob's union-find data structures. This is because type 3 edges can be traversed by both Alice and Bob. The number of type 3 edges united is counted as `common_edges`.

In the second loop, the algorithm goes through all the edges again, this time trying to unite the endpoints using the respective union-find data structure for type 1 and type 2 edges. If an edge cannot be united (because the two endpoints already belong to the same connected component), it means that this edge can be removed, so the count of `removed_edges` is incremented.

Finally, the algorithm checks if both Alice's and Bob's graphs are fully traversable by verifying that the number of connected components in each union-find data structure is 2 (the initial connected component and the fully connected graph). If they are, the algorithm returns the count of removed edges minus the count of common edges (this subtraction is done because common_edges shouldn't be counted twice); otherwise, it returns -1, indicating that the graph cannot be fully traversed by both Alice and Bob.

## A solution in C++

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

class UnionFind {
public:
    vector<int> parent;
    int components;

    UnionFind(int size) {
        parent.resize(size);
        components = size;
        for (int i = 0; i < size; ++i) {
            parent[i] = i;
        }
    }

    int find(int x) {
        if (x != parent[x])
            parent[x] = find(parent[x]);
        return parent[x];
    }

    bool unite(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            parent[rootX] = rootY;
            components--;
            return true;
        }
        return false;
    }
};

int maxNumEdgesToRemove(int n, vector<vector<int>> &edges) {
    UnionFind ufA(n + 1), ufB(n + 1);
    int common_edges = 0;

    for (auto &edge : edges) {
        if (edge[0] == 3) {
            if (ufA.unite(edge[1], edge[2])) {
                ufB.unite(edge[1], edge[2]);
                common_edges++;
            }
        }
    }

    int removed_edges = 0;
    for (auto &edge : edges) {
        UnionFind *uf = (edge[0] == 1) ? &ufA : (edge[0] == 2) ? &ufB : nullptr;
        if (uf && !uf->unite(edge[1], edge[2])) {
            removed_edges++;
        }
    }

    if (ufA.components != 2 || ufB.components != 2)
        return -1;
    return removed_edges - common_edges;
}
```
The algorithm first initializes one union-find data structure for Alice (ufA) and another for Bob (ufB).

In the first loop, the algorithm goes through all the edges and unites the endpoints of type 3 edges using both Alice's and Bob's union-find data structures. This is because type 3 edges can be traversed by both Alice and Bob. The number of type 3 edges united is counted as `common_edges`.

In the second loop, the algorithm goes through all the edges again, this time trying to unite the endpoints using the respective union-find data structure for type 1 and type 2 edges. If an edge cannot be united (because the two endpoints already belong to the same connected component), it means that this edge can be removed, so the count of `removed_edges` is incremented.

Finally, the algorithm checks if both Alice's and Bob's graphs are fully traversable by verifying that the number of connected components in each union-find data structure is 2 (the initial connected component and the fully connected graph). If they are, the algorithm returns the count of removed edges minus the count of common edges (this subtraction is done because common_edges shouldn't be counted twice); otherwise, it returns -1, indicating that the graph cannot be fully traversed by both Alice and Bob.

## A solution in Python

```python
class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size))
        self.components = size

    def find(self, x):
        if x != self.parent[x]:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def unite(self, x, y):
        root_x, root_y = self.find(x), self.find(y)
        if root_x != root_y:
            self.parent[root_x] = root_y
            self.components -= 1
            return True
        return False

def max_num_edges_to_remove(n, edges):
    ufA, ufB = UnionFind(n + 1), UnionFind(n + 1)
    common_edges = 0

    for t, u, v in edges:
        if t == 3:
            if ufA.unite(u, v):
                ufB.unite(u, v)
                common_edges += 1

    removed_edges = 0
    for t, u, v in edges:
        uf = ufA if t == 1 else ufB if t == 2 else None
        if uf and not uf.unite(u, v):
            removed_edges += 1

    return -1 if ufA.components != 2 or ufB.components != 2 else removed_edges - common_edges
```
The algorithm first initializes one union-find data structure for Alice (ufA) and another for Bob (ufB).

In the first loop, the algorithm goes through all the edges and unites the endpoints of type 3 edges using both Alice's and Bob's union-find data structures. This is because type 3 edges can be traversed by both Alice and Bob. The number of type 3 edges united is counted as `common_edges`.

In the second loop, the algorithm goes through all the edges again, this time trying to unite the endpoints using the respective union-find data structure for type 1 and type 2 edges. If an edge cannot be united (because the two endpoints already belong to the same connected component), it means that this edge can be removed, so the count of `removed_edges` is incremented.

Finally, the algorithm checks if both Alice's and Bob's graphs are fully traversable by verifying that the number of connected components in each union-find data structure is 2 (the initial connected component and the fully connected graph). If they are, the algorithm returns the count of removed edges minus the count of common edges (this subtraction is done because common_edges shouldn't be counted twice); otherwise, it returns -1, indicating that the graph cannot be fully traversed by both Alice and Bob.

## A solution in Javascript

```javascript
class UnionFind {
    constructor(size) {
        this.parent = Array.from({length: size}, (_, i) => i);
        this.components = size;
    }

    find(x) {
        if (x !== this.parent[x]) {
            this.parent[x] = this.find(this.parent[x]);
        }
        return this.parent[x];
    }

    unite(x, y) {
        const rootX = this.find(x);
        const rootY = this.find(y);
        if (rootX !== rootY) {
            this.parent[rootX] = rootY;
            this.components--;
            return true;
        }
        return false;
    }
}

function maxNumEdgesToRemove(n, edges) {
    const ufA = new UnionFind(n + 1);
    const ufB = new UnionFind(n + 1);
    let common_edges = 0;

    for (const [t, u, v] of edges) {
        if (t === 3) {
            if (ufA.unite(u, v)) {
                ufB.unite(u, v);
                common_edges++;
            }
        }
    }

    let removed_edges = 0;
    for (const [t, u, v] of edges) {
        const uf = (t === 1) ? ufA : (t === 2) ? ufB : null;
        if (uf && !uf.unite(u, v)) {
            removed_edges++;
        }
    }

    return (ufA.components !== 2 || ufB.components !== 2) ? -1 : removed_edges - common_edges;
}
```
The algorithm first initializes one union-find data structure for Alice (ufA) and another for Bob (ufB).

In the first loop, the algorithm goes through all the edges and unites the endpoints of type 3 edges using both Alice's and Bob's union-find data structures. This is because type 3 edges can be traversed by both Alice and Bob. The number of type 3 edges united is counted as `common_edges`.

In the second loop, the algorithm goes through all the edges again, this time trying to unite the endpoints using the respective union-find data structure for type 1 and type 2 edges. If an edge cannot be united (because the two endpoints already belong to the same connected component), it means that this edge can be removed, so the count of `removed_edges` is incremented.

Finally, the algorithm checks if both Alice's and Bob's graphs are fully traversable by verifying that the number of connected components in each union-find data structure is 2 (the initial connected component and the fully connected graph). If they are, the algorithm returns the count of removed edges minus the count of common edges (this subtraction is done because common_edges shouldn't be counted twice); otherwise, it returns -1, indicating that the graph cannot be fully traversed by both Alice and Bob.


# Put Boxes Into the Warehouse II

- slug: put-boxes-into-the-warehouse-ii
- difficulty: Medium

You are given two arrays of positive integers, `boxes` and `warehouse`, representing the heights of some boxes of unit width and the heights of `n` rooms in a warehouse respectively. The warehouse's rooms are labeled from `0` to `n - 1` from left to right where `warehouse[i]` (0-indexed) is the height of the `ith` room.

Boxes are put into the warehouse by the following rules:

*   Boxes cannot be stacked.
*   You can rearrange the insertion order of the boxes.
*   Boxes can be pushed into the warehouse from **either side** (left or right)
*   If the height of some room in the warehouse is less than the height of a box, then that box and all other boxes behind it will be stopped before that room.

Return _the maximum number of boxes you can put into the warehouse._

**Example 1:**

**Input:** boxes = \[1,2,2,3,4\], warehouse = \[3,4,1,2\]
**Output:** 4
**Explanation:**

We can store the boxes in the following order:
1- Put the yellow box in room 2 from either the left or right side.
2- Put the orange box in room 3 from the right side.
3- Put the green box in room 1 from the left side.
4- Put the red box in room 0 from the left side.
Notice that there are other valid ways to put 4 boxes such as swapping the red and green boxes or the red and orange boxes.

**Example 2:**

**Input:** boxes = \[3,5,5,2\], warehouse = \[2,1,3,4,5\]
**Output:** 3
**Explanation:**

It is not possible to put the two boxes of height 5 in the warehouse since there's only 1 room of height >= 5.
Other valid solutions are to put the green box in room 2 or to put the orange box first in room 2 before putting the green and red boxes.

**Constraints:**

*   `n == warehouse.length`
*   `1 <= boxes.length, warehouse.length <= 105`
*   `1 <= boxes[i], warehouse[i] <= 109`

## A solution in Java

```java
public int[] shuffle(int[] nums, int n) {
    int[] shuffled = new int[nums.length];
    for(int i = 0; i < n; i++) {
        shuffled[2*i] = nums[i];
        shuffled[2*i+1] = nums[i+n];
    }
    return shuffled;
}
```
The algorithm for solving this problem is quite simple:
1. Initialize an empty array called "shuffled" to store the shuffled elements.
2. Iterate through the first n elements of the input array (nums).
3. For each element at index i, add nums[i] and nums[i+n] to the "shuffled" array in that order.
4. Return the "shuffled" array.

## A solution in C++

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

vector<int> shuffle(vector<int>& nums, int n) {
    vector<int> shuffled;
    for(int i = 0; i < n; ++i) {
        shuffled.push_back(nums[i]);
        shuffled.push_back(nums[i+n]);
    }
    return shuffled;
}
```
The algorithm for solving this problem is quite simple:
1. Initialize an empty array called "shuffled" to store the shuffled elements.
2. Iterate through the first n elements of the input array (nums).
3. For each element at index i, add nums[i] and nums[i+n] to the "shuffled" array in that order.
4. Return the "shuffled" array.

## A solution in Python

```python
def shuffle(nums, n):
    shuffled = []
    for i in range(n):
        shuffled.append(nums[i])
        shuffled.append(nums[i+n])
    return shuffled
```
The algorithm for solving this problem is quite simple:
1. Initialize an empty array called "shuffled" to store the shuffled elements.
2. Iterate through the first n elements of the input array (nums).
3. For each element at index i, add nums[i] and nums[i+n] to the "shuffled" array in that order.
4. Return the "shuffled" array.

## A solution in Javascript

```javascript
function shuffle(nums, n) {
    const shuffled = [];
    for(let i = 0; i < n; i++) {
        shuffled.push(nums[i]);
        shuffled.push(nums[i+n]);
    }
    return shuffled;
}
```
The algorithm for solving this problem is quite simple:
1. Initialize an empty array called "shuffled" to store the shuffled elements.
2. Iterate through the first n elements of the input array (nums).
3. For each element at index i, add nums[i] and nums[i+n] to the "shuffled" array in that order.
4. Return the "shuffled" array.


# Special Positions in a Binary Matrix

- slug: special-positions-in-a-binary-matrix
- difficulty: Easy

Given an `m x n` binary matrix `mat`, return _the number of special positions in_ `mat`_._

A position `(i, j)` is called **special** if `mat[i][j] == 1` and all other elements in row `i` and column `j` are `0` (rows and columns are **0-indexed**).

**Example 1:**

**Input:** mat = \[\[1,0,0\],\[0,0,1\],\[1,0,0\]\]
**Output:** 1
**Explanation:** (1, 2) is a special position because mat\[1\]\[2\] == 1 and all other elements in row 1 and column 2 are 0.

**Example 2:**

**Input:** mat = \[\[1,0,0\],\[0,1,0\],\[0,0,1\]\]
**Output:** 3
**Explanation:** (0, 0), (1, 1) and (2, 2) are special positions.

**Constraints:**

*   `m == mat.length`
*   `n == mat[i].length`
*   `1 <= m, n <= 100`
*   `mat[i][j]` is either `0` or `1`.

## A solution in Java

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

class BrowserHistory {
    int currentIndex;
    List<String> history;

    public BrowserHistory(String homepage) {
        this.currentIndex = 0;
        this.history = new ArrayList<>();
        history.add(homepage);
    }

    public void visit(String url) {
        while (history.size() > currentIndex + 1) {
            history.remove(history.size()-1);
        }
        history.add(url);
        currentIndex++;
    }

    public String back(int steps) {
        currentIndex -= Math.min(steps, currentIndex);
        return history.get(currentIndex);
    }

    public String forward(int steps) {
        currentIndex += Math.min(steps, history.size() - 1 - currentIndex);
        return history.get(currentIndex);
    }
}
```
We have a BrowserHistory class which will keep track of visited urls as well as the current index of the history.

Whenever the object of the class is instantiated, we pass the homepage and store it in the history (array, list or vector) at 0 index.

For "visit(url)" function:
- We will first resize the history (if needed) so that all the urls after the current index are removed, as whenever we visit a new URL, the forward history should be cleared. After that, we will append the new url and increment the current index.

For the "back(steps)" function:
- We move the current index by the minimum of `steps` and the current index which ensures that the current index never goes below 0. And then, the function returns the URL at the updated index.

For the "forward(steps)" function:
- We move the current index by the minimum of `steps` and the difference between the size of history and current index-1 (to ensure it doesn't exceed the index range). And then, return the URL at the updated index.

## A solution in C++

```cpp
class BrowserHistory {
public:
    int currentIndex;
    vector<string> history;

    BrowserHistory(string homepage) {
        history.push_back(homepage);
        currentIndex = 0;
    }

    void visit(string url) {
        history.resize(currentIndex + 1);
        history.push_back(url);
        currentIndex++;
    }

    string back(int steps) {
        currentIndex -= min(steps, currentIndex);
        return history[currentIndex];
    }

    string forward(int steps) {
        currentIndex += min(steps, (int)(history.size() - 1 - currentIndex));
        return history[currentIndex];
    }
};
```
We have a BrowserHistory class which will keep track of visited urls as well as the current index of the history.

Whenever the object of the class is instantiated, we pass the homepage and store it in the history (array, list or vector) at 0 index.

For "visit(url)" function:
- We will first resize the history (if needed) so that all the urls after the current index are removed, as whenever we visit a new URL, the forward history should be cleared. After that, we will append the new url and increment the current index.

For the "back(steps)" function:
- We move the current index by the minimum of `steps` and the current index which ensures that the current index never goes below 0. And then, the function returns the URL at the updated index.

For the "forward(steps)" function:
- We move the current index by the minimum of `steps` and the difference between the size of history and current index-1 (to ensure it doesn't exceed the index range). And then, return the URL at the updated index.

## A solution in Python

```python
class BrowserHistory:

    def __init__(self, homepage: str):
        self.history = [homepage]
        self.current_index = 0

    def visit(self, url: str):
        self.history = self.history[:self.current_index + 1]
        self.history.append(url)
        self.current_index += 1

    def back(self, steps: int) -> str:
        self.current_index -= min(steps, self.current_index)
        return self.history[self.current_index]

    def forward(self, steps:int) -> str:
        self.current_index += min(steps, len(self.history) - 1 - self.current_index)
        return self.history[self.current_index]
```
We have a BrowserHistory class which will keep track of visited urls as well as the current index of the history.

Whenever the object of the class is instantiated, we pass the homepage and store it in the history (array, list or vector) at 0 index.

For "visit(url)" function:
- We will first resize the history (if needed) so that all the urls after the current index are removed, as whenever we visit a new URL, the forward history should be cleared. After that, we will append the new url and increment the current index.

For the "back(steps)" function:
- We move the current index by the minimum of `steps` and the current index which ensures that the current index never goes below 0. And then, the function returns the URL at the updated index.

For the "forward(steps)" function:
- We move the current index by the minimum of `steps` and the difference between the size of history and current index-1 (to ensure it doesn't exceed the index range). And then, return the URL at the updated index.

## A solution in Javascript

```javascript
class BrowserHistory {
    constructor(homepage) {
        this.history = [homepage];
        this.currentIndex = 0;
    }

    visit(url) {
        this.history = this.history.slice(0, this.currentIndex + 1);
        this.history.push(url);
        this.currentIndex++;
    }

    back(steps) {
        this.currentIndex -= Math.min(steps, this.currentIndex);
        return this.history[this.currentIndex];
    }

    forward(steps) {
        this.currentIndex += Math.min(steps, this.history.length - 1 - this.currentIndex);
        return this.history[this.currentIndex];
    }
}
```
We have a BrowserHistory class which will keep track of visited urls as well as the current index of the history.

Whenever the object of the class is instantiated, we pass the homepage and store it in the history (array, list or vector) at 0 index.

For "visit(url)" function:
- We will first resize the history (if needed) so that all the urls after the current index are removed, as whenever we visit a new URL, the forward history should be cleared. After that, we will append the new url and increment the current index.

For the "back(steps)" function:
- We move the current index by the minimum of `steps` and the current index which ensures that the current index never goes below 0. And then, the function returns the URL at the updated index.

For the "forward(steps)" function:
- We move the current index by the minimum of `steps` and the difference between the size of history and current index-1 (to ensure it doesn't exceed the index range). And then, return the URL at the updated index.


# Count Unhappy Friends

- slug: count-unhappy-friends
- difficulty: Medium

You are given a list of `preferences` for `n` friends, where `n` is always **even**.

For each person `i`, `preferences[i]` contains a list of friends **sorted** in the **order of preference**. In other words, a friend earlier in the list is more preferred than a friend later in the list. Friends in each list are denoted by integers from `0` to `n-1`.

All the friends are divided into pairs. The pairings are given in a list `pairs`, where `pairs[i] = [xi, yi]` denotes `xi` is paired with `yi` and `yi` is paired with `xi`.

However, this pairing may cause some of the friends to be unhappy. A friend `x` is unhappy if `x` is paired with `y` and there exists a friend `u` who is paired with `v` but:

*   `x` prefers `u` over `y`, and
*   `u` prefers `x` over `v`.

Return _the number of unhappy friends_.

**Example 1:**

**Input:** n = 4, preferences = \[\[1, 2, 3\], \[3, 2, 0\], \[3, 1, 0\], \[1, 2, 0\]\], pairs = \[\[0, 1\], \[2, 3\]\]
**Output:** 2
**Explanation:**
Friend 1 is unhappy because:
- 1 is paired with 0 but prefers 3 over 0, and
- 3 prefers 1 over 2.
Friend 3 is unhappy because:
- 3 is paired with 2 but prefers 1 over 2, and
- 1 prefers 3 over 0.
Friends 0 and 2 are happy.

**Example 2:**

**Input:** n = 2, preferences = \[\[1\], \[0\]\], pairs = \[\[1, 0\]\]
**Output:** 0
**Explanation:** Both friends 0 and 1 are happy.

**Example 3:**

**Input:** n = 4, preferences = \[\[1, 3, 2\], \[2, 3, 0\], \[1, 3, 0\], \[0, 2, 1\]\], pairs = \[\[1, 3\], \[0, 2\]\]
**Output:** 4

**Constraints:**

*   `2 <= n <= 500`
*   `n` is even.
*   `preferences.length == n`
*   `preferences[i].length == n - 1`
*   `0 <= preferences[i][j] <= n - 1`
*   `preferences[i]` does not contain `i`.
*   All values in `preferences[i]` are unique.
*   `pairs.length == n/2`
*   `pairs[i].length == 2`
*   `xi != yi`
*   `0 <= xi, yi <= n - 1`
*   Each person is contained in **exactly one** pair.

## A solution in Java

```java
public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
    int[][][] dp = new int[m][n][target + 1];

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            Arrays.fill(dp[i][j], Integer.MAX_VALUE);
        }
    }

    if (houses[0] != 0) {
        dp[0][houses[0] - 1][1] = 0;
    } else {
        for (int j = 0; j < n; j++) {
            dp[0][j][1] = cost[0][j];
        }
    }

    for (int i = 1; i < m; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 1; k <= target; k++) {
                if (houses[i] != 0 && houses[i] != j + 1) {
                    continue;
                }
                int paint_cost = (houses[i] != 0) ? 0 : cost[i][j];

                for (int l = 0; l < n; l++) {
                    if (l == j) {
                        dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][l][k] + paint_cost);
                    } else {
                        dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][l][k - 1] + paint_cost);
                    }
                }
            }
        }
    }

    int ans = Integer.MAX_VALUE;
    for (int j = 0; j < n; j++) {
        ans = Math.min(ans, dp[m - 1][j][target]);
    }
    return (ans == Integer.MAX_VALUE) ? -1 : ans;
}
```
The algorithm uses a 3D DP table `dp[i][j][k]` to store minimum cost for the first i houses, where the i-th house is painted with color j and there are k neighborhoods. For each house, we iterate through different colors and targets, if the house is unpainted or the current color matches the house color, we calculate the paint cost, and then update `dp[i][j][k]` by choosing either the same color from the previous house (maintaining neighborhoods count) or different color (increasing neighborhoods count).

After filling the DP table, we iterate through all colors in the last house, and get the minimum cost where the total neighborhoods equal the target. If the minimum cost is still infinity (initial value), it means there is no possible solution, so return -1.

## A solution in C++

```cpp
int minCost(vector<int>& houses, vector<vector<int>>& cost, int m, int n, int target) {
    int dp[m][n][target + 1];
    memset(dp, 0x3f, sizeof(dp));

    if (houses[0] != 0) {
        dp[0][houses[0] - 1][1] = 0;
    } else {
        for (int j = 0; j < n; j++) {
            dp[0][j][1] = cost[0][j];
        }
    }

    for (int i = 1; i < m; i++)
        for (int j = 0; j < n; j++)
            for (int k = 1; k <= target; k++) {
                if (houses[i] != 0 && houses[i] != j + 1) {
                    continue;
                }
                int paint_cost = (houses[i] != 0) ? 0 : cost[i][j];

                for (int l = 0; l < n; l++) {
                    if (l == j) {
                        dp[i][j][k] = min(dp[i][j][k], dp[i - 1][l][k] + paint_cost);
                    } else {
                        dp[i][j][k] = min(dp[i][j][k], dp[i - 1][l][k - 1] + paint_cost);
                    }
                }
            }

    int ans = 1e9;
    for (int j = 0; j < n; j++) {
        ans = min(ans, dp[m - 1][j][target]);
    }
    return (ans == 1e9) ? -1 : ans;
}
```
The algorithm uses a 3D DP table `dp[i][j][k]` to store minimum cost for the first i houses, where the i-th house is painted with color j and there are k neighborhoods. For each house, we iterate through different colors and targets, if the house is unpainted or the current color matches the house color, we calculate the paint cost, and then update `dp[i][j][k]` by choosing either the same color from the previous house (maintaining neighborhoods count) or different color (increasing neighborhoods count).

After filling the DP table, we iterate through all colors in the last house, and get the minimum cost where the total neighborhoods equal the target. If the minimum cost is still infinity (initial value), it means there is no possible solution, so return -1.

## A solution in Python

```python
def minCost(houses, cost, m, n, target):
    dp = [[[float('inf')] * (target + 1) for _ in range(n)] for _ in range(m)]

    if houses[0] != 0:
        dp[0][houses[0] - 1][1] = 0
    else:
        for j in range(n):
            dp[0][j][1] = cost[0][j]

    for i in range(1, m):
        for j in range(n):
            for k in range(1, target + 1):
                if houses[i] != 0 and houses[i] != j + 1:
                    continue
                paint_cost = 0 if houses[i] != 0 else cost[i][j]

                for l in range(n):
                    if l == j:
                        dp[i][j][k] = min(dp[i][j][k], dp[i - 1][l][k] + paint_cost)
                    else:
                        dp[i][j][k] = min(dp[i][j][k], dp[i - 1][l][k - 1] + paint_cost)

    ans = min(dp[m - 1][j][target] for j in range(n))
    return -1 if ans == float('inf') else ans
```
The algorithm uses a 3D DP table `dp[i][j][k]` to store minimum cost for the first i houses, where the i-th house is painted with color j and there are k neighborhoods. For each house, we iterate through different colors and targets, if the house is unpainted or the current color matches the house color, we calculate the paint cost, and then update `dp[i][j][k]` by choosing either the same color from the previous house (maintaining neighborhoods count) or different color (increasing neighborhoods count).

After filling the DP table, we iterate through all colors in the last house, and get the minimum cost where the total neighborhoods equal the target. If the minimum cost is still infinity (initial value), it means there is no possible solution, so return -1.

## A solution in Javascript

```javascript
function minCost(houses, cost, m, n, target) {
    const dp = Array.from({length: m}, () => Array.from({length: n}, () => Array(target + 1).fill(Infinity)));

    if (houses[0] !== 0) {
        dp[0][houses[0] - 1][1] = 0;
    } else {
        for (let j = 0; j < n; j++) {
           dp[0][j][1] = cost[0][j];
        }
    }

    for (let i = 1; i < m; i++) {
        for (let j = 0; j < n; j++) {
            for (let k = 1; k <= target; k++) {
                if (houses[i] !== 0 && houses[i] !== j + 1) {
                    continue;
                }
                const paint_cost = (houses[i] !== 0) ? 0 : cost[i][j];

                for (let l = 0; l < n; l++) {
                    if (l === j) {
                        dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][l][k] + paint_cost);
                    } else {
                        dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][l][k - 1] + paint_cost);
                    }
                }
            }
        }
    }

    let ans = Infinity;
    for (let j = 0; j < n; j++) {
        ans = Math.min(ans, dp[m - 1][j][target]);
    }
    return (ans === Infinity) ? -1 : ans;
}
```
The algorithm uses a 3D DP table `dp[i][j][k]` to store minimum cost for the first i houses, where the i-th house is painted with color j and there are k neighborhoods. For each house, we iterate through different colors and targets, if the house is unpainted or the current color matches the house color, we calculate the paint cost, and then update `dp[i][j][k]` by choosing either the same color from the previous house (maintaining neighborhoods count) or different color (increasing neighborhoods count).

After filling the DP table, we iterate through all colors in the last house, and get the minimum cost where the total neighborhoods equal the target. If the minimum cost is still infinity (initial value), it means there is no possible solution, so return -1.


# Min Cost to Connect All Points

- slug: min-cost-to-connect-all-points
- difficulty: Medium

You are given an array `points` representing integer coordinates of some points on a 2D-plane, where `points[i] = [xi, yi]`.

The cost of connecting two points `[xi, yi]` and `[xj, yj]` is the **manhattan distance** between them: `|xi - xj| + |yi - yj|`, where `|val|` denotes the absolute value of `val`.

Return _the minimum cost to make all points connected._ All points are connected if there is **exactly one** simple path between any two points.

**Example 1:**

**Input:** points = \[\[0,0\],\[2,2\],\[3,10\],\[5,2\],\[7,0\]\]
**Output:** 20
**Explanation:**

We can connect the points as shown above to get the minimum cost of 20.
Notice that there is a unique path between every pair of points.

**Example 2:**

**Input:** points = \[\[3,12\],\[-2,5\],\[-4,1\]\]
**Output:** 18

**Constraints:**

*   `1 <= points.length <= 1000`
*   `-106 <= xi, yi <= 106`
*   All pairs `(xi, yi)` are distinct.

## A solution in Java

```java
import java.util.Arrays;

public double average(int[] salary) {
    double sum = 0;
    int minSalary = Arrays.stream(salary).min().getAsInt();
    int maxSalary = Arrays.stream(salary).max().getAsInt();
    for (int s : salary) {
        sum += s;
    }
    sum -= (minSalary + maxSalary);
    return sum / (salary.length - 2);
}
```
First, find the minimum and maximum salary values in the salary array. The simplest method is to use existing standard library/helper functions provided by the programming languages to find the minimum and maximum values in the array. For C++, use `min_element()` and `max_element()`. For Java, use `Arrays.stream().min().getAsInt()` and `Arrays.stream().max().getAsInt()`. For Python, use `min()` and `max()`. For JavaScript, use `Math.min(...)` and `Math.max(...)`.

Next, calculate the sum of all salary values in the array using a loop. After that, subtract the minimum and maximum salary from the sum. Finally, divide the resulting sum by the total number of salary entries minus 2 (because we're excluding the minimum and maximum). This gives us the average salary excluding the minimum and maximum. Return the result as a double.

## A solution in C++

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

double average(vector<int>& salary) {
    double sum = 0;
    int min_salary = *min_element(salary.begin(), salary.end());
    int max_salary = *max_element(salary.begin(), salary.end());
    for (int s : salary) {
        sum += s;
    }
    sum -= (min_salary + max_salary);
    return sum / (salary.size() - 2);
}
```
First, find the minimum and maximum salary values in the salary array. The simplest method is to use existing standard library/helper functions provided by the programming languages to find the minimum and maximum values in the array. For C++, use `min_element()` and `max_element()`. For Java, use `Arrays.stream().min().getAsInt()` and `Arrays.stream().max().getAsInt()`. For Python, use `min()` and `max()`. For JavaScript, use `Math.min(...)` and `Math.max(...)`.

Next, calculate the sum of all salary values in the array using a loop. After that, subtract the minimum and maximum salary from the sum. Finally, divide the resulting sum by the total number of salary entries minus 2 (because we're excluding the minimum and maximum). This gives us the average salary excluding the minimum and maximum. Return the result as a double.

## A solution in Python

```python
def average(salary):
    min_salary = min(salary)
    max_salary = max(salary)
    sum_salaries = sum(salary)
    sum_salaries -= (min_salary + max_salary)
    return sum_salaries / (len(salary) - 2)
```
First, find the minimum and maximum salary values in the salary array. The simplest method is to use existing standard library/helper functions provided by the programming languages to find the minimum and maximum values in the array. For C++, use `min_element()` and `max_element()`. For Java, use `Arrays.stream().min().getAsInt()` and `Arrays.stream().max().getAsInt()`. For Python, use `min()` and `max()`. For JavaScript, use `Math.min(...)` and `Math.max(...)`.

Next, calculate the sum of all salary values in the array using a loop. After that, subtract the minimum and maximum salary from the sum. Finally, divide the resulting sum by the total number of salary entries minus 2 (because we're excluding the minimum and maximum). This gives us the average salary excluding the minimum and maximum. Return the result as a double.

## A solution in Javascript

```javascript
function average(salary) {
    let sum = 0, minSalary = Math.min(...salary), maxSalary = Math.max(...salary);
    for (let s of salary) {
        sum += s;
    }
    sum -= (minSalary + maxSalary);
    return sum / (salary.length - 2);
}
```
First, find the minimum and maximum salary values in the salary array. The simplest method is to use existing standard library/helper functions provided by the programming languages to find the minimum and maximum values in the array. For C++, use `min_element()` and `max_element()`. For Java, use `Arrays.stream().min().getAsInt()` and `Arrays.stream().max().getAsInt()`. For Python, use `min()` and `max()`. For JavaScript, use `Math.min(...)` and `Math.max(...)`.

Next, calculate the sum of all salary values in the array using a loop. After that, subtract the minimum and maximum salary from the sum. Finally, divide the resulting sum by the total number of salary entries minus 2 (because we're excluding the minimum and maximum). This gives us the average salary excluding the minimum and maximum. Return the result as a double.


# Check If String Is Transformable With Substring Sort Operations

- slug: check-if-string-is-transformable-with-substring-sort-operations
- difficulty: Hard

Given two strings `s` and `t`, transform string `s` into string `t` using the following operation any number of times:

*   Choose a **non-empty** substring in `s` and sort it in place so the characters are in **ascending order**.
    *   For example, applying the operation on the underlined substring in `"14234 "` results in `"12344 "`.

Return `true` if _it is possible to transform `s` into `t`_. Otherwise, return `false`.

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

**Example 1:**

**Input:** s =  "84532 ", t =  "34852 "
**Output:** true
**Explanation:** You can transform s into t using the following sort operations:
 "84532 " (from index 2 to 3) ->  "84352 "
 "84352 " (from index 0 to 2) ->  "34852 "

**Example 2:**

**Input:** s =  "34521 ", t =  "23415 "
**Output:** true
**Explanation:** You can transform s into t using the following sort operations:
 "34521 " ->  "23451 "
 "23451 " ->  "23415 "

**Example 3:**

**Input:** s =  "12345 ", t =  "12435 "
**Output:** false

**Constraints:**

*   `s.length == t.length`
*   `1 <= s.length <= 105`
*   `s` and `t` consist of only digits.

## A solution in Java

```java
public int kthFactor(int n, int k) {
    for (int i = 1; i <= n; ++i) {
        if (n % i == 0) {
            --k;
            if (k == 0) return i;
        }
    }
    return -1;
}
```
The algorithm starts with the smallest possible factor `i=1` and iterates through all numbers up to `n`. For each iteration, the algorithm checks if `n % i` is equal to 0, which means the current `i` is a factor of `n`. If so, it decrements the value of `k`. When `k` becomes zero, return the current `i`, as it is the kth factor. If the loop ends without finding the kth factor, return -1, since there are no k factors for given `n`.

## A solution in C++

```cpp
int kthFactor(int n, int k) {
    for (int i = 1; i <= n; ++i) {
        if (n % i == 0) {
            --k;
            if (k == 0) return i;
        }
    }
    return -1;
}
```
The algorithm starts with the smallest possible factor `i=1` and iterates through all numbers up to `n`. For each iteration, the algorithm checks if `n % i` is equal to 0, which means the current `i` is a factor of `n`. If so, it decrements the value of `k`. When `k` becomes zero, return the current `i`, as it is the kth factor. If the loop ends without finding the kth factor, return -1, since there are no k factors for given `n`.

## A solution in Python

```python
def kth_factor(n: int, k: int) -> int:
    for i in range(1, n+1):
        if n % i == 0:
            k -= 1
            if k == 0:
                return i
    return -1
```
The algorithm starts with the smallest possible factor `i=1` and iterates through all numbers up to `n`. For each iteration, the algorithm checks if `n % i` is equal to 0, which means the current `i` is a factor of `n`. If so, it decrements the value of `k`. When `k` becomes zero, return the current `i`, as it is the kth factor. If the loop ends without finding the kth factor, return -1, since there are no k factors for given `n`.

## A solution in Javascript

```javascript
function kthFactor(n, k) {
    for (let i = 1; i <= n; ++i) {
        if (n % i === 0) {
            --k;
            if (k === 0) return i;
        }
    }
    return -1;
}
```
The algorithm starts with the smallest possible factor `i=1` and iterates through all numbers up to `n`. For each iteration, the algorithm checks if `n % i` is equal to 0, which means the current `i` is a factor of `n`. If so, it decrements the value of `k`. When `k` becomes zero, return the current `i`, as it is the kth factor. If the loop ends without finding the kth factor, return -1, since there are no k factors for given `n`.


# Binary Search Tree Iterator II

- slug: binary-search-tree-iterator-ii
- difficulty: Medium

Implement the `BSTIterator` class that represents an iterator over the **[in-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#In-order_(LNR))** of a binary search tree (BST):

*   `BSTIterator(TreeNode root)` Initializes an object of the `BSTIterator` class. The `root` of the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST.
*   `boolean hasNext()` Returns `true` if there exists a number in the traversal to the right of the pointer, otherwise returns `false`.
*   `int next()` Moves the pointer to the right, then returns the number at the pointer.
*   `boolean hasPrev()` Returns `true` if there exists a number in the traversal to the left of the pointer, otherwise returns `false`.
*   `int prev()` Moves the pointer to the left, then returns the number at the pointer.

Notice that by initializing the pointer to a non-existent smallest number, the first call to `next()` will return the smallest element in the BST.

You may assume that `next()` and `prev()` calls will always be valid. That is, there will be at least a next/previous number in the in-order traversal when `next()`/`prev()` is called.

**Example 1:**

**Input**
\[ "BSTIterator ",  "next ",  "next ",  "prev ",  "next ",  "hasNext ",  "next ",  "next ",  "next ",  "hasNext ",  "hasPrev ",  "prev ",  "prev "\]
\[\[\[7, 3, 15, null, null, 9, 20\]\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\], \[null\]\]
**Output**
\[null, 3, 7, 3, 7, true, 9, 15, 20, false, true, 15, 9\]

**Explanation**
// The underlined element is where the pointer currently is.
BSTIterator bSTIterator = new BSTIterator(\[7, 3, 15, null, null, 9, 20\]); // state is  \[3, 7, 9, 15, 20\]
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 3
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 7
bSTIterator.prev(); // state becomes \[3, 7, 9, 15, 20\], return 3
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 7
bSTIterator.hasNext(); // return true
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 9
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 15
bSTIterator.next(); // state becomes \[3, 7, 9, 15, 20\], return 20
bSTIterator.hasNext(); // return false
bSTIterator.hasPrev(); // return true
bSTIterator.prev(); // state becomes \[3, 7, 9, 15, 20\], return 15
bSTIterator.prev(); // state becomes \[3, 7, 9, 15, 20\], return 9

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 105]`.
*   `0 <= Node.val <= 106`
*   At most `105` calls will be made to `hasNext`, `next`, `hasPrev`, and `prev`.

**Follow up:** Could you solve the problem without precalculating the values of the tree?

## A solution in Java

```java
public int findMaxLength(int[] nums) {
    int max_length = 0, zeroes = 0, ones = 0;
    HashMap<Integer, Integer> count_map = new HashMap<>();
    count_map.put(0, -1);

    for(int i = 0; i < nums.length; ++i) {
        if(nums[i] == 0)
            zeroes++;
        else
            ones++;

        if(!count_map.containsKey(zeroes - ones))
            count_map.put(zeroes - ones, i);
        else
            max_length = Math.max(max_length, i - count_map.get(zeroes - ones));
    }
    return max_length;
}
```
The algorithm uses a hashmap `count_map` to store the difference between the counts of 0's and 1's encountered in the array. We iterate through the input binary array `nums`, and for each element, we update the count of 0's and the count of 1's.

If the difference `(zeroes - ones)` is not present in the hashmap, we store it along with its index `i`. If the difference is already present in the hashmap, it means that we have found a subarray where 0's and 1's occur with a balanced frequency. We then update the maximum length of such a subarray if the difference with the stored index is larger than the current max_length.

The algorithm returns the max_length of balanced subarrays after iteration, accounting for the single element deletion, as it inherently checks for subarrays with equal numbers of 1's and 0's.

## A solution in C++

```cpp
int findMaxLength(vector<int>& nums) {
    int max_length = 0, zeroes = 0, ones = 0;
    unordered_map<int, int> count_map;
    count_map[0] = -1;

    for(int i = 0; i < nums.size(); ++i) {
        if(nums[i] == 0)
            zeroes++;
        else
            ones++;

        if(count_map.count(zeroes - ones) == 0)
            count_map[zeroes - ones] = i;
        else
            max_length = max(max_length, i - count_map[zeroes - ones]);
    }
    return max_length;
}
```
The algorithm uses a hashmap `count_map` to store the difference between the counts of 0's and 1's encountered in the array. We iterate through the input binary array `nums`, and for each element, we update the count of 0's and the count of 1's.

If the difference `(zeroes - ones)` is not present in the hashmap, we store it along with its index `i`. If the difference is already present in the hashmap, it means that we have found a subarray where 0's and 1's occur with a balanced frequency. We then update the maximum length of such a subarray if the difference with the stored index is larger than the current max_length.

The algorithm returns the max_length of balanced subarrays after iteration, accounting for the single element deletion, as it inherently checks for subarrays with equal numbers of 1's and 0's.

## A solution in Python

```python
def findMaxLength(nums):
    max_length, zeroes, ones = 0, 0, 0
    count_map = {0: -1}

    for i, num in enumerate(nums):
        if num == 0:
            zeroes += 1
        else:
            ones += 1

        if zeroes - ones not in count_map:
            count_map[zeroes - ones] = i
        else:
            max_length = max(max_length, i - count_map[zeroes - ones])

    return max_length
```
The algorithm uses a hashmap `count_map` to store the difference between the counts of 0's and 1's encountered in the array. We iterate through the input binary array `nums`, and for each element, we update the count of 0's and the count of 1's.

If the difference `(zeroes - ones)` is not present in the hashmap, we store it along with its index `i`. If the difference is already present in the hashmap, it means that we have found a subarray where 0's and 1's occur with a balanced frequency. We then update the maximum length of such a subarray if the difference with the stored index is larger than the current max_length.

The algorithm returns the max_length of balanced subarrays after iteration, accounting for the single element deletion, as it inherently checks for subarrays with equal numbers of 1's and 0's.

## A solution in Javascript

```javascript
function findMaxLength(nums) {
    let max_length = 0, zeroes = 0, ones = 0;
    let count_map = new Map();
    count_map.set(0, -1);

    for(let i = 0; i < nums.length; ++i) {
        if(nums[i] === 0)
            zeroes++;
        else
            ones++;

        if(!count_map.has(zeroes - ones))
            count_map.set(zeroes - ones, i);
        else
            max_length = Math.max(max_length, i - count_map.get(zeroes - ones));
    }
    return max_length;
}
```
The algorithm uses a hashmap `count_map` to store the difference between the counts of 0's and 1's encountered in the array. We iterate through the input binary array `nums`, and for each element, we update the count of 0's and the count of 1's.

If the difference `(zeroes - ones)` is not present in the hashmap, we store it along with its index `i`. If the difference is already present in the hashmap, it means that we have found a subarray where 0's and 1's occur with a balanced frequency. We then update the maximum length of such a subarray if the difference with the stored index is larger than the current max_length.

The algorithm returns the max_length of balanced subarrays after iteration, accounting for the single element deletion, as it inherently checks for subarrays with equal numbers of 1's and 0's.


# Sum of All Odd Length Subarrays

- slug: sum-of-all-odd-length-subarrays
- difficulty: Easy

Given an array of positive integers `arr`, return _the sum of all possible **odd-length subarrays** of_ `arr`.

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

**Example 1:**

**Input:** arr = \[1,4,2,5,3\]
**Output:** 58
**Explanation:** The odd-length subarrays of arr and their sums are:
\[1\] = 1
\[4\] = 4
\[2\] = 2
\[5\] = 5
\[3\] = 3
\[1,4,2\] = 7
\[4,2,5\] = 11
\[2,5,3\] = 10
\[1,4,2,5,3\] = 15
If we add all these together we get 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58

**Example 2:**

**Input:** arr = \[1,2\]
**Output:** 3
**Explanation:** There are only 2 subarrays of odd length, \[1\] and \[2\]. Their sum is 3.

**Example 3:**

**Input:** arr = \[10,11,12\]
**Output:** 66

**Constraints:**

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

**Follow up:**

Could you solve this problem in O(n) time complexity?

## A solution in Java

```java
public int sumOddLengthSubarrays(int[] arr) {
    int sum = 0, n = arr.length;
    for (int i = 0; i < n; i++) {
        int oddSubarrays = ((i + 1) * (n - i) + 1) / 2;
        sum += arr[i] * oddSubarrays;
    }
    return sum;
}
```
First, we loop through the input array with index `i`. For each element `arr[i]`, calculate how many odd-length subarrays it appears in by using the formula `((i + 1) * (n - i) + 1) / 2`, where `n` is the length of the array. This gives us the number of odd-length subarrays that have `arr[i]` in them.

Then, add the product of `arr[i]` and the number of odd-length subarrays it appears in to the total sum. Finally, return the total sum.

This algorithm runs in O(n) time complexity, where n is the length of the input array.

## A solution in C++

```cpp
int sumOddLengthSubarrays(vector<int>& arr) {
    int sum = 0, n = arr.size();
    for (int i = 0; i < n; i++) {
        int oddSubarrays = ((i + 1) * (n - i) + 1) / 2;
        sum += arr[i] * oddSubarrays;
    }
    return sum;
}
```
First, we loop through the input array with index `i`. For each element `arr[i]`, calculate how many odd-length subarrays it appears in by using the formula `((i + 1) * (n - i) + 1) / 2`, where `n` is the length of the array. This gives us the number of odd-length subarrays that have `arr[i]` in them.

Then, add the product of `arr[i]` and the number of odd-length subarrays it appears in to the total sum. Finally, return the total sum.

This algorithm runs in O(n) time complexity, where n is the length of the input array.

## A solution in Python

```python
def sumOddLengthSubarrays(arr):
    sum = 0
    n = len(arr)
    for i in range(n):
        oddSubarrays = ((i + 1) * (n - i) + 1) // 2
        sum += arr[i] * oddSubarrays
    return sum
```
First, we loop through the input array with index `i`. For each element `arr[i]`, calculate how many odd-length subarrays it appears in by using the formula `((i + 1) * (n - i) + 1) / 2`, where `n` is the length of the array. This gives us the number of odd-length subarrays that have `arr[i]` in them.

Then, add the product of `arr[i]` and the number of odd-length subarrays it appears in to the total sum. Finally, return the total sum.

This algorithm runs in O(n) time complexity, where n is the length of the input array.

## A solution in Javascript

```javascript
function sumOddLengthSubarrays(arr) {
    let sum = 0, n = arr.length;
    for (let i = 0; i < n; i++) {
        let oddSubarrays = Math.floor(((i + 1) * (n - i) + 1) / 2);
        sum += arr[i] * oddSubarrays;
    }
    return sum;
}
```
First, we loop through the input array with index `i`. For each element `arr[i]`, calculate how many odd-length subarrays it appears in by using the formula `((i + 1) * (n - i) + 1) / 2`, where `n` is the length of the array. This gives us the number of odd-length subarrays that have `arr[i]` in them.

Then, add the product of `arr[i]` and the number of odd-length subarrays it appears in to the total sum. Finally, return the total sum.

This algorithm runs in O(n) time complexity, where n is the length of the input array.


# Maximum Sum Obtained of Any Permutation

- slug: maximum-sum-obtained-of-any-permutation
- difficulty: Medium

We have an array of integers, `nums`, and an array of `requests` where `requests[i] = [starti, endi]`. The `ith` request asks for the sum of `nums[starti] + nums[starti + 1] + ... + nums[endi - 1] + nums[endi]`. Both `starti` and `endi` are _0-indexed_.

Return _the maximum total sum of all requests **among all permutations** of_ `nums`.

Since the answer may be too large, return it **modulo** `109 + 7`.

**Example 1:**

**Input:** nums = \[1,2,3,4,5\], requests = \[\[1,3\],\[0,1\]\]
**Output:** 19
**Explanation:** One permutation of nums is \[2,1,3,4,5\] with the following result:
requests\[0\] -> nums\[1\] + nums\[2\] + nums\[3\] = 1 + 3 + 4 = 8
requests\[1\] -> nums\[0\] + nums\[1\] = 2 + 1 = 3
Total sum: 8 + 3 = 11.
A permutation with a higher total sum is \[3,5,4,2,1\] with the following result:
requests\[0\] -> nums\[1\] + nums\[2\] + nums\[3\] = 5 + 4 + 2 = 11
requests\[1\] -> nums\[0\] + nums\[1\] = 3 + 5  = 8
Total sum: 11 + 8 = 19, which is the best that you can do.

**Example 2:**

**Input:** nums = \[1,2,3,4,5,6\], requests = \[\[0,1\]\]
**Output:** 11
**Explanation:** A permutation with the max total sum is \[6,5,4,3,2,1\] with request sums \[11\].

**Example 3:**

**Input:** nums = \[1,2,3,4,5,10\], requests = \[\[0,2\],\[1,3\],\[1,1\]\]
**Output:** 47
**Explanation:** A permutation with the max total sum is \[4,10,5,3,2,1\] with request sums \[19,18,10\].

**Constraints:**

*   `n == nums.length`
*   `1 <= n <= 105`
*   `0 <= nums[i] <= 105`
*   `1 <= requests.length <= 105`
*   `requests[i].length == 2`
*   `0 <= starti <= endi < n`

## A solution in Java

```java
import java.util.Arrays;

public int maxSumRangeQuery(int[] nums, int[][] requests) {
    int n = nums.length;
    int[] count = new int[n];
    for (int[] request : requests) {
        count[request[0]]++;
        if (request[1] + 1 < n)
            count[request[1] + 1]--;
    }
    for (int i = 1; i < n; i++) {
        count[i] += count[i - 1];
    }
    Arrays.sort(nums);
    Arrays.sort(count);

    long ans = 0;
    for (int i = 0; i < n; i++) {
        ans = (ans + (long)nums[i] * count[i]) % 1000000007;
    }
    return (int) ans;
}
```
1. Create an empty frequency count array, `count`, of the same size as `nums`.
2. Loop through the `requests` array to update our `count` array: increment the count value on the `start` index and decrement it on the `end + 1` index, if it is less than `n`.
3. Starting from the second index of the `count` array, update each `count` element with the sum of the current element and the previous element, i.e., compute the prefix sum.
4. Sort both the `nums` and `count` arrays in non-decreasing order.
5. Calculate the summation of the product of pairwise elements of two sorted arrays, modulo 1e9+7, and store it in a variable called `ans`.
6. Return the `ans` value.

## A solution in C++

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

const int MOD = 1000000007;

int maxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests) {
    int n = nums.size();
    vector<int> count(n, 0);
    for (auto& request : requests) {
        count[request[0]]++;
        if (request[1] + 1 < n)
            count[request[1] + 1]--;
    }
    for (int i = 1; i < n; i++) {
        count[i] += count[i - 1];
    }
    sort(nums.begin(), nums.end());
    sort(count.begin(), count.end());

    long long ans = 0;
    for (int i = 0; i < n; i++) {
        ans = (ans + (long long)nums[i] * count[i]) % MOD;
    }
    return ans;
}
```
1. Create an empty frequency count array, `count`, of the same size as `nums`.
2. Loop through the `requests` array to update our `count` array: increment the count value on the `start` index and decrement it on the `end + 1` index, if it is less than `n`.
3. Starting from the second index of the `count` array, update each `count` element with the sum of the current element and the previous element, i.e., compute the prefix sum.
4. Sort both the `nums` and `count` arrays in non-decreasing order.
5. Calculate the summation of the product of pairwise elements of two sorted arrays, modulo 1e9+7, and store it in a variable called `ans`.
6. Return the `ans` value.

## A solution in Python

```python
def maxSumRangeQuery(nums, requests):
    n = len(nums)
    count = [0] * n
    for request in requests:
        count[request[0]] += 1
        if request[1] + 1 < n:
            count[request[1] + 1] -= 1
    for i in range(1, n):
        count[i] += count[i - 1]

    nums.sort()
    count.sort()

    ans = 0
    for i in range(n):
        ans = (ans + nums[i] * count[i]) % 1000000007
    return ans
```
1. Create an empty frequency count array, `count`, of the same size as `nums`.
2. Loop through the `requests` array to update our `count` array: increment the count value on the `start` index and decrement it on the `end + 1` index, if it is less than `n`.
3. Starting from the second index of the `count` array, update each `count` element with the sum of the current element and the previous element, i.e., compute the prefix sum.
4. Sort both the `nums` and `count` arrays in non-decreasing order.
5. Calculate the summation of the product of pairwise elements of two sorted arrays, modulo 1e9+7, and store it in a variable called `ans`.
6. Return the `ans` value.

## A solution in Javascript

```javascript
function maxSumRangeQuery(nums, requests) {
    const n = nums.length;
    const count = new Array(n).fill(0);
    const MOD = 1000000007;

    for (const request of requests) {
        count[request[0]]++;
        if (request[1] + 1 < n) {
            count[request[1] + 1]--;
        }
    }
    for (let i = 1; i < n; i++) {
        count[i] += count[i - 1];
    }

    nums.sort((a, b) => a - b);
    count.sort((a, b) => a - b);

    let ans = 0;
    for (let i = 0; i < n; i++) {
        ans = (ans + nums[i] * count[i]) % MOD;
    }

    return ans;
}
```
1. Create an empty frequency count array, `count`, of the same size as `nums`.
2. Loop through the `requests` array to update our `count` array: increment the count value on the `start` index and decrement it on the `end + 1` index, if it is less than `n`.
3. Starting from the second index of the `count` array, update each `count` element with the sum of the current element and the previous element, i.e., compute the prefix sum.
4. Sort both the `nums` and `count` arrays in non-decreasing order.
5. Calculate the summation of the product of pairwise elements of two sorted arrays, modulo 1e9+7, and store it in a variable called `ans`.
6. Return the `ans` value.


# Make Sum Divisible by P

- slug: make-sum-divisible-by-p
- difficulty: Medium

Given an array of positive integers `nums`, remove the **smallest** subarray (possibly **empty**) such that the **sum** of the remaining elements is divisible by `p`. It is **not** allowed to remove the whole array.

Return _the length of the smallest subarray that you need to remove, or_ `-1` _if it's impossible_.

A **subarray** is defined as a contiguous block of elements in the array.

**Example 1:**

**Input:** nums = \[3,1,4,2\], p = 6
**Output:** 1
**Explanation:** The sum of the elements in nums is 10, which is not divisible by 6. We can remove the subarray \[4\], and the sum of the remaining elements is 6, which is divisible by 6.

**Example 2:**

**Input:** nums = \[6,3,5,2\], p = 9
**Output:** 2
**Explanation:** We cannot remove a single element to get a sum divisible by 9. The best way is to remove the subarray \[5,2\], leaving us with \[6,3\] with sum 9.

**Example 3:**

**Input:** nums = \[1,2,3\], p = 3
**Output:** 0
**Explanation:** Here the sum is 6. which is already divisible by 3. Thus we do not need to remove anything.

**Constraints:**

*   `1 <= nums.length <= 105`
*   `1 <= nums[i] <= 109`
*   `1 <= p <= 109`

## A solution in Java

```java
import java.util.HashMap;

public int minSubarray(int[] nums, int p) {
    int n = nums.length, res = n, need = 0, cur = 0;
    for (int num : nums)
        need = (need + num) % p;
    if (need == 0) return 0;
    HashMap<Integer, Integer> last_seen = new HashMap<>();
    last_seen.put(0, -1);
    for (int i = 0; i < n; i++) {
        cur = (cur + nums[i]) % p;
        last_seen.put(cur, i);
        res = Math.min(res, i - last_seen.getOrDefault((cur - need + p) % p, -n));
    }
    return res < n ? res : -1;
}
```
1. First, find the remainder `need` when the sum of the array is divided by `p`.
2. If `need` is 0, the sum is already divisible by `p`, so return 0.
3. Otherwise, create a hashmap `last_seen` to store the last seen index of each remainder when the sum from the start of the array is divided by `p`. Initialize with 0 mapped to `-1`.
4. Iterate through the array, updating the current remainder `cur`.
5. For each remainder, update the last seen index in `last_seen` hashmap and calculate the minimum length subarray to remove by finding the difference between the current index and the last seen index of `cur-need+p` modulo `p`. Update the result if the calculated length is smaller.
6. If the final result is smaller than the array length, return the result, otherwise, return -1.

## A solution in C++

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

int minSubarray(vector<int>& nums, int p) {
    int n = nums.size(), res = n, need = 0, cur = 0;
    for (int num : nums)
        need = (need + num) % p;
    if (need == 0) return 0;
    unordered_map<int, int> last_seen;
    last_seen[0] = -1;
    for (int i = 0; i < n; i++) {
        cur = (cur + nums[i]) % p;
        last_seen[cur] = i;
        res = min(res, i - last_seen[(cur - need + p) % p]);
    }
    return res < n ? res : -1;
}
```
1. First, find the remainder `need` when the sum of the array is divided by `p`.
2. If `need` is 0, the sum is already divisible by `p`, so return 0.
3. Otherwise, create a hashmap `last_seen` to store the last seen index of each remainder when the sum from the start of the array is divided by `p`. Initialize with 0 mapped to `-1`.
4. Iterate through the array, updating the current remainder `cur`.
5. For each remainder, update the last seen index in `last_seen` hashmap and calculate the minimum length subarray to remove by finding the difference between the current index and the last seen index of `cur-need+p` modulo `p`. Update the result if the calculated length is smaller.
6. If the final result is smaller than the array length, return the result, otherwise, return -1.

## A solution in Python

```python
def minSubarray(nums, p):
    n, res, need, cur = len(nums), len(nums), 0, 0
    for num in nums:
        need = (need + num) % p
    if need == 0:
        return 0
    last_seen = {0: -1}
    for i, num in enumerate(nums):
        cur = (cur + num) % p
        last_seen[cur] = i
        res = min(res, i - last_seen.get((cur - need + p) % p, -n))
    return res if res < n else -1
```
1. First, find the remainder `need` when the sum of the array is divided by `p`.
2. If `need` is 0, the sum is already divisible by `p`, so return 0.
3. Otherwise, create a hashmap `last_seen` to store the last seen index of each remainder when the sum from the start of the array is divided by `p`. Initialize with 0 mapped to `-1`.
4. Iterate through the array, updating the current remainder `cur`.
5. For each remainder, update the last seen index in `last_seen` hashmap and calculate the minimum length subarray to remove by finding the difference between the current index and the last seen index of `cur-need+p` modulo `p`. Update the result if the calculated length is smaller.
6. If the final result is smaller than the array length, return the result, otherwise, return -1.

## A solution in Javascript

```javascript
function minSubarray(nums, p) {
    let n = nums.length, res = n, need = 0, cur = 0;
    for (let num of nums)
        need = (need + num) % p;
    if (need === 0) return 0;
    let last_seen = new Map();
    last_seen.set(0, -1);
    for (let i = 0; i < n; i++) {
        cur = (cur + nums[i]) % p;
        last_seen.set(cur, i);
        res = Math.min(res, i - (last_seen.get((cur - need + p) % p) || -n));
    }
    return res < n ? res : -1;
}
```
1. First, find the remainder `need` when the sum of the array is divided by `p`.
2. If `need` is 0, the sum is already divisible by `p`, so return 0.
3. Otherwise, create a hashmap `last_seen` to store the last seen index of each remainder when the sum from the start of the array is divided by `p`. Initialize with 0 mapped to `-1`.
4. Iterate through the array, updating the current remainder `cur`.
5. For each remainder, update the last seen index in `last_seen` hashmap and calculate the minimum length subarray to remove by finding the difference between the current index and the last seen index of `cur-need+p` modulo `p`. Update the result if the calculated length is smaller.
6. If the final result is smaller than the array length, return the result, otherwise, return -1.


# Strange Printer II

- slug: strange-printer-ii
- difficulty: Hard

There is a strange printer with the following two special requirements:

*   On each turn, the printer will print a solid rectangular pattern of a single color on the grid. This will cover up the existing colors in the rectangle.
*   Once the printer has used a color for the above operation, **the same color cannot be used again**.

You are given a `m x n` matrix `targetGrid`, where `targetGrid[row][col]` is the color in the position `(row, col)` of the grid.

Return `true` _if it is possible to print the matrix_ `targetGrid`_,_ _otherwise, return_ `false`.

**Example 1:**

**Input:** targetGrid = \[\[1,1,1,1\],\[1,2,2,1\],\[1,2,2,1\],\[1,1,1,1\]\]
**Output:** true

**Example 2:**

**Input:** targetGrid = \[\[1,1,1,1\],\[1,1,3,3\],\[1,1,3,4\],\[5,5,1,4\]\]
**Output:** true

**Example 3:**

**Input:** targetGrid = \[\[1,2,1\],\[2,1,2\],\[1,2,1\]\]
**Output:** false
**Explanation:** It is impossible to form targetGrid because it is not allowed to print the same color in different turns.

**Constraints:**

*   `m == targetGrid.length`
*   `n == targetGrid[i].length`
*   `1 <= m, n <= 60`
*   `1 <= targetGrid[row][col] <= 60`

## A solution in Java

```java
public boolean isPrintable(int[][] targetGrid) {
    int m = targetGrid.length, n = targetGrid[0].length;
    Map<Integer, int[]> colorBounds = new HashMap<>();
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            int color = targetGrid[i][j];
            colorBounds.putIfAbsent(color, new int[] {i, j, i, j});
            colorBounds.get(color)[0] = Math.min(colorBounds.get(color)[0], i);
            colorBounds.get(color)[1] = Math.min(colorBounds.get(color)[1], j);
            colorBounds.get(color)[2] = Math.max(colorBounds.get(color)[2], i);
            colorBounds.get(color)[3] = Math.max(colorBounds.get(color)[3], j);
        }
    }

    Set<Integer> remainingColors = new HashSet<>(colorBounds.keySet());
    while (!remainingColors.isEmpty()) {
        boolean progress = false;
        for (Iterator<Integer> it = remainingColors.iterator(); it.hasNext();) {
            int color = it.next();
            int[] bounds = colorBounds.get(color);
            boolean contained = true;
            for (int i = bounds[0]; i <= bounds[2] && contained; ++i) {
                for (int j = bounds[1]; j <= bounds[3]; ++j) {
                    if (targetGrid[i][j] != color && targetGrid[i][j] != -1) {
                        contained = false;
                        break;
                    }
                }
            }
            if (contained) {
                for (int i = bounds[0]; i <= bounds[2]; ++i) {
                    for (int j = bounds[1]; j <= bounds[3]; ++j) {
                        targetGrid[i][j] = -1;
                    }
                }
                it.remove();
                progress = true;
            }
        }
        if (!progress) return false;
    }
    return true;
}
```
The algorithm keeps track of the bounding rectangles of each color and tries to print them in any order.

For each color, the bounding rectangle is calculated by searching for the minimum/maximum row/col coordinates of the same color.

To check if a rectangle can be printed, we examine each cell in the rectangle, making sure that either the cell is already covered by the current color or the cell is transparent and has not been covered by any other color. If a rectangle can be printed, we make it transparent (set its value in targetGrid to -1) and remove the color from the remaining colors set.

If a progress is made in the current iteration (removing at least one color), we continue with the next iteration. This loop will continue until there are no remaining colors or no further progress is made. If there are still remaining colors in the set when progress is not made anymore, it is impossible to print the target grid, and the function returns False. Otherwise, it returns True.

The time complexity is O(N^4) since we iterate over all colors and 2D coordinates. The space complexity is O(N^2) because of the memory used in targetGrid and colorBounds.

## A solution in C++

```cpp
bool isPrintable(vector<vector<int>>& targetGrid) {
    unordered_map<int, vector<int>> color_bounds;
    int m = targetGrid.size(), n = targetGrid[0].size();
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            int color = targetGrid[i][j];
            if (!color_bounds.count(color)) color_bounds[color] = {i, j, i, j};
            else {
                color_bounds[color][0] = min(color_bounds[color][0], i);
                color_bounds[color][1] = min(color_bounds[color][1], j);
                color_bounds[color][2] = max(color_bounds[color][2], i);
                color_bounds[color][3] = max(color_bounds[color][3], j);
            }
        }
    }

    set<int> remaining_colors;
    for (const auto& p : color_bounds) {
        remaining_colors.insert(p.first);
    }
    while (!remaining_colors.empty()) {
        bool progress = false;
        for (auto it = remaining_colors.begin(); it != remaining_colors.end();) {
            int color = *it;
            const auto& bounds = color_bounds[color];
            bool contained = true;
            for (int i = bounds[0]; i <= bounds[2] && contained; ++i) {
                for (int j = bounds[1]; j <= bounds[3]; ++j) {
                    if (targetGrid[i][j] != color && targetGrid[i][j] != -1) {
                        contained = false;
                        break;
                    }
                }
            }
            if (contained) {
                for (int i = bounds[0]; i <= bounds[2]; ++i) {
                    for (int j = bounds[1]; j <= bounds[3]; ++j) {
                        targetGrid[i][j] = -1;
                    }
                }
                it = remaining_colors.erase(it);
                progress = true;
            } else {
                ++it;
            }
        }
        if (!progress) return false;
    }
    return true;
}
```
The algorithm keeps track of the bounding rectangles of each color and tries to print them in any order.

For each color, the bounding rectangle is calculated by searching for the minimum/maximum row/col coordinates of the same color.

To check if a rectangle can be printed, we examine each cell in the rectangle, making sure that either the cell is already covered by the current color or the cell is transparent and has not been covered by any other color. If a rectangle can be printed, we make it transparent (set its value in targetGrid to -1) and remove the color from the remaining colors set.

If a progress is made in the current iteration (removing at least one color), we continue with the next iteration. This loop will continue until there are no remaining colors or no further progress is made. If there are still remaining colors in the set when progress is not made anymore, it is impossible to print the target grid, and the function returns False. Otherwise, it returns True.

The time complexity is O(N^4) since we iterate over all colors and 2D coordinates. The space complexity is O(N^2) because of the memory used in targetGrid and colorBounds.

## A solution in Python

```python
def isPrintable(self, targetGrid: List[List[int]]) -> bool:
    color_bounds = {}
    m, n = len(targetGrid), len(targetGrid[0])

    for i in range(m):
        for j in range(n):
            color = targetGrid[i][j]
            if color not in color_bounds:
                color_bounds[color] = [i, j, i, j]
            else:
                color_bounds[color][0] = min(color_bounds[color][0], i)
                color_bounds[color][1] = min(color_bounds[color][1], j)
                color_bounds[color][2] = max(color_bounds[color][2], i)
                color_bounds[color][3] = max(color_bounds[color][3], j)

    remaining_colors = set(color_bounds.keys())
    while remaining_colors:
        progress = False
        to_remove = set()
        for color in remaining_colors:
            bounds = color_bounds[color]
            contained = all(targetGrid[i][j] == color or targetGrid[i][j] == -1
                        for i in range(bounds[0], bounds[2] + 1)
                        for j in range(bounds[1], bounds[3] + 1))
            if contained:
                for i in range(bounds[0], bounds[2] + 1):
                    for j in range(bounds[1], bounds[3] + 1):
                        targetGrid[i][j] = -1
                to_remove.add(color)
                progress = True

        remaining_colors -= to_remove
        if not progress:
            return False

    return True
```
The algorithm keeps track of the bounding rectangles of each color and tries to print them in any order.

For each color, the bounding rectangle is calculated by searching for the minimum/maximum row/col coordinates of the same color.

To check if a rectangle can be printed, we examine each cell in the rectangle, making sure that either the cell is already covered by the current color or the cell is transparent and has not been covered by any other color. If a rectangle can be printed, we make it transparent (set its value in targetGrid to -1) and remove the color from the remaining colors set.

If a progress is made in the current iteration (removing at least one color), we continue with the next iteration. This loop will continue until there are no remaining colors or no further progress is made. If there are still remaining colors in the set when progress is not made anymore, it is impossible to print the target grid, and the function returns False. Otherwise, it returns True.

The time complexity is O(N^4) since we iterate over all colors and 2D coordinates. The space complexity is O(N^2) because of the memory used in targetGrid and colorBounds.

## A solution in Javascript

```javascript
const isPrintable = (targetGrid) => {
    const m = targetGrid.length, n = targetGrid[0].length;
    const colorBounds = new Map();
    for (let i = 0; i < m; ++i) {
        for (let j = 0; j < n; ++j) {
            const color = targetGrid[i][j];
            if (!colorBounds.has(color)) colorBounds.set(color, [i, j, i, j]);
            else {
                colorBounds.get(color)[0] = Math.min(colorBounds.get(color)[0], i);
                colorBounds.get(color)[1] = Math.min(colorBounds.get(color)[1], j);
                colorBounds.get(color)[2] = Math.max(colorBounds.get(color)[2], i);
                colorBounds.get(color)[3] = Math.max(colorBounds.get(color)[3], j);
            }
        }
    }

    const remainingColors = new Set(colorBounds.keys());
    while (remainingColors.size) {
        let progress = false;
        for (const color of Array.from(remainingColors)) {
            const bounds = colorBounds.get(color);
            let contained = true;
            for (let i = bounds[0]; i <= bounds[2] && contained; ++i) {
                for (let j = bounds[1]; j <= bounds[3]; ++j) {
                    if (targetGrid[i][j] !== color && targetGrid[i][j] !== -1) {
                        contained = false;
                        break;
                    }
                }
            }
            if (contained) {
                for (let i = bounds[0]; i <= bounds[2]; ++i) {
                    for (let j = bounds[1]; j <= bounds[3]; ++j) {
                        targetGrid[i][j] = -1;
                    }
                }
                remainingColors.delete(color);
                progress = true;
            }
        }
        if (!progress) return false;
    }
    return true;
};
```
The algorithm keeps track of the bounding rectangles of each color and tries to print them in any order.

For each color, the bounding rectangle is calculated by searching for the minimum/maximum row/col coordinates of the same color.

To check if a rectangle can be printed, we examine each cell in the rectangle, making sure that either the cell is already covered by the current color or the cell is transparent and has not been covered by any other color. If a rectangle can be printed, we make it transparent (set its value in targetGrid to -1) and remove the color from the remaining colors set.

If a progress is made in the current iteration (removing at least one color), we continue with the next iteration. This loop will continue until there are no remaining colors or no further progress is made. If there are still remaining colors in the set when progress is not made anymore, it is impossible to print the target grid, and the function returns False. Otherwise, it returns True.

The time complexity is O(N^4) since we iterate over all colors and 2D coordinates. The space complexity is O(N^2) because of the memory used in targetGrid and colorBounds.


# Rearrange Spaces Between Words

- slug: rearrange-spaces-between-words
- difficulty: Easy

You are given a string `text` of words that are placed among some number of spaces. Each word consists of one or more lowercase English letters and are separated by at least one space. It's guaranteed that `text` **contains at least one word**.

Rearrange the spaces so that there is an **equal** number of spaces between every pair of adjacent words and that number is **maximized**. If you cannot redistribute all the spaces equally, place the **extra spaces at the end**, meaning the returned string should be the same length as `text`.

Return _the string after rearranging the spaces_.

**Example 1:**

**Input:** text =  "  this   is  a sentence  "
**Output:**  "this   is   a   sentence "
**Explanation:** There are a total of 9 spaces and 4 words. We can evenly divide the 9 spaces between the words: 9 / (4-1) = 3 spaces.

**Example 2:**

**Input:** text =  " practice   makes   perfect "
**Output:**  "practice   makes   perfect  "
**Explanation:** There are a total of 7 spaces and 3 words. 7 / (3-1) = 3 spaces plus 1 extra space. We place this extra space at the end of the string.

**Constraints:**

*   `1 <= text.length <= 100`
*   `text` consists of lowercase English letters and `' '`.
*   `text` contains at least one word.

## A solution in Java

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

public String reorderSpaces(String text) {
    int spaces = 0, words = 0;

    for (char c : text.toCharArray()) {
        if (c == ' ') spaces++;
    }

    String[] splitText = text.trim().split("\\s+");
    List<String> wordList = new ArrayList<>();
    for (String word : splitText) {
        wordList.add(word);
        words++;
    }

    int spacesBetweenWords = words == 1 ? 0 : spaces / (words - 1);
    int extraSpaces = words == 1 ? spaces : spaces % (words - 1);

    StringBuilder result = new StringBuilder();

    for (int i = 0; i < words; i++) {
        result.append(wordList.get(i));
        if (i != words - 1) {
            result.append(" ".repeat(spacesBetweenWords));
        } else {
            result.append(" ".repeat(extraSpaces));
        }
    }

    return result.toString();
}
```
To solve this problem, first we need to count the number of spaces and words in the input `text`. We iterate through the `text` and count the spaces. Then, we split the `text` into words, and count the number of words.

Next, we need to calculate the number of spaces between words and the extra spaces that will be placed at the end. If there is only one word, then all spaces will be used as extra spaces. Otherwise, we divide the total number of spaces by the number of words minus 1 (to get the spaces between words), and calculate the remainder (i.e., the extra spaces).

After that, we construct the result by joining the words with the calculated space between them and then adding the extra spaces at the end of the last word.

In all four implementations, the core logic and step-by-step procedure are the same, only the syntax and library functions vary according to the language being used.

## A solution in C++

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

std::string reorderSpaces(std::string text) {
    int spaces = 0, words = 0;

    for (char c : text) {
        if (c == ' ') spaces++;
    }

    std::istringstream iss(text);
    std::vector<std::string> wordList;
    std::string word;

    while (iss >> word) {
        wordList.push_back(word);
        words++;
    }

    int spacesBetweenWords = words == 1 ? 0 : spaces / (words - 1);
    int extraSpaces = words == 1 ? spaces : spaces % (words - 1);

    std::string result;

    for (int i = 0; i < words; i++) {
        result += wordList[i];
        if (i != words - 1) {
            result.append(spacesBetweenWords, ' ');
        } else {
            result.append(extraSpaces, ' ');
        }
    }

    return result;
}
```
To solve this problem, first we need to count the number of spaces and words in the input `text`. We iterate through the `text` and count the spaces. Then, we split the `text` into words, and count the number of words.

Next, we need to calculate the number of spaces between words and the extra spaces that will be placed at the end. If there is only one word, then all spaces will be used as extra spaces. Otherwise, we divide the total number of spaces by the number of words minus 1 (to get the spaces between words), and calculate the remainder (i.e., the extra spaces).

After that, we construct the result by joining the words with the calculated space between them and then adding the extra spaces at the end of the last word.

In all four implementations, the core logic and step-by-step procedure are the same, only the syntax and library functions vary according to the language being used.

## A solution in Python

```python
def reorderSpaces(text):
    spaces = text.count(' ')
    words = text.split()
    num_words = len(words)

    if num_words == 1:
        spaces_between_words = 0
    else:
        spaces_between_words = spaces // (num_words - 1)

    extra_spaces = spaces - spaces_between_words * (num_words - 1)

    return (' ' * spaces_between_words).join(words) + ' ' * extra_spaces
```
To solve this problem, first we need to count the number of spaces and words in the input `text`. We iterate through the `text` and count the spaces. Then, we split the `text` into words, and count the number of words.

Next, we need to calculate the number of spaces between words and the extra spaces that will be placed at the end. If there is only one word, then all spaces will be used as extra spaces. Otherwise, we divide the total number of spaces by the number of words minus 1 (to get the spaces between words), and calculate the remainder (i.e., the extra spaces).

After that, we construct the result by joining the words with the calculated space between them and then adding the extra spaces at the end of the last word.

In all four implementations, the core logic and step-by-step procedure are the same, only the syntax and library functions vary according to the language being used.

## A solution in Javascript

```javascript
function reorderSpaces(text) {
    const spaces = text.split(' ').length - 1;
    const words = text.trim().split(/\s+/);
    const numWords = words.length;

    const spacesBetweenWords = numWords === 1 ? 0 : Math.floor(spaces / (numWords - 1));
    const extraSpaces = spaces - spacesBetweenWords * (numWords - 1);

    return words.join(' '.repeat(spacesBetweenWords)) + ' '.repeat(extraSpaces);
}
```
To solve this problem, first we need to count the number of spaces and words in the input `text`. We iterate through the `text` and count the spaces. Then, we split the `text` into words, and count the number of words.

Next, we need to calculate the number of spaces between words and the extra spaces that will be placed at the end. If there is only one word, then all spaces will be used as extra spaces. Otherwise, we divide the total number of spaces by the number of words minus 1 (to get the spaces between words), and calculate the remainder (i.e., the extra spaces).

After that, we construct the result by joining the words with the calculated space between them and then adding the extra spaces at the end of the last word.

In all four implementations, the core logic and step-by-step procedure are the same, only the syntax and library functions vary according to the language being used.