# Maximum Value of a String in an Array

- slug: maximum-value-of-a-string-in-an-array
- difficulty: Easy

The **value** of an alphanumeric string can be defined as:

*   The **numeric** representation of the string in base `10`, if it comprises of digits **only**.
*   The **length** of the string, otherwise.

Given an array `strs` of alphanumeric strings, return _the **maximum value** of any string in_ `strs`.

**Example 1:**

**Input:** strs = \[ "alic3 ", "bob ", "3 ", "4 ", "00000 "\]
**Output:** 5
**Explanation:**
-  "alic3 " consists of both letters and digits, so its value is its length, i.e. 5.
-  "bob " consists only of letters, so its value is also its length, i.e. 3.
-  "3 " consists only of digits, so its value is its numeric equivalent, i.e. 3.
-  "4 " also consists only of digits, so its value is 4.
-  "00000 " consists only of digits, so its value is 0.
Hence, the maximum value is 5, of  "alic3 ".

**Example 2:**

**Input:** strs = \[ "1 ", "01 ", "001 ", "0001 "\]
**Output:** 1
**Explanation:**
Each string in the array has value 1. Hence, we return 1.

**Constraints:**

*   `1 <= strs.length <= 100`
*   `1 <= strs[i].length <= 9`
*   `strs[i]` consists of only lowercase English letters and digits.

## A solution in Java

```java
import java.util.List;

public int maxValue(List<String> strs) {
    int maxValue = 0;
    for (String str : strs) {
        int value;
        if (str.chars().allMatch(Character::isDigit)) {
            value = Integer.parseInt(str);
        } else {
            value = str.length();
        }
        maxValue = Math.max(maxValue, value);
    }
    return maxValue;
}
```
We iterate through the input array `strs`. For each string, we check whether it contains only digits or not. If it contains only digits, we find its numeric value and store it in a variable `value`. If it contains other characters (letters), we store its length in the `value` variable. In each iteration, we update the `max_value` variable with the maximum of the current `max_value` and the `value` found.

Finally, we return the `max_value`.

## A solution in C++

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

int maxValue(std::vector<std::string>& strs) {
    int max_value = 0;
    for (const std::string& str : strs) {
        int value;
        if (str.find_first_not_of("0123456789") == std::string::npos) {
            value = std::stoi(str);
        } else {
            value = static_cast<int>(str.length());
        }
        max_value = std::max(max_value, value);
    }
    return max_value;
}
```
We iterate through the input array `strs`. For each string, we check whether it contains only digits or not. If it contains only digits, we find its numeric value and store it in a variable `value`. If it contains other characters (letters), we store its length in the `value` variable. In each iteration, we update the `max_value` variable with the maximum of the current `max_value` and the `value` found.

Finally, we return the `max_value`.

## A solution in Python

```python
def maxValue(strs) -> int:
    max_value = 0
    for str in strs:
        if str.isdigit():
            value = int(str)
        else:
            value = len(str)
        max_value = max(max_value, value)
    return max_value
```
We iterate through the input array `strs`. For each string, we check whether it contains only digits or not. If it contains only digits, we find its numeric value and store it in a variable `value`. If it contains other characters (letters), we store its length in the `value` variable. In each iteration, we update the `max_value` variable with the maximum of the current `max_value` and the `value` found.

Finally, we return the `max_value`.

## A solution in Javascript

```javascript
function maxValue(strs) {
    let maxValue = 0;
    for (const str of strs) {
        let value;
        if (/^\d+$/.test(str)) {
            value = parseInt(str, 10);
        } else {
            value = str.length;
        }
        maxValue = Math.max(maxValue, value);
    }
    return maxValue;
}
```
We iterate through the input array `strs`. For each string, we check whether it contains only digits or not. If it contains only digits, we find its numeric value and store it in a variable `value`. If it contains other characters (letters), we store its length in the `value` variable. In each iteration, we update the `max_value` variable with the maximum of the current `max_value` and the `value` found.

Finally, we return the `max_value`.


# Maximum Star Sum of a Graph

- slug: maximum-star-sum-of-a-graph
- difficulty: Medium

There is an undirected graph consisting of `n` nodes numbered from `0` to `n - 1`. You are given a **0-indexed** integer array `vals` of length `n` where `vals[i]` denotes the value of the `ith` node.

You are also given a 2D integer array `edges` where `edges[i] = [ai, bi]` denotes that there exists an **undirected** edge connecting nodes `ai` and `bi.`

A **star graph** is a subgraph of the given graph having a center node containing `0` or more neighbors. In other words, it is a subset of edges of the given graph such that there exists a common node for all edges.

The image below shows star graphs with `3` and `4` neighbors respectively, centered at the blue node.

The **star sum** is the sum of the values of all the nodes present in the star graph.

Given an integer `k`, return _the **maximum star sum** of a star graph containing **at most**_ `k` _edges._

**Example 1:**

**Input:** vals = \[1,2,3,4,10,-10,-20\], edges = \[\[0,1\],\[1,2\],\[1,3\],\[3,4\],\[3,5\],\[3,6\]\], k = 2
**Output:** 16
**Explanation:** The above diagram represents the input graph.
The star graph with the maximum star sum is denoted by blue. It is centered at 3 and includes its neighbors 1 and 4.
It can be shown it is not possible to get a star graph with a sum greater than 16.

**Example 2:**

**Input:** vals = \[-5\], edges = \[\], k = 0
**Output:** -5
**Explanation:** There is only one possible star graph, which is node 0 itself.
Hence, we return -5.

**Constraints:**

*   `n == vals.length`
*   `1 <= n <= 105`
*   `-104 <= vals[i] <= 104`
*   `0 <= edges.length <= min(n * (n - 1) / 2``, 105)`
*   `edges[i].length == 2`
*   `0 <= ai, bi <= n - 1`
*   `ai != bi`
*   `0 <= k <= n - 1`

## A solution in Java

```java
import java.util.*;

public int maxStarSum(int[] vals, int[][] edges, int k) {
    List<Integer>[] adj = new ArrayList[vals.length];
    for (int i = 0; i < vals.length; i++) {
        adj[i] = new ArrayList<Integer>();
    }

    for (int[] edge : edges) {
        adj[edge[0]].add(vals[edge[1]]);
        adj[edge[1]].add(vals[edge[0]]);
    }

    int ans = Integer.MIN_VALUE;
    for (int i = 0; i < vals.length; i++) {
        Collections.sort(adj[i], Collections.reverseOrder());
        int sum = vals[i];
        for (int j = 0; j < k && j < adj[i].size(); j++) {
            sum += adj[i].get(j);
        }
        ans = Math.max(ans, sum);
    }

    return ans;
}
```
The basic idea of the algorithm is to find the center node and its neighbors that maximize the star sum with the given constraints. For every node, we calculate the sum of its neighbors' values sorted in decreasing order, up to `k` neighbors. We keep track of the maximum sum found for any node so far.

1. Create an adjacency list `adj` to store the values of neighbors of each node.

2. Iterate through the `edges` array and populate the adjacency list `adj` such that `adj[a]` contains the values of the neighbors of the node `a`.

3. For each node `i`, we sort the values of its neighbors in decreasing order to process the maximum values first.

4. Initiate the maximum sum variable `ans` as the minimum value possible.

5. For each node `i`, calculate the sum `sum` of its value and the sum of `k` maximum neighbors' values (if any). Update the `ans` variable to the maximum of the current sum and the previously stored maximum sum.

6. Return the maximum star sum, `ans`.

## A solution in C++

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

int maxStarSum(const vector<int>& vals, const vector<vector<int>>& edges, int k) {
    vector<int> adj[100000];
    int ans = -1e9;

    for (const vector<int>& edge : edges) {
        adj[edge[0]].push_back(vals[edge[1]]);
        adj[edge[1]].push_back(vals[edge[0]]);
    }

    for (int i = 0; i < vals.size(); i++) {
        sort(adj[i].rbegin(), adj[i].rend());
        int sum = vals[i];
        for (int j = 0; j < k && j < adj[i].size(); j++) {
            sum += adj[i][j];
        }
        ans = max(ans, sum);
    }

    return ans;
}
```
The basic idea of the algorithm is to find the center node and its neighbors that maximize the star sum with the given constraints. For every node, we calculate the sum of its neighbors' values sorted in decreasing order, up to `k` neighbors. We keep track of the maximum sum found for any node so far.

1. Create an adjacency list `adj` to store the values of neighbors of each node.

2. Iterate through the `edges` array and populate the adjacency list `adj` such that `adj[a]` contains the values of the neighbors of the node `a`.

3. For each node `i`, we sort the values of its neighbors in decreasing order to process the maximum values first.

4. Initiate the maximum sum variable `ans` as the minimum value possible.

5. For each node `i`, calculate the sum `sum` of its value and the sum of `k` maximum neighbors' values (if any). Update the `ans` variable to the maximum of the current sum and the previously stored maximum sum.

6. Return the maximum star sum, `ans`.

## A solution in Python

```python
def max_star_sum(vals, edges, k):
    adj = [[] for _ in range(len(vals))]

    for edge in edges:
        adj[edge[0]].append(vals[edge[1]])
        adj[edge[1]].append(vals[edge[0]])

    ans = float("-inf")
    for i in range(len(vals)):
        adj[i].sort(reverse=True)
        ans = max(ans, vals[i] + sum(adj[i][:k]))

    return ans
```
The basic idea of the algorithm is to find the center node and its neighbors that maximize the star sum with the given constraints. For every node, we calculate the sum of its neighbors' values sorted in decreasing order, up to `k` neighbors. We keep track of the maximum sum found for any node so far.

1. Create an adjacency list `adj` to store the values of neighbors of each node.

2. Iterate through the `edges` array and populate the adjacency list `adj` such that `adj[a]` contains the values of the neighbors of the node `a`.

3. For each node `i`, we sort the values of its neighbors in decreasing order to process the maximum values first.

4. Initiate the maximum sum variable `ans` as the minimum value possible.

5. For each node `i`, calculate the sum `sum` of its value and the sum of `k` maximum neighbors' values (if any). Update the `ans` variable to the maximum of the current sum and the previously stored maximum sum.

6. Return the maximum star sum, `ans`.

## A solution in Javascript

```javascript
function maxStarSum(vals, edges, k) {
    const adj = Array.from({ length: vals.length }, () => []);

    for (const [a, b] of edges) {
        adj[a].push(vals[b]);
        adj[b].push(vals[a]);
    }

    let ans = -Infinity;
    for (let i = 0; i < vals.length; i++) {
        adj[i].sort((a, b) => b - a);
        const sum = vals[i] + adj[i].slice(0, k).reduce((a, b) => a + b, 0);
        ans = Math.max(ans, sum);
    }

    return ans;
}
```
The basic idea of the algorithm is to find the center node and its neighbors that maximize the star sum with the given constraints. For every node, we calculate the sum of its neighbors' values sorted in decreasing order, up to `k` neighbors. We keep track of the maximum sum found for any node so far.

1. Create an adjacency list `adj` to store the values of neighbors of each node.

2. Iterate through the `edges` array and populate the adjacency list `adj` such that `adj[a]` contains the values of the neighbors of the node `a`.

3. For each node `i`, we sort the values of its neighbors in decreasing order to process the maximum values first.

4. Initiate the maximum sum variable `ans` as the minimum value possible.

5. For each node `i`, calculate the sum `sum` of its value and the sum of `k` maximum neighbors' values (if any). Update the `ans` variable to the maximum of the current sum and the previously stored maximum sum.

6. Return the maximum star sum, `ans`.


# Frog Jump II

- slug: frog-jump-ii
- difficulty: Medium

You are given a **0-indexed** integer array `stones` sorted in **strictly increasing order** representing the positions of stones in a river.

A frog, initially on the first stone, wants to travel to the last stone and then return to the first stone. However, it can jump to any stone **at most once**.

The **length** of a jump is the absolute difference between the position of the stone the frog is currently on and the position of the stone to which the frog jumps.

*   More formally, if the frog is at `stones[i]` and is jumping to `stones[j]`, the length of the jump is `|stones[i] - stones[j]|`.

The **cost** of a path is the **maximum length of a jump** among all jumps in the path.

Return _the **minimum** cost of a path for the frog_.

**Example 1:**

**Input:** stones = \[0,2,5,6,7\]
**Output:** 5
**Explanation:** The above figure represents one of the optimal paths the frog can take.
The cost of this path is 5, which is the maximum length of a jump.
Since it is not possible to achieve a cost of less than 5, we return it.

**Example 2:**

**Input:** stones = \[0,3,9\]
**Output:** 9
**Explanation:**
The frog can jump directly to the last stone and come back to the first stone.
In this case, the length of each jump will be 9. The cost for the path will be max(9, 9) = 9.
It can be shown that this is the minimum achievable cost.

**Constraints:**

*   `2 <= stones.length <= 105`
*   `0 <= stones[i] <= 109`
*   `stones[0] == 0`
*   `stones` is sorted in a strictly increasing order.

## A solution in Java

```java
public int minimumPathCost(int[] stones) {
    int n = stones.length;
    int max_cost = stones[n-1];
    for(int i = 1; i < n-1; ++i){
        max_cost = Math.min(max_cost, Math.max(stones[i], stones[n-1]-stones[i]));
    }
    return max_cost;
}
```
The algorithm calculates the minimum cost of a path for the frog. It first initializes the maximum cost as the last stone. It then iterates through the stones (excluding the first and last one), and at each stone, it calculates the cost of jumping to the last stone and back. It updates the max_cost with the minimum of itself and the current cost. Finally, it returns the max_cost as the result. Since we iterate through the stones once, the time complexity is O(n).

## A solution in C++

```cpp
int minimumPathCost(vector<int>& stones) {
    int n = stones.size();
    int max_cost = stones[n-1];
    for(int i = 1; i < n-1; ++i){
        max_cost = min(max_cost, max(stones[i], stones[n-1]-stones[i]));
    }
    return max_cost;
}
```
The algorithm calculates the minimum cost of a path for the frog. It first initializes the maximum cost as the last stone. It then iterates through the stones (excluding the first and last one), and at each stone, it calculates the cost of jumping to the last stone and back. It updates the max_cost with the minimum of itself and the current cost. Finally, it returns the max_cost as the result. Since we iterate through the stones once, the time complexity is O(n).

## A solution in Python

```python
def minimum_path_cost(stones):
    n = len(stones)
    max_cost = stones[n-1]
    for i in range(1, n-1):
        max_cost = min(max_cost, max(stones[i], stones[n-1]-stones[i]))
    return max_cost
```
The algorithm calculates the minimum cost of a path for the frog. It first initializes the maximum cost as the last stone. It then iterates through the stones (excluding the first and last one), and at each stone, it calculates the cost of jumping to the last stone and back. It updates the max_cost with the minimum of itself and the current cost. Finally, it returns the max_cost as the result. Since we iterate through the stones once, the time complexity is O(n).

## A solution in Javascript

```javascript
function minimumPathCost(stones) {
    let n = stones.length;
    let max_cost = stones[n-1];
    for(let i = 1; i < n-1; ++i){
        max_cost = Math.min(max_cost, Math.max(stones[i], stones[n-1]-stones[i]));
    }
    return max_cost;
}
```
The algorithm calculates the minimum cost of a path for the frog. It first initializes the maximum cost as the last stone. It then iterates through the stones (excluding the first and last one), and at each stone, it calculates the cost of jumping to the last stone and back. It updates the max_cost with the minimum of itself and the current cost. Finally, it returns the max_cost as the result. Since we iterate through the stones once, the time complexity is O(n).


# Minimum Total Cost to Make Arrays Unequal

- slug: minimum-total-cost-to-make-arrays-unequal
- difficulty: Hard

You are given two **0-indexed** integer arrays `nums1` and `nums2`, of equal length `n`.

In one operation, you can swap the values of any two indices of `nums1`. The **cost** of this operation is the **sum** of the indices.

Find the **minimum** total cost of performing the given operation **any** number of times such that `nums1[i] != nums2[i]` for all `0 <= i <= n - 1` after performing all the operations.

Return _the **minimum total cost** such that_ `nums1` and `nums2` _satisfy the above condition_. In case it is not possible, return `-1`.

**Example 1:**

**Input:** nums1 = \[1,2,3,4,5\], nums2 = \[1,2,3,4,5\]
**Output:** 10
**Explanation:**
One of the ways we can perform the operations is:
- Swap values at indices 0 and 3, incurring cost = 0 + 3 = 3. Now, nums1 = \[4,2,3,1,5\]
- Swap values at indices 1 and 2, incurring cost = 1 + 2 = 3. Now, nums1 = \[4,3,2,1,5\].
- Swap values at indices 0 and 4, incurring cost = 0 + 4 = 4. Now, nums1 =\[5,3,2,1,4\].
We can see that for each index i, nums1\[i\] != nums2\[i\]. The cost required here is 10.
Note that there are other ways to swap values, but it can be proven that it is not possible to obtain a cost less than 10.

**Example 2:**

**Input:** nums1 = \[2,2,2,1,3\], nums2 = \[1,2,2,3,3\]
**Output:** 10
**Explanation:**
One of the ways we can perform the operations is:
- Swap values at indices 2 and 3, incurring cost = 2 + 3 = 5. Now, nums1 = \[2,2,1,2,3\].
- Swap values at indices 1 and 4, incurring cost = 1 + 4 = 5. Now, nums1 = \[2,3,1,2,2\].
The total cost needed here is 10, which is the minimum possible.

**Example 3:**

**Input:** nums1 = \[1,2,2\], nums2 = \[1,2,2\]
**Output:** -1
**Explanation:**
It can be shown that it is not possible to satisfy the given conditions irrespective of the number of operations we perform.
Hence, we return -1.

**Constraints:**

*   `n == nums1.length == nums2.length`
*   `1 <= n <= 105`
*   `1 <= nums1[i], nums2[i] <= n`

## A solution in Java

```java
public int minCost(int[] nums1, int[] nums2) {
    Map<Integer, List<Integer>> valueToIndices = new HashMap<>();
    for (int i = 0; i < nums1.length; ++i) {
        valueToIndices.putIfAbsent(nums1[i], new ArrayList<>());
        valueToIndices.get(nums1[i]).add(i);
    }

    int result = 0;
    for (int val : nums2) {
        List<Integer> indices = valueToIndices.get(val);
        if (indices == null || indices.isEmpty()) return -1;
        result += indices.get(indices.size() - 1);
        indices.remove(indices.size() - 1);
    }

    return result;
}
```
We make a mapping (`value_to_indices`) from each value in `nums1` to its indices in `nums1`.

Then, for each value `val` in `nums2`, we get the last index from `value_to_indices[val]` vector, add it to the result, and remove it from the vector. If at any point the vector is empty, it means we can't satisfy the conditions and we return -1.

## A solution in C++

```cpp
int minCost(vector<int>& nums1, vector<int>& nums2) {
    unordered_map<int, vector<int>> value_to_indices;
    for (int i = 0; i < nums1.size(); ++i) {
        value_to_indices[nums1[i]].push_back(i);
    }

    int result = 0;
    for (int val : nums2) {
        if (value_to_indices[val].empty()) return -1;
        result += value_to_indices[val].back();
        value_to_indices[val].pop_back();
    }

    return result;
}
```
We make a mapping (`value_to_indices`) from each value in `nums1` to its indices in `nums1`.

Then, for each value `val` in `nums2`, we get the last index from `value_to_indices[val]` vector, add it to the result, and remove it from the vector. If at any point the vector is empty, it means we can't satisfy the conditions and we return -1.

## A solution in Python

```python
def min_cost(nums1: List[int], nums2: List[int]) -> int:
    value_to_indices = {}
    for i, val in enumerate(nums1):
        value_to_indices.setdefault(val, []).append(i)

    result = 0
    for val in nums2:
        if not value_to_indices[val]:
            return -1
        result += value_to_indices[val].pop()

    return result
```
We make a mapping (`value_to_indices`) from each value in `nums1` to its indices in `nums1`.

Then, for each value `val` in `nums2`, we get the last index from `value_to_indices[val]` vector, add it to the result, and remove it from the vector. If at any point the vector is empty, it means we can't satisfy the conditions and we return -1.

## A solution in Javascript

```javascript
function minCost(nums1, nums2) {
    const valueToIndices = new Map();
    for (let i = 0; i < nums1.length; ++i) {
        if (!valueToIndices.has(nums1[i])) {
            valueToIndices.set(nums1[i], []);
        }
        valueToIndices.get(nums1[i]).push(i);
    }

    let result = 0;
    for (const val of nums2) {
        const indices = valueToIndices.get(val);
        if (!indices || indices.length === 0) return -1;
        result += indices.pop();
    }

    return result;
}
```
We make a mapping (`value_to_indices`) from each value in `nums1` to its indices in `nums1`.

Then, for each value `val` in `nums2`, we get the last index from `value_to_indices[val]` vector, add it to the result, and remove it from the vector. If at any point the vector is empty, it means we can't satisfy the conditions and we return -1.


# Delete Greatest Value in Each Row

- slug: delete-greatest-value-in-each-row
- difficulty: Easy

You are given an `m x n` matrix `grid` consisting of positive integers.

Perform the following operation until `grid` becomes empty:

*   Delete the element with the greatest value from each row. If multiple such elements exist, delete any of them.
*   Add the maximum of deleted elements to the answer.

**Note** that the number of columns decreases by one after each operation.

Return _the answer after performing the operations described above_.

**Example 1:**

**Input:** grid = \[\[1,2,4\],\[3,3,1\]\]
**Output:** 8
**Explanation:** The diagram above shows the removed values in each step.
- In the first operation, we remove 4 from the first row and 3 from the second row (notice that, there are two cells with value 3 and we can remove any of them). We add 4 to the answer.
- In the second operation, we remove 2 from the first row and 3 from the second row. We add 3 to the answer.
- In the third operation, we remove 1 from the first row and 1 from the second row. We add 1 to the answer.
The final answer = 4 + 3 + 1 = 8.

**Example 2:**

**Input:** grid = \[\[10\]\]
**Output:** 10
**Explanation:** The diagram above shows the removed values in each step.
- In the first operation, we remove 10 from the first row. We add 10 to the answer.
The final answer = 10.

**Constraints:**

*   `m == grid.length`
*   `n == grid[i].length`
*   `1 <= m, n <= 50`
*   `1 <= grid[i][j] <= 100`

## A solution in Java

```java
int maxValueAfterOperations(int[][] grid) {
    int ans = 0;
    while (grid.length != 0) {
        int maxVal = 0, maxRow = -1;

        for (int i = 0; i < grid.length; ++i) {
            int rowMax = Arrays.stream(grid[i]).max().getAsInt();
            if (rowMax > maxVal) {
                maxVal = rowMax;
                maxRow = i;
            }
            grid[i] = Arrays.stream(grid[i]).filter(e -> e != rowMax).toArray();
        }

        ans += maxVal;
        if (grid[maxRow].length == 0) {
            grid = Arrays.stream(grid).filter(row -> row.length != 0).toArray(int[][]::new);
        }
    }

    return ans;
}
```
- Loop until 'grid' becomes empty.
- Search for the greatest element in each row and delete any of them if there's a tie. Keep track of the maximum of deleted elements and the respective row number.
- Add the maximum of deleted elements to 'ans'.
- If the row with initially found maximum becomes empty, remove that row from 'grid'.
- Finally, return the sum of all maximum deleted elements 'ans'.

## A solution in C++

```cpp
int maxValueAfterOperations(vector<vector<int>>& grid) {
    int ans = 0;
    while (!grid.empty()) {
        int maxVal = 0, maxRow = -1;

        for(int i = 0; i < grid.size(); ++i) {
            auto it = max_element(grid[i].begin(), grid[i].end());
            if(*it > maxVal) {
                maxVal = *it;
                maxRow = i;
            }
            grid[i].erase(it);
        }

        ans += maxVal;
        if (grid[maxRow].empty()) {
            grid.erase(grid.begin() + maxRow);
        }
    }

    return ans;
}
```
- Loop until 'grid' becomes empty.
- Search for the greatest element in each row and delete any of them if there's a tie. Keep track of the maximum of deleted elements and the respective row number.
- Add the maximum of deleted elements to 'ans'.
- If the row with initially found maximum becomes empty, remove that row from 'grid'.
- Finally, return the sum of all maximum deleted elements 'ans'.

## A solution in Python

```python
def maxValueAfterOperations(grid):
    ans = 0
    while grid:
        maxVal = 0
        maxRow = -1

        for i, row in enumerate(grid):
            rowMax = max(row)
            if rowMax > maxVal:
                maxVal = rowMax
                maxRow = i
            grid[i] = [e for e in row if e != rowMax]

        ans += maxVal
        if not grid[maxRow]:
            grid.pop(maxRow)

    return ans
```
- Loop until 'grid' becomes empty.
- Search for the greatest element in each row and delete any of them if there's a tie. Keep track of the maximum of deleted elements and the respective row number.
- Add the maximum of deleted elements to 'ans'.
- If the row with initially found maximum becomes empty, remove that row from 'grid'.
- Finally, return the sum of all maximum deleted elements 'ans'.

## A solution in Javascript

```javascript
function maxValueAfterOperations(grid) {
    let ans = 0;
    while (grid.length) {
        let maxVal = 0;
        let maxRow = -1;

        grid.forEach((row, i) => {
            let rowMax = Math.max(...row);
            if (rowMax > maxVal) {
                maxVal = rowMax;
                maxRow = i;
            }
            grid[i] = row.filter(e => e !== rowMax);
        });

        ans += maxVal;
        if (!grid[maxRow].length) {
            grid.splice(maxRow, 1);
        }
    }

    return ans;
}
```
- Loop until 'grid' becomes empty.
- Search for the greatest element in each row and delete any of them if there's a tie. Keep track of the maximum of deleted elements and the respective row number.
- Add the maximum of deleted elements to 'ans'.
- If the row with initially found maximum becomes empty, remove that row from 'grid'.
- Finally, return the sum of all maximum deleted elements 'ans'.


# Longest Square Streak in an Array

- slug: longest-square-streak-in-an-array
- difficulty: Medium

You are given an integer array `nums`. A subsequence of `nums` is called a **square streak** if:

*   The length of the subsequence is at least `2`, and
*   **after** sorting the subsequence, each element (except the first element) is the **square** of the previous number.

Return _the length of the **longest square streak** in_ `nums`_, or return_ `-1` _if there is no **square streak**._

A **subsequence** is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

**Example 1:**

**Input:** nums = \[4,3,6,16,8,2\]
**Output:** 3
**Explanation:** Choose the subsequence \[4,16,2\]. After sorting it, it becomes \[2,4,16\].
- 4 = 2 \* 2.
- 16 = 4 \* 4.
Therefore, \[4,16,2\] is a square streak.
It can be shown that every subsequence of length 4 is not a square streak.

**Example 2:**

**Input:** nums = \[2,3,5,6,7\]
**Output:** -1
**Explanation:** There is no square streak in nums so return -1.

**Constraints:**

*   `2 <= nums.length <= 105`
*   `2 <= nums[i] <= 105`

## A solution in Java

```java
import java.util.HashSet;
import java.util.Set;

public int longestSquareStreak(int[] nums) {
    Set<Integer> numSet = new HashSet<>();

    for (int num : nums) {
        numSet.add(num);
    }

    int longestStreak = -1;

    for (int num : numSet) {
        int streak = 1;

        while (numSet.contains((int) Math.sqrt(num))) {
            streak++;
            num = (int) Math.sqrt(num);
        }

        longestStreak = Math.max(longestStreak, streak);
    }

    return longestStreak >= 2 ? longestStreak : -1;
}
```
The algorithm for finding the longest square streak consists of the following steps:

1. Create a set of unique numbers from the given array. This will help in eliminating duplicate numbers.
2. Initialize a variable 'longestStreak' to store the length of the longest square streak found so far. Set it to -1 initially.
3. Iterate through each unique number in the set.
4. For each number, start a streak count at 1.
5. Check if the square root of the current number is present in the set. If it is, increment the streak count and update the current number in the streak to the square root of the current number.
6. Repeat step 5 until the square root of the current number is not found in the set.
7. Update the longest streak found so far by comparing it with the current streak.
8. After iterating through all unique numbers, check if the longest streak is at least 2. If it is, return the length of the longest streak. Otherwise, return -1.

## A solution in C++

```cpp
#include <unordered_set>
#include <cmath>
#include <algorithm>

int longest_square_streak(std::vector<int>& nums) {
    std::unordered_set<int> num_set(nums.begin(), nums.end());
    int longest_streak = -1;

    for (int num : num_set) {
        int streak = 1;

        while (num_set.count(static_cast<int>(std::pow(num, 0.5))) > 0) {
            ++streak;
            num = static_cast<int>(std::pow(num, 0.5));
        }

        longest_streak = std::max(longest_streak, streak);
    }

    return longest_streak >= 2 ? longest_streak : -1;
}
```
The algorithm for finding the longest square streak consists of the following steps:

1. Create a set of unique numbers from the given array. This will help in eliminating duplicate numbers.
2. Initialize a variable 'longestStreak' to store the length of the longest square streak found so far. Set it to -1 initially.
3. Iterate through each unique number in the set.
4. For each number, start a streak count at 1.
5. Check if the square root of the current number is present in the set. If it is, increment the streak count and update the current number in the streak to the square root of the current number.
6. Repeat step 5 until the square root of the current number is not found in the set.
7. Update the longest streak found so far by comparing it with the current streak.
8. After iterating through all unique numbers, check if the longest streak is at least 2. If it is, return the length of the longest streak. Otherwise, return -1.

## A solution in Python

```python
def longest_square_streak(nums):
    num_set = set(nums)
    longest_streak = -1

    for num in num_set:
        streak = 1

        while int(num ** 0.5) in num_set:
            streak += 1
            num = int(num ** 0.5)

        longest_streak = max(longest_streak, streak)

    return longest_streak if longest_streak >= 2 else -1
```
The algorithm for finding the longest square streak consists of the following steps:

1. Create a set of unique numbers from the given array. This will help in eliminating duplicate numbers.
2. Initialize a variable 'longestStreak' to store the length of the longest square streak found so far. Set it to -1 initially.
3. Iterate through each unique number in the set.
4. For each number, start a streak count at 1.
5. Check if the square root of the current number is present in the set. If it is, increment the streak count and update the current number in the streak to the square root of the current number.
6. Repeat step 5 until the square root of the current number is not found in the set.
7. Update the longest streak found so far by comparing it with the current streak.
8. After iterating through all unique numbers, check if the longest streak is at least 2. If it is, return the length of the longest streak. Otherwise, return -1.

## A solution in Javascript

```javascript
function longestSquareStreak(nums) {
    const numSet = new Set(nums);
    let longestStreak = -1;

    for (const num of numSet) {
        let streak = 1;

        while (numSet.has(Math.sqrt(num))) {
            streak++;
            num = Math.sqrt(num);
        }

        longestStreak = Math.max(longestStreak, streak);
    }

    return longestStreak >= 2 ? longestStreak : -1;
}
```
The algorithm for finding the longest square streak consists of the following steps:

1. Create a set of unique numbers from the given array. This will help in eliminating duplicate numbers.
2. Initialize a variable 'longestStreak' to store the length of the longest square streak found so far. Set it to -1 initially.
3. Iterate through each unique number in the set.
4. For each number, start a streak count at 1.
5. Check if the square root of the current number is present in the set. If it is, increment the streak count and update the current number in the streak to the square root of the current number.
6. Repeat step 5 until the square root of the current number is not found in the set.
7. Update the longest streak found so far by comparing it with the current streak.
8. After iterating through all unique numbers, check if the longest streak is at least 2. If it is, return the length of the longest streak. Otherwise, return -1.


# Design Memory Allocator

- slug: design-memory-allocator
- difficulty: Medium

You are given an integer `n` representing the size of a **0-indexed** memory array. All memory units are initially free.

You have a memory allocator with the following functionalities:

1.  **Allocate** a block of `size` consecutive free memory units and assign it the id `mID`.
2.  **Free** all memory units with the given id `mID`.

**Note** that:

*   Multiple blocks can be allocated to the same `mID`.
*   You should free all the memory units with `mID`, even if they were allocated in different blocks.

Implement the `Allocator` class:

*   `Allocator(int n)` Initializes an `Allocator` object with a memory array of size `n`.
*   `int allocate(int size, int mID)` Find the **leftmost** block of `size` **consecutive** free memory units and allocate it with the id `mID`. Return the block's first index. If such a block does not exist, return `-1`.
*   `int free(int mID)` Free all memory units with the id `mID`. Return the number of memory units you have freed.

**Example 1:**

**Input**
\[ "Allocator ",  "allocate ",  "allocate ",  "allocate ",  "free ",  "allocate ",  "allocate ",  "allocate ",  "free ",  "allocate ",  "free "\]
\[\[10\], \[1, 1\], \[1, 2\], \[1, 3\], \[2\], \[3, 4\], \[1, 1\], \[1, 1\], \[1\], \[10, 2\], \[7\]\]
**Output**
\[null, 0, 1, 2, 1, 3, 1, 6, 3, -1, 0\]

**Explanation**
Allocator loc = new Allocator(10); // Initialize a memory array of size 10. All memory units are initially free.
loc.allocate(1, 1); // The leftmost block's first index is 0. The memory array becomes \[**1**,\_,\_,\_,\_,\_,\_,\_,\_,\_\]. We return 0.
loc.allocate(1, 2); // The leftmost block's first index is 1. The memory array becomes \[1,**2**,\_,\_,\_,\_,\_,\_,\_,\_\]. We return 1.
loc.allocate(1, 3); // The leftmost block's first index is 2. The memory array becomes \[1,2,**3**,\_,\_,\_,\_,\_,\_,\_\]. We return 2.
loc.free(2); // Free all memory units with mID 2. The memory array becomes \[1,\_, 3,\_,\_,\_,\_,\_,\_,\_\]. We return 1 since there is only 1 unit with mID 2.
loc.allocate(3, 4); // The leftmost block's first index is 3. The memory array becomes \[1,\_,3,**4**,**4**,**4**,\_,\_,\_,\_\]. We return 3.
loc.allocate(1, 1); // The leftmost block's first index is 1. The memory array becomes \[1,**1**,3,4,4,4,\_,\_,\_,\_\]. We return 1.
loc.allocate(1, 1); // The leftmost block's first index is 6. The memory array becomes \[1,1,3,4,4,4,**1**,\_,\_,\_\]. We return 6.
loc.free(1); // Free all memory units with mID 1. The memory array becomes \[\_,\_,3,4,4,4,\_,\_,\_,\_\]. We return 3 since there are 3 units with mID 1.
loc.allocate(10, 2); // We can not find any free block with 10 consecutive free memory units, so we return -1.
loc.free(7); // Free all memory units with mID 7. The memory array remains the same since there is no memory unit with mID 7. We return 0.

**Constraints:**

*   `1 <= n, size, mID <= 1000`
*   At most `1000` calls will be made to `allocate` and `free`.

## A solution in Java

```java
class Allocator {
    private int[] mem;

    public Allocator(int n) {
        mem = new int[n];
    }

    public int allocate(int size, int mID) {
        int start = -1, count = 0;
        for (int i = 0; i <= mem.length; i++) {
            if (i < mem.length && mem[i] == 0) {
                if (start == -1) start = i;
                count++;
            } else {
                if (count >= size) {
                    for (int j = start; j < start + size; j++) {
                        mem[j] = mID;
                    }
                    return start;
                }
                start = -1;
                count = 0;
            }
        }
        return -1;
    }

    public int free(int mID) {
        int count = 0;
        for (int i = 0; i < mem.length; i++) {
            if (mem[i] == mID) {
                count++;
                mem[i] = 0;
            }
        }
        return count;
    }
}
```
1. Create a memory array of size `n` initialized to 0.
2. Implement the `allocate` function:
    a. Iterate over the memory array.
    b. Check if there's an empty slot (value equals 0).
    c. If so, count the consecutive empty slots.
    d. If the number of consecutive empty slots is greater than or equal to the requested size, fill the slots with the given mID and return the start index of the allocated block.
    e. If not, continue searching and return -1 if not found.
3. Implement the `free` function:
    a. Iterate over the memory array.
    b. Check if a slot's value equals the given mID.
    c. If so, set the slot to 0 and increment a counter.
    d. Return the counter as the total number of memory units freed.

## A solution in C++

```cpp
class Allocator {
    vector<int> mem;
public:
    Allocator(int n): mem(n, 0) {}

    int allocate(int size, int mID) {
        int start = -1, count = 0;
        for(int i = 0; i <= mem.size(); ++i) {
            if(i < mem.size() && mem[i] == 0) {
                if(start == -1) start = i;
                count++;
            } else {
                if(count >= size) {
                    fill(mem.begin() + start, mem.begin() + start + size, mID);
                    return start;
                }
                start = -1;
                count = 0;
            }
        }
        return -1;
    }

    int free(int mID) {
        int count = 0;
        for(int i = 0; i < mem.size(); ++i) {
            if(mem[i] == mID) {
                count++;
                mem[i] = 0;
            }
        }
        return count;
    }
};
```
1. Create a memory array of size `n` initialized to 0.
2. Implement the `allocate` function:
    a. Iterate over the memory array.
    b. Check if there's an empty slot (value equals 0).
    c. If so, count the consecutive empty slots.
    d. If the number of consecutive empty slots is greater than or equal to the requested size, fill the slots with the given mID and return the start index of the allocated block.
    e. If not, continue searching and return -1 if not found.
3. Implement the `free` function:
    a. Iterate over the memory array.
    b. Check if a slot's value equals the given mID.
    c. If so, set the slot to 0 and increment a counter.
    d. Return the counter as the total number of memory units freed.

## A solution in Python

```python
class Allocator:
    def __init__(self, n: int):
        self.mem = [0] * n

    def allocate(self, size: int, mID: int) -> int:
        start, count = -1, 0
        for i in range(len(self.mem) + 1):
            if i < len(self.mem) and self.mem[i] == 0:
                if start == -1:
                    start = i
                count += 1
            else:
                if count >= size:
                    for j in range(start, start + size):
                        self.mem[j] = mID
                    return start
                start, count = -1, 0
        return -1

    def free(self, mID: int) -> int:
        count = 0
        for i in range(len(self.mem)):
            if self.mem[i] == mID:
                count += 1
                self.mem[i] = 0
        return count
```
1. Create a memory array of size `n` initialized to 0.
2. Implement the `allocate` function:
    a. Iterate over the memory array.
    b. Check if there's an empty slot (value equals 0).
    c. If so, count the consecutive empty slots.
    d. If the number of consecutive empty slots is greater than or equal to the requested size, fill the slots with the given mID and return the start index of the allocated block.
    e. If not, continue searching and return -1 if not found.
3. Implement the `free` function:
    a. Iterate over the memory array.
    b. Check if a slot's value equals the given mID.
    c. If so, set the slot to 0 and increment a counter.
    d. Return the counter as the total number of memory units freed.

## A solution in Javascript

```javascript
class Allocator {
    constructor(n) {
        this.mem = new Array(n).fill(0);
    }

    allocate(size, mID) {
        let start = -1, count = 0;
        for (let i = 0; i <= this.mem.length; ++i) {
            if (i < this.mem.length && this.mem[i] === 0) {
                if (start === -1) start = i;
                count++;
            } else {
                if (count >= size) {
                    for (let j = start; j < start + size; j++) {
                        this.mem[j] = mID;
                    }
                    return start;
                }
                start = -1;
                count = 0;
            }
        }
        return -1;
    }

    free(mID) {
        let count = 0;
        for (let i = 0; i < this.mem.length; ++i) {
            if (this.mem[i] === mID) {
                count++;
                this.mem[i] = 0;
            }
        }
        return count;
    }
};
```
1. Create a memory array of size `n` initialized to 0.
2. Implement the `allocate` function:
    a. Iterate over the memory array.
    b. Check if there's an empty slot (value equals 0).
    c. If so, count the consecutive empty slots.
    d. If the number of consecutive empty slots is greater than or equal to the requested size, fill the slots with the given mID and return the start index of the allocated block.
    e. If not, continue searching and return -1 if not found.
3. Implement the `free` function:
    a. Iterate over the memory array.
    b. Check if a slot's value equals the given mID.
    c. If so, set the slot to 0 and increment a counter.
    d. Return the counter as the total number of memory units freed.


# Maximum Number of Points From Grid Queries

- slug: maximum-number-of-points-from-grid-queries
- difficulty: Hard

You are given an `m x n` integer matrix `grid` and an array `queries` of size `k`.

Find an array `answer` of size `k` such that for each integer `queries[i]` you start in the **top left** cell of the matrix and repeat the following process:

*   If `queries[i]` is **strictly** greater than the value of the current cell that you are in, then you get one point if it is your first time visiting this cell, and you can move to any **adjacent** cell in all `4` directions: up, down, left, and right.
*   Otherwise, you do not get any points, and you end this process.

After the process, `answer[i]` is the **maximum** number of points you can get. **Note** that for each query you are allowed to visit the same cell **multiple** times.

Return _the resulting array_ `answer`.

**Example 1:**

**Input:** grid = \[\[1,2,3\],\[2,5,7\],\[3,5,1\]\], queries = \[5,6,2\]
**Output:** \[5,8,1\]
**Explanation:** The diagrams above show which cells we visit to get points for each query.

**Example 2:**

**Input:** grid = \[\[5,2,1\],\[1,1,2\]\], queries = \[3\]
**Output:** \[0\]
**Explanation:** We can not get any points because the value of the top left cell is already greater than or equal to 3.

**Constraints:**

*   `m == grid.length`
*   `n == grid[i].length`
*   `2 <= m, n <= 1000`
*   `4 <= m * n <= 105`
*   `k == queries.length`
*   `1 <= k <= 104`
*   `1 <= grid[i][j], queries[i] <= 106`

## A solution in Java

```java
import java.util.*;

public List<Integer> maxPoints(int[][] grid, int[] queries) {
    int m = grid.length;
    int n = grid[0].length;
    int[] dx = {-1, 0, 1, 0};
    int[] dy = {0, 1, 0, -1};
    List<Integer> result = new ArrayList<>();

    for (int query : queries) {
        int points = 0;
        Set<String> visited = new HashSet<>();
        Stack<int[]> stack = new Stack<>();
        stack.push(new int[]{0, 0});

        while (!stack.isEmpty()) {
            int[] cur = stack.pop();
            int x = cur[0], y = cur[1];
            String coordStr = x + "," + y;

            if (!visited.contains(coordStr) && grid[x][y] < query) {
                visited.add(coordStr);
                points++;
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[i], ny = y + dy[i];
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
                        stack.push(new int[]{nx, ny});
                    }
                }
            }
        }
        result.add(points);
    }
    return result;
}
```
The algorithm for this problem is essentially a depth-first search on the grid. For each query, start at the top left of the grid and perform a DFS.

1. If the cell has not been visited and the value of the cell is strictly lower than the query value, add the cell to the visited set, increment the points, and continue the DFS for all 4 adjacent cells.
2. If the cell is visited or the value is not lower than the query, the DFS terminates for that path.

This process is repeated for all queries, and the answer array is returned with the maximum points for each query.

## A solution in C++

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

vector<int> traverseMatrix(vector<vector<int>>& grid, const vector<int>& queries, int m, int n) {
    vector<int> dx = {-1, 0, 1, 0};
    vector<int> dy = {0, 1, 0, -1};
    vector<int> answer(queries.size(), 0);

    for (int k = 0; k < queries.size(); ++k) {
        int q = queries[k];
        int points = 0;
        set<pair<int, int>> visited;

        function<void(int, int)> dfs = [&](int x, int y) {
            if (visited.find({x, y}) == visited.end() && grid[x][y] < q) {
                visited.insert({x, y});
                points++;
                for (int i = 0; i < 4; ++i) {
                    int nx = x + dx[i], ny = y + dy[i];
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
                        dfs(nx, ny);
                    }
                }
            }
        };

        dfs(0, 0);
        answer[k] = points;
    }

    return answer;
}

vector<int> maxPoints(vector<vector<int>>& grid, vector<int>& queries) {
    int m = grid.size();
    int n = grid[0].size();
    return traverseMatrix(grid, queries, m, n);
}
```
The algorithm for this problem is essentially a depth-first search on the grid. For each query, start at the top left of the grid and perform a DFS.

1. If the cell has not been visited and the value of the cell is strictly lower than the query value, add the cell to the visited set, increment the points, and continue the DFS for all 4 adjacent cells.
2. If the cell is visited or the value is not lower than the query, the DFS terminates for that path.

This process is repeated for all queries, and the answer array is returned with the maximum points for each query.

## A solution in Python

```python
from typing import List

def maxPoints(grid: List[List[int]], queries: List[int]) -> List[int]:
    m, n = len(grid), len(grid[0])
    dx = [-1, 0, 1, 0]
    dy = [0, 1, 0, -1]

    def dfs(x: int, y: int, q: int, visited: set) -> int:
        if 0 <= x < m and 0 <= y < n and grid[x][y] < q and (x, y) not in visited:
            visited.add((x, y))
            points = 1
            for i in range(4):
                nx, ny = x + dx[i], y + dy[i]
                points += dfs(nx, ny, q, visited)
            return points
        return 0

    return [dfs(0, 0, query, set()) for query in queries]
```
The algorithm for this problem is essentially a depth-first search on the grid. For each query, start at the top left of the grid and perform a DFS.

1. If the cell has not been visited and the value of the cell is strictly lower than the query value, add the cell to the visited set, increment the points, and continue the DFS for all 4 adjacent cells.
2. If the cell is visited or the value is not lower than the query, the DFS terminates for that path.

This process is repeated for all queries, and the answer array is returned with the maximum points for each query.

## A solution in Javascript

```javascript
function maxPoints(grid, queries) {
    const m = grid.length;
    const n = grid[0].length;
    const dx = [-1, 0, 1, 0];
    const dy = [0, 1, 0, -1];

    function dfs(x, y, q, visited) {
        if (0 <= x && x < m && 0 <= y && y < n && grid[x][y] < q && !visited.has(`${x},${y}`)) {
            visited.add(`${x},${y}`);
            let points = 1;
            for (let i = 0; i < 4; i++) {
                const nx = x + dx[i], ny = y + dy[i];
                points += dfs(nx, ny, q, visited);
            }
            return points;
        }
        return 0;
    }

    return queries.map(query => dfs(0, 0, query, new Set()));
}
```
The algorithm for this problem is essentially a depth-first search on the grid. For each query, start at the top left of the grid and perform a DFS.

1. If the cell has not been visited and the value of the cell is strictly lower than the query value, add the cell to the visited set, increment the points, and continue the DFS for all 4 adjacent cells.
2. If the cell is visited or the value is not lower than the query, the DFS terminates for that path.

This process is repeated for all queries, and the answer array is returned with the maximum points for each query.


# Bitwise OR of All Subsequence Sums

- slug: bitwise-or-of-all-subsequence-sums
- difficulty: Medium

Given an integer array `nums`, return _the value of the bitwise_ **OR** _of the sum of all possible **subsequences** in the array_.

A **subsequence** is a sequence that can be derived from another sequence by removing zero or more elements without changing the order of the remaining elements.

**Example 1:**

**Input:** nums = \[2,1,0,3\]
**Output:** 7
**Explanation:** All possible subsequence sums that we can have are: 0, 1, 2, 3, 4, 5, 6.
And we have 0 OR 1 OR 2 OR 3 OR 4 OR 5 OR 6 = 7, so we return 7.

**Example 2:**

**Input:** nums = \[0,0,0\]
**Output:** 0
**Explanation:** 0 is the only possible subsequence sum we can have, so we return 0.

**Constraints:**

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

## A solution in Java

```java
public int subsequenceORSum(int[] nums) {
    int result = 0;
    for (int num : nums) {
        result |= num;
    }
    return result;
}
```
For each integer in the array, we use the bitwise OR operation to accumulate the results, since it ensures that we don't lose any set bit while combining numbers. At the end, the result variable holds the bitwise OR sum of all subsequences in the array. This is an O(n) solution, as it iterates through the input array once.

## A solution in C++

```cpp
int subsequenceORSum(vector<int>& nums) {
    int result = 0;
    for (int num : nums) {
        result |= num;
    }
    return result;
}
```
For each integer in the array, we use the bitwise OR operation to accumulate the results, since it ensures that we don't lose any set bit while combining numbers. At the end, the result variable holds the bitwise OR sum of all subsequences in the array. This is an O(n) solution, as it iterates through the input array once.

## A solution in Python

```python
def subsequence_or_sum(nums):
    result = 0
    for num in nums:
        result |= num
    return result
```
For each integer in the array, we use the bitwise OR operation to accumulate the results, since it ensures that we don't lose any set bit while combining numbers. At the end, the result variable holds the bitwise OR sum of all subsequences in the array. This is an O(n) solution, as it iterates through the input array once.

## A solution in Javascript

```javascript
function subsequenceORSum(nums) {
    let result = 0;
    for (let num of nums) {
        result |= num;
    }
    return result;
}
```
For each integer in the array, we use the bitwise OR operation to accumulate the results, since it ensures that we don't lose any set bit while combining numbers. At the end, the result variable holds the bitwise OR sum of all subsequences in the array. This is an O(n) solution, as it iterates through the input array once.


# Count Pairs Of Similar Strings

- slug: count-pairs-of-similar-strings
- difficulty: Easy

You are given a **0-indexed** string array `words`.

Two strings are **similar** if they consist of the same characters.

*   For example, `"abca "` and `"cba "` are similar since both consist of characters `'a'`, `'b'`, and `'c'`.
*   However, `"abacba "` and `"bcfd "` are not similar since they do not consist of the same characters.

Return _the number of pairs_ `(i, j)` _such that_ `0 <= i < j <= word.length - 1` _and the two strings_ `words[i]` _and_ `words[j]` _are similar_.

**Example 1:**

**Input:** words = \[ "aba ", "aabb ", "abcd ", "bac ", "aabc "\]
**Output:** 2
**Explanation:** There are 2 pairs that satisfy the conditions:
- i = 0 and j = 1 : both words\[0\] and words\[1\] only consist of characters 'a' and 'b'.
- i = 3 and j = 4 : both words\[3\] and words\[4\] only consist of characters 'a', 'b', and 'c'.

**Example 2:**

**Input:** words = \[ "aabb ", "ab ", "ba "\]
**Output:** 3
**Explanation:** There are 3 pairs that satisfy the conditions:
- i = 0 and j = 1 : both words\[0\] and words\[1\] only consist of characters 'a' and 'b'.
- i = 0 and j = 2 : both words\[0\] and words\[2\] only consist of characters 'a' and 'b'.
- i = 1 and j = 2 : both words\[1\] and words\[2\] only consist of characters 'a' and 'b'.

**Example 3:**

**Input:** words = \[ "nba ", "cba ", "dba "\]
**Output:** 0
**Explanation:** Since there does not exist any pair that satisfies the conditions, we return 0.

**Constraints:**

*   `1 <= words.length <= 100`
*   `1 <= words[i].length <= 100`
*   `words[i]` consist of only lowercase English letters.

## A solution in Java

```java
import java.util.HashSet;
import java.util.Set;

public int countSimilarPairs(String[] words) {
    int count = 0;
    for (int i = 0; i < words.length; ++i) {
        for (int j = i + 1; j < words.length; ++j) {
            Set<Character> set1 = new HashSet<>();
            Set<Character> set2 = new HashSet<>();
            for (char c : words[i].toCharArray()) set1.add(c);
            for (char c : words[j].toCharArray()) set2.add(c);
            if (set1.equals(set2)) count++;
        }
    }
    return count;
}
```
We will use a nested loop to iterate through all pairs (i, j) such that 0 <= i < j <= words.length - 1. For each pair of words, create two sets containing the constituent characters for each string. To create the sets, use a set object initialized with the characters from the corresponding word. Compare the two sets to see if they are equal. If they are, increment a counter. After iterating through all possible pairs of words, return the counter as the total number of similar pairs.

## A solution in C++

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

int count_similar_pairs(std::vector<std::string>& words) {
    int count = 0;
    for (int i = 0; i < words.size(); ++i) {
        for (int j = i + 1; j < words.size(); ++j) {
            std::unordered_set<char> set1{words[i].begin(), words[i].end()};
            std::unordered_set<char> set2{words[j].begin(), words[j].end()};
            if (set1 == set2) count++;
        }
    }
    return count;
}
```
We will use a nested loop to iterate through all pairs (i, j) such that 0 <= i < j <= words.length - 1. For each pair of words, create two sets containing the constituent characters for each string. To create the sets, use a set object initialized with the characters from the corresponding word. Compare the two sets to see if they are equal. If they are, increment a counter. After iterating through all possible pairs of words, return the counter as the total number of similar pairs.

## A solution in Python

```python
def count_similar_pairs(words):
    count = 0
    for i in range(len(words)):
        for j in range(i + 1, len(words)):
            set1 = set(words[i])
            set2 = set(words[j])
            if set1 == set2:
                count += 1
    return count
```
We will use a nested loop to iterate through all pairs (i, j) such that 0 <= i < j <= words.length - 1. For each pair of words, create two sets containing the constituent characters for each string. To create the sets, use a set object initialized with the characters from the corresponding word. Compare the two sets to see if they are equal. If they are, increment a counter. After iterating through all possible pairs of words, return the counter as the total number of similar pairs.

## A solution in Javascript

```javascript
function countSimilarPairs(words) {
    let count = 0;
    for (let i = 0; i < words.length; ++i) {
        for (let j = i + 1; j < words.length; ++j) {
            let set1 = new Set(words[i]);
            let set2 = new Set(words[j]);
            if (areSetsEqual(set1, set2)) count++;
        }
    }
    return count;

    function areSetsEqual(set1, set2) {
        if (set1.size !== set2.size) return false;
        for (let item of set1) {
            if (!set2.has(item)) return false;
        }
        return true;
    }
}
```
We will use a nested loop to iterate through all pairs (i, j) such that 0 <= i < j <= words.length - 1. For each pair of words, create two sets containing the constituent characters for each string. To create the sets, use a set object initialized with the characters from the corresponding word. Compare the two sets to see if they are equal. If they are, increment a counter. After iterating through all possible pairs of words, return the counter as the total number of similar pairs.


# Smallest Value After Replacing With Sum of Prime Factors

- slug: smallest-value-after-replacing-with-sum-of-prime-factors
- difficulty: Medium

You are given a positive integer `n`.

Continuously replace `n` with the sum of its **prime factors**.

*   Note that if a prime factor divides `n` multiple times, it should be included in the sum as many times as it divides `n`.

Return _the smallest value_ `n` _will take on._

**Example 1:**

**Input:** n = 15
**Output:** 5
**Explanation:** Initially, n = 15.
15 = 3 \* 5, so replace n with 3 + 5 = 8.
8 = 2 \* 2 \* 2, so replace n with 2 + 2 + 2 = 6.
6 = 2 \* 3, so replace n with 2 + 3 = 5.
5 is the smallest value n will take on.

**Example 2:**

**Input:** n = 3
**Output:** 3
**Explanation:** Initially, n = 3.
3 is the smallest value n will take on.

**Constraints:**

*   `2 <= n <= 105`

## A solution in Java

```java
public int smallestFactorization(int n) {
    if (n <= 3)
        return n;
    int result = 0, factor = 1;
    for (int i = 2; i <= 5; ++i) {
        while (n % i == 0) {
            result += factor * i;
            factor *= 10;
            n /= i;
        }
    }
    return n == 1 ? result : n;
}
```
The algorithm starts by checking if `n` is less than or equal to 3. If it is, the input integer is already the smallest possible value and is returned. If it's not less than or equal to 3, then the algorithm initializes a variable `result` to store the minimum factorization and a variable `factor` to increase the weight of the prime factors when constructing the sum.

Then, we create a loop that iterates through the prime factors from 2 to 5 (the only prime factors that can divide the number many times to reduce to 1). For each prime factor `i`, we use a nested loop that continuously divides `n` by `i` if it’s divisible. For each successful division, we update `result` with the weighted sum of `factor` and `i` (i.e., `result += factor * i`), increment `factor` by a factor of 10 (i.e., `factor *= 10`), and update `n` to the result of the division (i.e., `n /= i`).

Once the loop is completed, we check if the updated `n` is 1. If it is, we return the `result` as it represents the smallest possible value of the input integer. Otherwise, we return `n`, since we are unable to factor it down to 1 while adding the factors to the sum.

## A solution in C++

```cpp
int smallestFactorization(int n) {
    if (n <= 3)
        return n;
    int result = 0, factor = 1;
    for (int i = 2; i <= 5; ++i) {
        while (n % i == 0) {
            result += factor * i;
            factor *= 10;
            n /= i;
        }
    }
    return n == 1 ? result : n;
}
```
The algorithm starts by checking if `n` is less than or equal to 3. If it is, the input integer is already the smallest possible value and is returned. If it's not less than or equal to 3, then the algorithm initializes a variable `result` to store the minimum factorization and a variable `factor` to increase the weight of the prime factors when constructing the sum.

Then, we create a loop that iterates through the prime factors from 2 to 5 (the only prime factors that can divide the number many times to reduce to 1). For each prime factor `i`, we use a nested loop that continuously divides `n` by `i` if it’s divisible. For each successful division, we update `result` with the weighted sum of `factor` and `i` (i.e., `result += factor * i`), increment `factor` by a factor of 10 (i.e., `factor *= 10`), and update `n` to the result of the division (i.e., `n /= i`).

Once the loop is completed, we check if the updated `n` is 1. If it is, we return the `result` as it represents the smallest possible value of the input integer. Otherwise, we return `n`, since we are unable to factor it down to 1 while adding the factors to the sum.

## A solution in Python

```python
def smallestFactorization(n):
    if n <= 3:
        return n
    result, factor = 0, 1
    for i in range(2, 6):
        while n % i == 0:
            result += factor * i
            factor *= 10
            n //= i
    return result if n == 1 else n
```
The algorithm starts by checking if `n` is less than or equal to 3. If it is, the input integer is already the smallest possible value and is returned. If it's not less than or equal to 3, then the algorithm initializes a variable `result` to store the minimum factorization and a variable `factor` to increase the weight of the prime factors when constructing the sum.

Then, we create a loop that iterates through the prime factors from 2 to 5 (the only prime factors that can divide the number many times to reduce to 1). For each prime factor `i`, we use a nested loop that continuously divides `n` by `i` if it’s divisible. For each successful division, we update `result` with the weighted sum of `factor` and `i` (i.e., `result += factor * i`), increment `factor` by a factor of 10 (i.e., `factor *= 10`), and update `n` to the result of the division (i.e., `n /= i`).

Once the loop is completed, we check if the updated `n` is 1. If it is, we return the `result` as it represents the smallest possible value of the input integer. Otherwise, we return `n`, since we are unable to factor it down to 1 while adding the factors to the sum.

## A solution in Javascript

```javascript
function smallestFactorization(n) {
    if (n <= 3)
        return n;
    let result = 0, factor = 1;
    for (let i = 2; i <= 5; ++i) {
        while (n % i === 0) {
            result += factor * i;
            factor *= 10;
            n /= i;
        }
    }
    return n === 1 ? result : n;
}
```
The algorithm starts by checking if `n` is less than or equal to 3. If it is, the input integer is already the smallest possible value and is returned. If it's not less than or equal to 3, then the algorithm initializes a variable `result` to store the minimum factorization and a variable `factor` to increase the weight of the prime factors when constructing the sum.

Then, we create a loop that iterates through the prime factors from 2 to 5 (the only prime factors that can divide the number many times to reduce to 1). For each prime factor `i`, we use a nested loop that continuously divides `n` by `i` if it’s divisible. For each successful division, we update `result` with the weighted sum of `factor` and `i` (i.e., `result += factor * i`), increment `factor` by a factor of 10 (i.e., `factor *= 10`), and update `n` to the result of the division (i.e., `n /= i`).

Once the loop is completed, we check if the updated `n` is 1. If it is, we return the `result` as it represents the smallest possible value of the input integer. Otherwise, we return `n`, since we are unable to factor it down to 1 while adding the factors to the sum.


# Add Edges to Make Degrees of All Nodes Even

- slug: add-edges-to-make-degrees-of-all-nodes-even
- difficulty: Hard

There is an **undirected** graph consisting of `n` nodes numbered from `1` to `n`. You are given the integer `n` and a **2D** array `edges` where `edges[i] = [ai, bi]` indicates that there is an edge between nodes `ai` and `bi`. The graph can be disconnected.

You can add **at most** two additional edges (possibly none) to this graph so that there are no repeated edges and no self-loops.

Return `true` _if it is possible to make the degree of each node in the graph even, otherwise return_ `false`_._

The degree of a node is the number of edges connected to it.

**Example 1:**

**Input:** n = 5, edges = \[\[1,2\],\[2,3\],\[3,4\],\[4,2\],\[1,4\],\[2,5\]\]
**Output:** true
**Explanation:** The above diagram shows a valid way of adding an edge.
Every node in the resulting graph is connected to an even number of edges.

**Example 2:**

**Input:** n = 4, edges = \[\[1,2\],\[3,4\]\]
**Output:** true
**Explanation:** The above diagram shows a valid way of adding two edges.

**Example 3:**

**Input:** n = 4, edges = \[\[1,2\],\[1,3\],\[1,4\]\]
**Output:** false
**Explanation:** It is not possible to obtain a valid graph with adding at most 2 edges.

**Constraints:**

*   `3 <= n <= 105`
*   `2 <= edges.length <= 105`
*   `edges[i].length == 2`
*   `1 <= ai, bi <= n`
*   `ai != bi`
*   There are no repeated edges.

## A solution in Java

```java
import java.util.HashMap;

public boolean possibleDegreeEven(int n, int[][] edges) {
    HashMap<Integer, Integer> degrees = new HashMap<>();
    for (int[] edge : edges) {
        degrees.put(edge[0], degrees.getOrDefault(edge[0], 0) + 1);
        degrees.put(edge[1], degrees.getOrDefault(edge[1], 0) + 1);
    }

    int odd_degrees = 0;
    for (int i = 1; i <= n; i++) {
        if (degrees.getOrDefault(i, 0) % 2 != 0) odd_degrees++;
    }

    return (odd_degrees == 0 || odd_degrees == 2);
}
```
The algorithm is as follows:
1. Create a degrees list to store the degree of each node (number of edges connected to the node).
2. Iterate through the edges list and increment the degree of both nodes (a and b) in each edge.
3. Count the number of nodes with odd degrees.
4. If the number of nodes with odd degrees is either 0 or 2, it is possible to add at most 2 edges to make the degree of each node even. Otherwise, it's not possible.

The solution is in O(n) time complexity, where n is the number of nodes.

## A solution in C++

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

bool possibleDegreeEven(int n, vector<vector<int>>& edges) {
    vector<int> degrees(n + 1, 0);
    for (const auto& edge : edges) {
        degrees[edge[0]]++;
        degrees[edge[1]]++;
    }

    int odd_degrees = 0;
    for (int i = 1; i <= n; i++) {
        if (degrees[i] % 2 != 0) odd_degrees++;
    }

    return (odd_degrees == 0 || odd_degrees == 2);
}
```
The algorithm is as follows:
1. Create a degrees list to store the degree of each node (number of edges connected to the node).
2. Iterate through the edges list and increment the degree of both nodes (a and b) in each edge.
3. Count the number of nodes with odd degrees.
4. If the number of nodes with odd degrees is either 0 or 2, it is possible to add at most 2 edges to make the degree of each node even. Otherwise, it's not possible.

The solution is in O(n) time complexity, where n is the number of nodes.

## A solution in Python

```python
from collections import defaultdict

def possible_degree_even(n, edges):
    degrees = defaultdict(int)
    for a, b in edges:
        degrees[a] += 1
        degrees[b] += 1

    odd_degrees = sum(1 for d in range(1, n + 1) if degrees[d] % 2 != 0)
    return odd_degrees == 0 or odd_degrees == 2
```
The algorithm is as follows:
1. Create a degrees list to store the degree of each node (number of edges connected to the node).
2. Iterate through the edges list and increment the degree of both nodes (a and b) in each edge.
3. Count the number of nodes with odd degrees.
4. If the number of nodes with odd degrees is either 0 or 2, it is possible to add at most 2 edges to make the degree of each node even. Otherwise, it's not possible.

The solution is in O(n) time complexity, where n is the number of nodes.

## A solution in Javascript

```javascript
function possibleDegreeEven(n, edges) {
    let degrees = {};
    for (let edge of edges) {
        degrees[edge[0]] = (degrees[edge[0]] || 0) + 1;
        degrees[edge[1]] = (degrees[edge[1]] || 0) + 1;
    }
    let odd_degrees = 0;
    for (let i = 1; i <= n; i++) {
        if ((degrees[i] || 0) % 2 != 0) odd_degrees++;
    }
    return (odd_degrees == 0 || odd_degrees == 2);
}
```
The algorithm is as follows:
1. Create a degrees list to store the degree of each node (number of edges connected to the node).
2. Iterate through the edges list and increment the degree of both nodes (a and b) in each edge.
3. Count the number of nodes with odd degrees.
4. If the number of nodes with odd degrees is either 0 or 2, it is possible to add at most 2 edges to make the degree of each node even. Otherwise, it's not possible.

The solution is in O(n) time complexity, where n is the number of nodes.


# Cycle Length Queries in a Tree

- slug: cycle-length-queries-in-a-tree
- difficulty: Hard

You are given an integer `n`. There is a **complete binary tree** with `2n - 1` nodes. The root of that tree is the node with the value `1`, and every node with a value `val` in the range `[1, 2n - 1 - 1]` has two children where:

*   The left node has the value `2 * val`, and
*   The right node has the value `2 * val + 1`.

You are also given a 2D integer array `queries` of length `m`, where `queries[i] = [ai, bi]`. For each query, solve the following problem:

1.  Add an edge between the nodes with values `ai` and `bi`.
2.  Find the length of the cycle in the graph.
3.  Remove the added edge between nodes with values `ai` and `bi`.

**Note** that:

*   A **cycle** is a path that starts and ends at the same node, and each edge in the path is visited only once.
*   The length of a cycle is the number of edges visited in the cycle.
*   There could be multiple edges between two nodes in the tree after adding the edge of the query.

Return _an array_ `answer` _of length_ `m` _where_ `answer[i]` _is the answer to the_ `ith` _query._

**Example 1:**

**Input:** n = 3, queries = \[\[5,3\],\[4,7\],\[2,3\]\]
**Output:** \[4,5,3\]
**Explanation:** The diagrams above show the tree of 23 - 1 nodes. Nodes colored in red describe the nodes in the cycle after adding the edge.
- After adding the edge between nodes 3 and 5, the graph contains a cycle of nodes \[5,2,1,3\]. Thus answer to the first query is 4. We delete the added edge and process the next query.
- After adding the edge between nodes 4 and 7, the graph contains a cycle of nodes \[4,2,1,3,7\]. Thus answer to the second query is 5. We delete the added edge and process the next query.
- After adding the edge between nodes 2 and 3, the graph contains a cycle of nodes \[2,1,3\]. Thus answer to the third query is 3. We delete the added edge.

**Example 2:**

**Input:** n = 2, queries = \[\[1,2\]\]
**Output:** \[2\]
**Explanation:** The diagram above shows the tree of 22 - 1 nodes. Nodes colored in red describe the nodes in the cycle after adding the edge.
- After adding the edge between nodes 1 and 2, the graph contains a cycle of nodes \[2,1\]. Thus answer for the first query is 2. We delete the added edge.

**Constraints:**

*   `2 <= n <= 30`
*   `m == queries.length`
*   `1 <= m <= 105`
*   `queries[i].length == 2`
*   `1 <= ai, bi <= 2n - 1`
*   `ai != bi`

## A solution in Java

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

public class Solution {
    public List<Integer> length_of_cycle(int n, int[][] queries) {
        List<Integer> result = new ArrayList();
        for (int[] query : queries) {
            int depth_A = 0, depth_B = 0, A = query[0], B = query[1];
            while (A != B) {
                if (A < B) {
                    int tmp = A;
                    A = B;
                    B = tmp;
                }
                A >>= 1;
                depth_A++;
            }
            result.add(depth_A + depth_B);
        }
        return result;
    }
}
```
The algorithm is based on tree traversal. For each query `[A, B]`, we keep track of the depth of nodes `A` and `B`. We traverse the tree by moving both nodes up (dividing by 2) until they become equal.

In each iteration, if `A < B`, we swap `A` and `B`. Then, we divide `A` by 2 and increment the depth of node `A`. This continues until nodes `A` and `B` become the same.

After the loop, the length of the cycle is the sum of the depths of both nodes.

This algorithm doesn't need to add and remove edges, as finding the nodes' depths gives us the cycle length directly.

## A solution in C++

```cpp
#include <vector>

std::vector<int> length_of_cycle(int n, const std::vector<std::vector<int>>& queries) {
    std::vector<int> result;
    for (const auto& query : queries) {
        int depth_A = 0, depth_B = 0, A = query[0], B = query[1];
        while (A != B) {
            if (A < B) std::swap(A, B);
            A >>= 1;
            depth_A++;
        }
        result.push_back(depth_A + depth_B);
    }
    return result;
}
```
The algorithm is based on tree traversal. For each query `[A, B]`, we keep track of the depth of nodes `A` and `B`. We traverse the tree by moving both nodes up (dividing by 2) until they become equal.

In each iteration, if `A < B`, we swap `A` and `B`. Then, we divide `A` by 2 and increment the depth of node `A`. This continues until nodes `A` and `B` become the same.

After the loop, the length of the cycle is the sum of the depths of both nodes.

This algorithm doesn't need to add and remove edges, as finding the nodes' depths gives us the cycle length directly.

## A solution in Python

```python
def length_of_cycle(n, queries):
    result = []
    for A, B in queries:
        depth_A, depth_B = 0, 0
        while A != B:
            if A < B:
                A, B = B, A
            A >>= 1
            depth_A += 1
        result.append(depth_A + depth_B)
    return result
```
The algorithm is based on tree traversal. For each query `[A, B]`, we keep track of the depth of nodes `A` and `B`. We traverse the tree by moving both nodes up (dividing by 2) until they become equal.

In each iteration, if `A < B`, we swap `A` and `B`. Then, we divide `A` by 2 and increment the depth of node `A`. This continues until nodes `A` and `B` become the same.

After the loop, the length of the cycle is the sum of the depths of both nodes.

This algorithm doesn't need to add and remove edges, as finding the nodes' depths gives us the cycle length directly.

## A solution in Javascript

```javascript
function length_of_cycle(n, queries) {
    const result = [];
    for (const query of queries) {
        let depth_A = 0, depth_B = 0, A = query[0], B = query[1];
        while (A !== B) {
            if (A < B) [A, B] = [B, A];
            A >>= 1;
            depth_A++;
        }
        result.push(depth_A + depth_B);
    }
    return result;
}
```
The algorithm is based on tree traversal. For each query `[A, B]`, we keep track of the depth of nodes `A` and `B`. We traverse the tree by moving both nodes up (dividing by 2) until they become equal.

In each iteration, if `A < B`, we swap `A` and `B`. Then, we divide `A` by 2 and increment the depth of node `A`. This continues until nodes `A` and `B` become the same.

After the loop, the length of the cycle is the sum of the depths of both nodes.

This algorithm doesn't need to add and remove edges, as finding the nodes' depths gives us the cycle length directly.


# Check if There is a Path With Equal Number of 0's And 1's

- slug: check-if-there-is-a-path-with-equal-number-of-0s-and-1s
- difficulty: Medium

You are given a **0-indexed** `m x n` **binary** matrix `grid`. You can move from a cell `(row, col)` to any of the cells `(row + 1, col)` or `(row, col + 1)`.

Return `true` _if there is a path from_ `(0, 0)` _to_ `(m - 1, n - 1)` _that visits an **equal** number of_ `0`_'s and_ `1`_'s_. Otherwise return `false`.

**Example 1:**

**Input:** grid = \[\[0,1,0,0\],\[0,1,0,0\],\[1,0,1,0\]\]
**Output:** true
**Explanation:** The path colored in blue in the above diagram is a valid path because we have 3 cells with a value of 1 and 3 with a value of 0. Since there is a valid path, we return true.

**Example 2:**

**Input:** grid = \[\[1,1,0\],\[0,0,1\],\[1,0,0\]\]
**Output:** false
**Explanation:** There is no path in this grid with an equal number of 0's and 1's.

**Constraints:**

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

## A solution in Java

```java
public boolean isValidPath(int[][] grid, int row, int col, int zeros, int ones) {
    if (row < 0 || col < 0 || row >= grid.length || col >= grid[0].length) {
        return false;
    }
    if (grid[row][col] == 1) {
        ones++;
    } else {
        zeros++;
    }
    if (row == grid.length - 1 && col == grid[0].length - 1) {
        return zeros == ones;
    }
    return isValidPath(grid, row + 1, col, zeros, ones) || isValidPath(grid, row, col + 1, zeros, ones);
}

public boolean equalPath(int[][] grid) {
    return isValidPath(grid, 0, 0, 0, 0);
}
```
The algorithm is based on a Depth First Search (DFS) approach, where the goal is to find a valid path by visiting each node in the grid exactly once. Starting at the top-left corner (0, 0), we recursively call `isValidPath` on the neighboring cells (row + 1, col) and (row, col + 1), and keep track of the number of zeros and ones visited so far.

At each recursive call of `isValidPath`, we first check if the current cell is in valid range. If it is not, we return false. We then increment the respective zeros or ones count based on the value of the current cell. If we reach the bottom-right corner (m - 1, n - 1), we check if the number of zeros and ones visited are equal, and return the result.

The algorithm continues to make recursive calls until either a valid path with equal zeros and ones is found, or all possible paths are exhausted. The final answer is returned as true or false accordingly.

## A solution in C++

```cpp
bool isValidPath(vector<vector<int>>& grid, int row, int col, int zeros, int ones) {
    if (row < 0 || col < 0 || row >= grid.size() || col >= grid[0].size()) {
        return false;
    }
    if (grid[row][col] == 1) {
        ones++;
    } else {
        zeros++;
    }
    if (row == grid.size() - 1 && col == grid[0].size() - 1) {
        return zeros == ones;
    }
    return isValidPath(grid, row + 1, col, zeros, ones) || isValidPath(grid, row, col + 1, zeros, ones);
}

bool equalPath(vector<vector<int>>& grid) {
    return isValidPath(grid, 0, 0, 0, 0);
}
```
The algorithm is based on a Depth First Search (DFS) approach, where the goal is to find a valid path by visiting each node in the grid exactly once. Starting at the top-left corner (0, 0), we recursively call `isValidPath` on the neighboring cells (row + 1, col) and (row, col + 1), and keep track of the number of zeros and ones visited so far.

At each recursive call of `isValidPath`, we first check if the current cell is in valid range. If it is not, we return false. We then increment the respective zeros or ones count based on the value of the current cell. If we reach the bottom-right corner (m - 1, n - 1), we check if the number of zeros and ones visited are equal, and return the result.

The algorithm continues to make recursive calls until either a valid path with equal zeros and ones is found, or all possible paths are exhausted. The final answer is returned as true or false accordingly.

## A solution in Python

```python
def isValidPath(grid, row, col, zeros, ones):
    if row < 0 or col < 0 or row >= len(grid) or col >= len(grid[0]):
        return False
    if grid[row][col] == 1:
        ones += 1
    else:
        zeros += 1
    if row == len(grid) - 1 and col == len(grid[0]) - 1:
        return zeros == ones
    return (isValidPath(grid, row + 1, col, zeros, ones)
            or isValidPath(grid, row, col + 1, zeros, ones))

def equalPath(grid):
    return isValidPath(grid, 0, 0, 0, 0)
```
The algorithm is based on a Depth First Search (DFS) approach, where the goal is to find a valid path by visiting each node in the grid exactly once. Starting at the top-left corner (0, 0), we recursively call `isValidPath` on the neighboring cells (row + 1, col) and (row, col + 1), and keep track of the number of zeros and ones visited so far.

At each recursive call of `isValidPath`, we first check if the current cell is in valid range. If it is not, we return false. We then increment the respective zeros or ones count based on the value of the current cell. If we reach the bottom-right corner (m - 1, n - 1), we check if the number of zeros and ones visited are equal, and return the result.

The algorithm continues to make recursive calls until either a valid path with equal zeros and ones is found, or all possible paths are exhausted. The final answer is returned as true or false accordingly.

## A solution in Javascript

```javascript
function isValidPath(grid, row, col, zeros, ones) {
    if (row < 0 || col < 0 || row >= grid.length || col >= grid[0].length) {
        return false;
    }
    if (grid[row][col] === 1) {
        ones++;
    } else {
        zeros++;
    }
    if (row === grid.length - 1 && col === grid[0].length - 1) {
        return zeros === ones;
    }
    return isValidPath(grid, row + 1, col, zeros, ones) || isValidPath(grid, row, col + 1, zeros, ones);
}

function equalPath(grid) {
    return isValidPath(grid, 0, 0, 0, 0);
}
```
The algorithm is based on a Depth First Search (DFS) approach, where the goal is to find a valid path by visiting each node in the grid exactly once. Starting at the top-left corner (0, 0), we recursively call `isValidPath` on the neighboring cells (row + 1, col) and (row, col + 1), and keep track of the number of zeros and ones visited so far.

At each recursive call of `isValidPath`, we first check if the current cell is in valid range. If it is not, we return false. We then increment the respective zeros or ones count based on the value of the current cell. If we reach the bottom-right corner (m - 1, n - 1), we check if the number of zeros and ones visited are equal, and return the result.

The algorithm continues to make recursive calls until either a valid path with equal zeros and ones is found, or all possible paths are exhausted. The final answer is returned as true or false accordingly.


# Maximum Enemy Forts That Can Be Captured

- slug: maximum-enemy-forts-that-can-be-captured
- difficulty: Easy

You are given a **0-indexed** integer array `forts` of length `n` representing the positions of several forts. `forts[i]` can be `-1`, `0`, or `1` where:

*   `-1` represents there is **no fort** at the `ith` position.
*   `0` indicates there is an **enemy** fort at the `ith` position.
*   `1` indicates the fort at the `ith` the position is under your command.

Now you have decided to move your army from one of your forts at position `i` to an empty position `j` such that:

*   `0 <= i, j <= n - 1`
*   The army travels over enemy forts **only**. Formally, for all `k` where `min(i,j) < k < max(i,j)`, `forts[k] == 0.`

While moving the army, all the enemy forts that come in the way are **captured**.

Return _the **maximum** number of enemy forts that can be captured_. In case it is **impossible** to move your army, or you do not have any fort under your command, return `0`_._

**Example 1:**

**Input:** forts = \[1,0,0,-1,0,0,0,0,1\]
**Output:** 4
**Explanation:**
- Moving the army from position 0 to position 3 captures 2 enemy forts, at 1 and 2.
- Moving the army from position 8 to position 3 captures 4 enemy forts.
Since 4 is the maximum number of enemy forts that can be captured, we return 4.

**Example 2:**

**Input:** forts = \[0,0,1,-1\]
**Output:** 0
**Explanation:** Since no enemy fort can be captured, 0 is returned.

**Constraints:**

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

## A solution in Java

```java
public int maxCapturedForts(int[] forts) {
    int n = forts.length;
    int maxCapture = 0;
    for(int i = 0; i < n; i++) {
        if(forts[i] == 1) {
            for(int j = i + 1; j < n; j++) {
                if(forts[j] != -1) {
                    int capture = 0;
                    for(int k = i + 1; k < j; k++) {
                        if(forts[k] == 0) capture++;
                    }
                    if(forts[j] == 1) maxCapture = Math.max(maxCapture, capture);
                }
            }
        }
    }
    return maxCapture;
}
```
For each of our fort (1), we try to move our army to another our fort (1) through enemy forts (0). For each pair of our forts, we count how many enemy forts we can capture in between our forts. We are only interested in the pair that captures the maximum number of enemy forts.

1. Iterate through each element in the array.
2. If the current fort is our fort (1), we iterate through the rest of the elements.
3. If the next element `j` is not an empty position (-1), we count the number of enemy forts we can capture.
4. If `forts[j]` is equal to 1, it means it's our fort, and we update the maximum number of captures.
5. After iterating through all elements, return the maximum number of captures.

## A solution in C++

```cpp
int maxCapturedForts(vector<int>& forts) {
    int n = forts.size();
    int maxCapture = 0;
    for(int i = 0; i < n; i++) {
        if(forts[i] == 1) {
            for(int j = i + 1; j < n; j++) {
                if(forts[j] != -1) {
                    int capture = 0;
                    for(int k = i + 1; k < j; k++) {
                        if(forts[k] == 0) capture++;
                    }
                    if(forts[j] == 1) maxCapture = max(maxCapture, capture);
                }
            }
        }
    }
    return maxCapture;
}
```
For each of our fort (1), we try to move our army to another our fort (1) through enemy forts (0). For each pair of our forts, we count how many enemy forts we can capture in between our forts. We are only interested in the pair that captures the maximum number of enemy forts.

1. Iterate through each element in the array.
2. If the current fort is our fort (1), we iterate through the rest of the elements.
3. If the next element `j` is not an empty position (-1), we count the number of enemy forts we can capture.
4. If `forts[j]` is equal to 1, it means it's our fort, and we update the maximum number of captures.
5. After iterating through all elements, return the maximum number of captures.

## A solution in Python

```python
def max_captured_forts(forts):
    n = len(forts)
    max_capture = 0
    for i in range(n):
        if forts[i] == 1:
            for j in range(i+1, n):
                if forts[j] != -1:
                    capture = sum(1 for k in range(i+1, j) if forts[k] == 0)
                    if forts[j] == 1:
                        max_capture = max(max_capture, capture)
    return max_capture
```
For each of our fort (1), we try to move our army to another our fort (1) through enemy forts (0). For each pair of our forts, we count how many enemy forts we can capture in between our forts. We are only interested in the pair that captures the maximum number of enemy forts.

1. Iterate through each element in the array.
2. If the current fort is our fort (1), we iterate through the rest of the elements.
3. If the next element `j` is not an empty position (-1), we count the number of enemy forts we can capture.
4. If `forts[j]` is equal to 1, it means it's our fort, and we update the maximum number of captures.
5. After iterating through all elements, return the maximum number of captures.

## A solution in Javascript

```javascript
function maxCapturedForts(forts) {
    const n = forts.length;
    let maxCapture = 0;
    for(let i = 0; i < n; i++) {
        if(forts[i] === 1) {
            for(let j = i + 1; j < n; j++) {
                if(forts[j] !== -1) {
                    let capture = 0;
                    for(let k = i + 1; k < j; k++) {
                        if(forts[k] === 0) capture++;
                    }
                    if(forts[j] === 1) maxCapture = Math.max(maxCapture, capture);
                }
            }
        }
    }
    return maxCapture;
}
```
For each of our fort (1), we try to move our army to another our fort (1) through enemy forts (0). For each pair of our forts, we count how many enemy forts we can capture in between our forts. We are only interested in the pair that captures the maximum number of enemy forts.

1. Iterate through each element in the array.
2. If the current fort is our fort (1), we iterate through the rest of the elements.
3. If the next element `j` is not an empty position (-1), we count the number of enemy forts we can capture.
4. If `forts[j]` is equal to 1, it means it's our fort, and we update the maximum number of captures.
5. After iterating through all elements, return the maximum number of captures.