# Search in Rotated Sorted Array

- slug: search-in-rotated-sorted-array
- difficulty: Medium

There is an integer array `nums` sorted in ascending order (with **distinct** values).

Prior to being passed to your function, `nums` is **possibly rotated** at an unknown pivot index `k` (`1 <= k < nums.length`) such that the resulting array is `[nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]` (**0-indexed**). For example, `[0,1,2,4,5,6,7]` might be rotated at pivot index `3` and become `[4,5,6,7,0,1,2]`.

Given the array `nums` **after** the possible rotation and an integer `target`, return _the index of_ `target` _if it is in_ `nums`_, or_ `-1` _if it is not in_ `nums`.

You must write an algorithm with `O(log n)` runtime complexity.

**Example 1:**

**Input:** nums = \[4,5,6,7,0,1,2\], target = 0
**Output:** 4

**Example 2:**

**Input:** nums = \[4,5,6,7,0,1,2\], target = 3
**Output:** -1

**Example 3:**

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

**Constraints:**

*   `1 <= nums.length <= 5000`
*   `-104 <= nums[i] <= 104`
*   All values of `nums` are **unique**.
*   `nums` is an ascending array that is possibly rotated.
*   `-104 <= target <= 104`

## A solution in Java

```java
public int search(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        }
        if (nums[mid] >= nums[left]) {
            if (target >= nums[left] && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (target > nums[mid] && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return -1;
}
```
The algorithm is a variation of binary search. The main idea is to decide whether the target is in the left or the right half of the current subarray. If nums[mid] >= nums[left], the left half is sorted. If target is in the range [nums[left], nums[mid]), set right = mid - 1. Otherwise, set left = mid + 1. If nums[mid] < nums[left], the right half must be sorted. If target is in the range (nums[mid], nums[right]], set left = mid + 1. Otherwise, set right = mid - 1. Continue the process until the target is found or the subarray is empty, in which case return -1. This algorithm has a runtime complexity of O(log n) because it eliminates half of the remaining elements at each step, similar to a binary search.

## A solution in C++

```cpp
int search(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        }
        if (nums[mid] >= nums[left]) {
            if (target >= nums[left] && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (target > nums[mid] && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return -1;
}
```
The algorithm is a variation of binary search. The main idea is to decide whether the target is in the left or the right half of the current subarray. If nums[mid] >= nums[left], the left half is sorted. If target is in the range [nums[left], nums[mid]), set right = mid - 1. Otherwise, set left = mid + 1. If nums[mid] < nums[left], the right half must be sorted. If target is in the range (nums[mid], nums[right]], set left = mid + 1. Otherwise, set right = mid - 1. Continue the process until the target is found or the subarray is empty, in which case return -1. This algorithm has a runtime complexity of O(log n) because it eliminates half of the remaining elements at each step, similar to a binary search.

## A solution in Python

```python
def search(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        if nums[mid] >= nums[left]:
            if target >= nums[left] and target < nums[mid]:
                right = mid - 1
            else:
                left = mid + 1
        else:
            if target > nums[mid] and target <= nums[right]:
                left = mid + 1
            else:
                right = mid - 1
    return -1
```
The algorithm is a variation of binary search. The main idea is to decide whether the target is in the left or the right half of the current subarray. If nums[mid] >= nums[left], the left half is sorted. If target is in the range [nums[left], nums[mid]), set right = mid - 1. Otherwise, set left = mid + 1. If nums[mid] < nums[left], the right half must be sorted. If target is in the range (nums[mid], nums[right]], set left = mid + 1. Otherwise, set right = mid - 1. Continue the process until the target is found or the subarray is empty, in which case return -1. This algorithm has a runtime complexity of O(log n) because it eliminates half of the remaining elements at each step, similar to a binary search.

## A solution in Javascript

```javascript
function search(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2);
        if (nums[mid] === target) {
            return mid;
        }
        if (nums[mid] >= nums[left]) {
            if (target >= nums[left] && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (target > nums[mid] && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return -1;
}
```
The algorithm is a variation of binary search. The main idea is to decide whether the target is in the left or the right half of the current subarray. If nums[mid] >= nums[left], the left half is sorted. If target is in the range [nums[left], nums[mid]), set right = mid - 1. Otherwise, set left = mid + 1. If nums[mid] < nums[left], the right half must be sorted. If target is in the range (nums[mid], nums[right]], set left = mid + 1. Otherwise, set right = mid - 1. Continue the process until the target is found or the subarray is empty, in which case return -1. This algorithm has a runtime complexity of O(log n) because it eliminates half of the remaining elements at each step, similar to a binary search.


# Find First and Last Position of Element in Sorted Array

- slug: find-first-and-last-position-of-element-in-sorted-array
- difficulty: Medium

Given an array of integers `nums` sorted in non-decreasing order, find the starting and ending position of a given `target` value.

If `target` is not found in the array, return `[-1, -1]`.

You must write an algorithm with `O(log n)` runtime complexity.

**Example 1:**

**Input:** nums = \[5,7,7,8,8,10\], target = 8
**Output:** \[3,4\]

**Example 2:**

**Input:** nums = \[5,7,7,8,8,10\], target = 6
**Output:** \[-1,-1\]

**Example 3:**

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

**Constraints:**

*   `0 <= nums.length <= 105`
*   `-109 <= nums[i] <= 109`
*   `nums` is a non-decreasing array.
*   `-109 <= target <= 109`

## A solution in Java

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

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
            if (nums[mid] == target) {
                start = mid;
            }
        }
    }

    left = 0;
    right = nums.length - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
            if (nums[mid] == target) {
                end = mid;
            }
        }
    }

    return new int[] {start, end};
}
```
1. Initialize `start` and `end` variables to -1 as default return values.
2. Setup `left` and `right` pointers at the beginning and end of the `nums` array.
3. Loop until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is smaller than `target`, move the `left` pointer to `mid + 1`.
   c. If the value at the `mid` index is greater than or equal to `target`, move the `right` pointer to `mid - 1`. If the value at the `mid` index is equal to `target`, update `start` with `mid`.
4. Reset `left` and `right` pointers to the beginning and end of the `nums` array.
5. Loop again until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is greater than `target`, move the `right` pointer to `mid - 1`.
   c. If the value at the `mid` index is smaller than or equal to `target`, move the `left` pointer to `mid + 1`. If the value at the `mid` index is equal to `target`, update `end` with `mid`.
6. Return the resulting `start` and `end` values as an array/list.

## A solution in C++

```cpp
#include <vector>

std::vector<int> searchRange(std::vector<int>& nums, int target) {
    int start = -1, end = -1;
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
            if (nums[mid] == target) {
                start = mid;
            }
        }
    }

    left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
            if (nums[mid] == target) {
                end = mid;
            }
        }
    }

    return {start, end};
}
```
1. Initialize `start` and `end` variables to -1 as default return values.
2. Setup `left` and `right` pointers at the beginning and end of the `nums` array.
3. Loop until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is smaller than `target`, move the `left` pointer to `mid + 1`.
   c. If the value at the `mid` index is greater than or equal to `target`, move the `right` pointer to `mid - 1`. If the value at the `mid` index is equal to `target`, update `start` with `mid`.
4. Reset `left` and `right` pointers to the beginning and end of the `nums` array.
5. Loop again until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is greater than `target`, move the `right` pointer to `mid - 1`.
   c. If the value at the `mid` index is smaller than or equal to `target`, move the `left` pointer to `mid + 1`. If the value at the `mid` index is equal to `target`, update `end` with `mid`.
6. Return the resulting `start` and `end` values as an array/list.

## A solution in Python

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

    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
            if nums[mid] == target:
                start = mid

    left, right = 0, len(nums) - 1

    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] > target:right = mid - 1
        else:
            left = mid + 1
            if nums[mid] == target:
                end = mid

    return [start, end]
```
1. Initialize `start` and `end` variables to -1 as default return values.
2. Setup `left` and `right` pointers at the beginning and end of the `nums` array.
3. Loop until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is smaller than `target`, move the `left` pointer to `mid + 1`.
   c. If the value at the `mid` index is greater than or equal to `target`, move the `right` pointer to `mid - 1`. If the value at the `mid` index is equal to `target`, update `start` with `mid`.
4. Reset `left` and `right` pointers to the beginning and end of the `nums` array.
5. Loop again until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is greater than `target`, move the `right` pointer to `mid - 1`.
   c. If the value at the `mid` index is smaller than or equal to `target`, move the `left` pointer to `mid + 1`. If the value at the `mid` index is equal to `target`, update `end` with `mid`.
6. Return the resulting `start` and `end` values as an array/list.

## A solution in Javascript

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

    while (left <= right) {
        const mid = left + Math.floor((right - left) / 2);
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
            if (nums[mid] === target) {
                start = mid;
            }
        }
    }

    left = 0;
    right = nums.length - 1;

    while (left <= right) {
        const mid = left + Math.floor((right - left) / 2);
        if (nums[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
            if (nums[mid] === target) {
                end = mid;
            }
        }
    }

    return [start, end];
}
```
1. Initialize `start` and `end` variables to -1 as default return values.
2. Setup `left` and `right` pointers at the beginning and end of the `nums` array.
3. Loop until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is smaller than `target`, move the `left` pointer to `mid + 1`.
   c. If the value at the `mid` index is greater than or equal to `target`, move the `right` pointer to `mid - 1`. If the value at the `mid` index is equal to `target`, update `start` with `mid`.
4. Reset `left` and `right` pointers to the beginning and end of the `nums` array.
5. Loop again until `left` is greater than `right`:
   a. Calculate the `mid` index.
   b. If the value at the `mid` index is greater than `target`, move the `right` pointer to `mid - 1`.
   c. If the value at the `mid` index is smaller than or equal to `target`, move the `left` pointer to `mid + 1`. If the value at the `mid` index is equal to `target`, update `end` with `mid`.
6. Return the resulting `start` and `end` values as an array/list.


# Search Insert Position

- slug: search-insert-position
- difficulty: Easy

Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You must write an algorithm with `O(log n)` runtime complexity.

**Example 1:**

**Input:** nums = \[1,3,5,6\], target = 5
**Output:** 2

**Example 2:**

**Input:** nums = \[1,3,5,6\], target = 2
**Output:** 1

**Example 3:**

**Input:** nums = \[1,3,5,6\], target = 7
**Output:** 4

**Constraints:**

*   `1 <= nums.length <= 104`
*   `-104 <= nums[i] <= 104`
*   `nums` contains **distinct** values sorted in **ascending** order.
*   `-104 <= target <= 104`

## A solution in Java

```java
public int searchInsert(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return left;
}
```
The given problem requires a binary search algorithm. We define two pointers, `left` and `right`, initially set to the first and last index of the array. We then enter a loop that continues as long as left is less than or equal to right. Inside the loop, we calculate the middle index, `mid`, as the average of left and right. If the value at this middle index is equal to the target value, we return the middle index. If the middle value is less than the target value, we set left to `mid + 1`, meaning we search the right half of the remaining array. If the middle value is greater than the target value, we set the right to `mid - 1`, meaning we search the left half of the remaining array. After the loop, if the target value is not found, we return the value of the left pointer, which represents the index where the target value should be inserted.

## A solution in C++

```cpp
int searchInsert(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return left;
}
```
The given problem requires a binary search algorithm. We define two pointers, `left` and `right`, initially set to the first and last index of the array. We then enter a loop that continues as long as left is less than or equal to right. Inside the loop, we calculate the middle index, `mid`, as the average of left and right. If the value at this middle index is equal to the target value, we return the middle index. If the middle value is less than the target value, we set left to `mid + 1`, meaning we search the right half of the remaining array. If the middle value is greater than the target value, we set the right to `mid - 1`, meaning we search the left half of the remaining array. After the loop, if the target value is not found, we return the value of the left pointer, which represents the index where the target value should be inserted.

## A solution in Python

```python
def searchInsert(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return left
```
The given problem requires a binary search algorithm. We define two pointers, `left` and `right`, initially set to the first and last index of the array. We then enter a loop that continues as long as left is less than or equal to right. Inside the loop, we calculate the middle index, `mid`, as the average of left and right. If the value at this middle index is equal to the target value, we return the middle index. If the middle value is less than the target value, we set left to `mid + 1`, meaning we search the right half of the remaining array. If the middle value is greater than the target value, we set the right to `mid - 1`, meaning we search the left half of the remaining array. After the loop, if the target value is not found, we return the value of the left pointer, which represents the index where the target value should be inserted.

## A solution in Javascript

```javascript
function searchInsert(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2);
        if (nums[mid] === target) return mid;
        if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return left;
}
```
The given problem requires a binary search algorithm. We define two pointers, `left` and `right`, initially set to the first and last index of the array. We then enter a loop that continues as long as left is less than or equal to right. Inside the loop, we calculate the middle index, `mid`, as the average of left and right. If the value at this middle index is equal to the target value, we return the middle index. If the middle value is less than the target value, we set left to `mid + 1`, meaning we search the right half of the remaining array. If the middle value is greater than the target value, we set the right to `mid - 1`, meaning we search the left half of the remaining array. After the loop, if the target value is not found, we return the value of the left pointer, which represents the index where the target value should be inserted.


# Count and Say

- slug: count-and-say
- difficulty: Medium

The **count-and-say** sequence is a sequence of digit strings defined by the recursive formula:

*   `countAndSay(1) = "1 "`
*   `countAndSay(n)` is the way you would "say " the digit string from `countAndSay(n-1)`, which is then converted into a different digit string.

To determine how you "say " a digit string, split it into the **minimal** number of substrings such that each substring contains exactly **one** unique digit. Then for each substring, say the number of digits, then say the digit. Finally, concatenate every said digit.

For example, the saying and conversion for digit string `"3322251 "`:

Given a positive integer `n`, return _the_ `nth` _term of the **count-and-say** sequence_.

**Example 1:**

**Input:** n = 1
**Output:**  "1 "
**Explanation:** This is the base case.

**Example 2:**

**Input:** n = 4
**Output:**  "1211 "
**Explanation:**
countAndSay(1) =  "1 "
countAndSay(2) = say  "1 " = one 1 =  "11 "
countAndSay(3) = say  "11 " = two 1's =  "21 "
countAndSay(4) = say  "21 " = one 2 + one 1 =  "12 " +  "11 " =  "1211 "

**Constraints:**

*   `1 <= n <= 30`

## A solution in Java

```java
public String countAndSay(int n) {
    if (n == 1) return "1";
    String previous = countAndSay(n-1);
    StringBuilder result = new StringBuilder();
    int count = 1;
    for (int i = 1; i < previous.length(); i++) {
        if (previous.charAt(i) == previous.charAt(i-1)) {
            count++;
        } else {
            result.append(count).append(previous.charAt(i-1));
            count = 1;
        }
    }
    result.append(count).append(previous.charAt(previous.length()-1));
    return result.toString();
}
```
The algorithm is a recursive solution. It starts with the base case, when `n` is 1, it returns the first term of the sequence "1". In other cases, it makes a recursive call to the function with `n-1` to get the previous term in the sequence. Then it iterates through the previous term, comparing each character with the previous one to count the number of consecutive equal digits. When it encounters a different character, it appends the count and the character to the result string and resets the count to 1. Finally, it appends the last count and character to the result string and returns it.

## A solution in C++

```cpp
#include <string>

std::string countAndSay(int n) {
    if (n == 1) return "1";
    std::string previous = countAndSay(n-1);
    std::string result = "";
    int count = 1;
    for (int i = 1; i < previous.length(); i++) {
        if (previous[i] == previous[i-1]) {
            count++;
        } else {
            result += std::to_string(count) + previous[i-1];
            count = 1;
        }
    }
    result += std::to_string(count) + previous.back();
    return result;
}
```
The algorithm is a recursive solution. It starts with the base case, when `n` is 1, it returns the first term of the sequence "1". In other cases, it makes a recursive call to the function with `n-1` to get the previous term in the sequence. Then it iterates through the previous term, comparing each character with the previous one to count the number of consecutive equal digits. When it encounters a different character, it appends the count and the character to the result string and resets the count to 1. Finally, it appends the last count and character to the result string and returns it.

## A solution in Python

```python
def count_and_say(n):
    if n == 1:
        return "1"
    previous = count_and_say(n - 1)
    result = []
    count = 1
    for i in range(1, len(previous)):
        if previous[i] == previous[i - 1]:
            count += 1
        else:
            result.append(str(count))
            result.append(previous[i - 1])
            count = 1
    result.append(str(count))
    result.append(previous[-1])
    return "".join(result)
```
The algorithm is a recursive solution. It starts with the base case, when `n` is 1, it returns the first term of the sequence "1". In other cases, it makes a recursive call to the function with `n-1` to get the previous term in the sequence. Then it iterates through the previous term, comparing each character with the previous one to count the number of consecutive equal digits. When it encounters a different character, it appends the count and the character to the result string and resets the count to 1. Finally, it appends the last count and character to the result string and returns it.

## A solution in Javascript

```javascript
function countAndSay(n) {
    if (n === 1) return "1";
    let previous = countAndSay(n - 1);
    let result = "";
    let count = 1;
    for (let i = 1; i < previous.length; i++) {
        if (previous[i] === previous[i - 1]) {
            count++;
        } else {
            result += count.toString() + previous[i - 1];
            count = 1;
        }
    }
    result += count.toString() + previous[previous.length - 1];
    return result;
}
```
The algorithm is a recursive solution. It starts with the base case, when `n` is 1, it returns the first term of the sequence "1". In other cases, it makes a recursive call to the function with `n-1` to get the previous term in the sequence. Then it iterates through the previous term, comparing each character with the previous one to count the number of consecutive equal digits. When it encounters a different character, it appends the count and the character to the result string and resets the count to 1. Finally, it appends the last count and character to the result string and returns it.


# Combination Sum

- slug: combination-sum
- difficulty: Medium

Given an array of **distinct** integers `candidates` and a target integer `target`, return _a list of all **unique combinations** of_ `candidates` _where the chosen numbers sum to_ `target`_._ You may return the combinations in **any order**.

The **same** number may be chosen from `candidates` an **unlimited number of times**. Two combinations are unique if the frequency of at least one of the chosen numbers is different.

The test cases are generated such that the number of unique combinations that sum up to `target` is less than `150` combinations for the given input.

**Example 1:**

**Input:** candidates = \[2,3,6,7\], target = 7
**Output:** \[\[2,2,3\],\[7\]\]
**Explanation:**
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
These are the only two combinations.

**Example 2:**

**Input:** candidates = \[2,3,5\], target = 8
**Output:** \[\[2,2,2,2\],\[2,3,3\],\[3,5\]\]

**Example 3:**

**Input:** candidates = \[2\], target = 1
**Output:** \[\]

**Constraints:**

*   `1 <= candidates.length <= 30`
*   `2 <= candidates[i] <= 40`
*   All elements of `candidates` are **distinct**.
*   `1 <= target <= 40`

## A solution in Java

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

public List<List<Integer>> combinationSum(int[] candidates, int target) {
    List<List<Integer>> result = new ArrayList<>();
    findCombinations(candidates, target, 0, new ArrayList<>(), result);
    return result;
}

private void findCombinations(int[] candidates, int target, int startIndex, List<Integer> current, List<List<Integer>> result) {
    if (target == 0) {
        result.add(new ArrayList<>(current));
        return;
    }
    if (startIndex == candidates.length || target < 0) {
        return;
    }

    findCombinations(candidates, target, startIndex + 1, current, result);

    current.add(candidates[startIndex]);
    findCombinations(candidates, target - candidates[startIndex], startIndex, current, result);
    current.remove(current.size() - 1);
}
```
The algorithm is a recursive backtracking algorithm. We define a helper function `findCombinations` that takes the following parameters:

1. `startIndex`: the index of the candidates array from which it can start choosing numbers.
2. `remaining`: the remaining sum needed to reach the target.

The base cases are:
- If `remaining` is 0, it means we have found a valid combination, so we return a list containing an empty list.
- If `startIndex` is equal to the length of candidates, or `remaining` is negative, there are no valid combinations, so we return an empty list.

In the function, we first initialize an empty list called `result`. Then, we make two recursive calls to `findCombinations`:

1. Excluding the current candidate at `startIndex` and incrementing `startIndex`, to search for combinations without this candidate.
2. Including the current candidate in the combination, and decreasing `remaining` accordingly (without updating `startIndex`).

After getting results from both recursive calls, we merge them and return the final list of combinations.

The main function `combinationSum` calls `findCombinations` with `startIndex` as 0 and `remaining` as the target, and returns the result after the recursion is done.

## A solution in C++

```cpp
#include <vector>

void findCombinations(std::vector<int>& candidates, int target, int startIndex, std::vector<int>& current, std::vector<std::vector<int>>& result) {
    if (target == 0) {
        result.push_back(current);
        return;
    }
    if (startIndex == candidates.size() || target < 0) {
        return;
    }

    findCombinations(candidates, target, startIndex + 1, current, result);

    current.push_back(candidates[startIndex]);
    findCombinations(candidates, target - candidates[startIndex], startIndex, current, result);
    current.pop_back();
}

std::vector<std::vector<int>> combinationSum(std::vector<int>& candidates, int target) {
    std::vector<int> current;
    std::vector<std::vector<int>> result;
    findCombinations(candidates, target, 0, current, result);
    return result;
}
```
The algorithm is a recursive backtracking algorithm. We define a helper function `findCombinations` that takes the following parameters:

1. `startIndex`: the index of the candidates array from which it can start choosing numbers.
2. `remaining`: the remaining sum needed to reach the target.

The base cases are:
- If `remaining` is 0, it means we have found a valid combination, so we return a list containing an empty list.
- If `startIndex` is equal to the length of candidates, or `remaining` is negative, there are no valid combinations, so we return an empty list.

In the function, we first initialize an empty list called `result`. Then, we make two recursive calls to `findCombinations`:

1. Excluding the current candidate at `startIndex` and incrementing `startIndex`, to search for combinations without this candidate.
2. Including the current candidate in the combination, and decreasing `remaining` accordingly (without updating `startIndex`).

After getting results from both recursive calls, we merge them and return the final list of combinations.

The main function `combinationSum` calls `findCombinations` with `startIndex` as 0 and `remaining` as the target, and returns the result after the recursion is done.

## A solution in Python

```python
def combinationSum(candidates, target):
    def findCombinations(startIndex, remaining):
        if remaining == 0:
            return [[]]
        if startIndex == len(candidates) or remaining < 0:
            return []

        result = []
        result.extend(findCombinations(startIndex + 1, remaining))
        result.extend([x + [candidates[startIndex]] for x in findCombinations(startIndex, remaining - candidates[startIndex])])

        return result

    return findCombinations(0, target)
```
The algorithm is a recursive backtracking algorithm. We define a helper function `findCombinations` that takes the following parameters:

1. `startIndex`: the index of the candidates array from which it can start choosing numbers.
2. `remaining`: the remaining sum needed to reach the target.

The base cases are:
- If `remaining` is 0, it means we have found a valid combination, so we return a list containing an empty list.
- If `startIndex` is equal to the length of candidates, or `remaining` is negative, there are no valid combinations, so we return an empty list.

In the function, we first initialize an empty list called `result`. Then, we make two recursive calls to `findCombinations`:

1. Excluding the current candidate at `startIndex` and incrementing `startIndex`, to search for combinations without this candidate.
2. Including the current candidate in the combination, and decreasing `remaining` accordingly (without updating `startIndex`).

After getting results from both recursive calls, we merge them and return the final list of combinations.

The main function `combinationSum` calls `findCombinations` with `startIndex` as 0 and `remaining` as the target, and returns the result after the recursion is done.

## A solution in Javascript

```javascript
function combinationSum(candidates, target) {
    function findCombinations(startIndex, remaining) {
        if (remaining === 0) {
            return [[]];
        }
        if (startIndex === candidates.length || remaining < 0) {
            return [];
        }

        let result = [];
        result = result.concat(findCombinations(startIndex + 1, remaining));
        result = result.concat(findCombinations(startIndex, remaining - candidates[startIndex]).map(x => x.concat([candidates[startIndex]])));

        return result;
    }

    return findCombinations(0, target);
}
```
The algorithm is a recursive backtracking algorithm. We define a helper function `findCombinations` that takes the following parameters:

1. `startIndex`: the index of the candidates array from which it can start choosing numbers.
2. `remaining`: the remaining sum needed to reach the target.

The base cases are:
- If `remaining` is 0, it means we have found a valid combination, so we return a list containing an empty list.
- If `startIndex` is equal to the length of candidates, or `remaining` is negative, there are no valid combinations, so we return an empty list.

In the function, we first initialize an empty list called `result`. Then, we make two recursive calls to `findCombinations`:

1. Excluding the current candidate at `startIndex` and incrementing `startIndex`, to search for combinations without this candidate.
2. Including the current candidate in the combination, and decreasing `remaining` accordingly (without updating `startIndex`).

After getting results from both recursive calls, we merge them and return the final list of combinations.

The main function `combinationSum` calls `findCombinations` with `startIndex` as 0 and `remaining` as the target, and returns the result after the recursion is done.


# Combination Sum II

- slug: combination-sum-ii
- difficulty: Medium

Given a collection of candidate numbers (`candidates`) and a target number (`target`), find all unique combinations in `candidates` where the candidate numbers sum to `target`.

Each number in `candidates` may only be used **once** in the combination.

**Note:** The solution set must not contain duplicate combinations.

**Example 1:**

**Input:** candidates = \[10,1,2,7,6,1,5\], target = 8
**Output:**
\[
\[1,1,6\],
\[1,2,5\],
\[1,7\],
\[2,6\]
\]

**Example 2:**

**Input:** candidates = \[2,5,2,1,2\], target = 5
**Output:**
\[
\[1,2,2\],
\[5\]
\]

**Constraints:**

*   `1 <= candidates.length <= 100`
*   `1 <= candidates[i] <= 50`
*   `1 <= target <= 30`

## A solution in Java

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

public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    List<List<Integer>> result = new ArrayList<>();
    Arrays.sort(candidates);
    combine(candidates, target, 0, result, new ArrayList<Integer>());
    return result;
}

private void combine(int[] candidates, int target, int start, List<List<Integer>> result, List<Integer> current) {
    if (target == 0) {
        result.add(new ArrayList<>(current));
        return;
    }

    for (int i = start; i < candidates.length && target >= candidates[i]; i++) {
        if (i == start || candidates[i] != candidates[i - 1]) {
            current.add(candidates[i]);
            combine(candidates, target - candidates[i], i + 1, result, current);
            current.remove(current.size() - 1);
        }
    }
}
```
The algorithm uses a backtracking approach to find all possible combinations. It starts by sorting the input `candidates` array/list. Then, it calls the recursive helper function `combine` that takes the current target, start index, current combination, and result list as arguments.

1. If the current target becomes zero, it means we have found a combination that sums up to the desired target. Add the current combination to the result list and return.
2. Iterate through the `candidates` list starting from the given index.
   - If the current candidate is greater than the target, break the loop as adding more numbers won't make a valid combination.
   - Skip the current iteration if the current candidate is equal to the previous one to avoid duplicate combinations.
   - Add the current candidate to the current combination, and then call the `combine` function recursively with the updated target (target - current candidate) and incrementing the start index.
   - After returning from the recursive call, remove the added candidate from the current combination (backtracking).

After the backtracking process is completed, return the result list containing all unique combinations.

## A solution in C++

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

void combine(std::vector<int>& candidates, int target, std::vector<std::vector<int>>& result, std::vector<int>& combination, int index) {
    if (target == 0) {
        result.push_back(combination);
        return;
    }

    for (int i = index; i < candidates.size() && target >= candidates[i]; ++i) {
        if (i == index || candidates[i] != candidates[i - 1]) {
            combination.push_back(candidates[i]);
            combine(candidates, target - candidates[i], result, combination, i + 1);
            combination.pop_back();
        }
    }
}

std::vector<std::vector<int>> combinationSum2(std::vector<int>& candidates, int target) {
    std::vector<std::vector<int>> result;
    std::vector<int> combination;
    std::sort(candidates.begin(), candidates.end());
    combine(candidates, target, result, combination, 0);
    return result;
}
```
The algorithm uses a backtracking approach to find all possible combinations. It starts by sorting the input `candidates` array/list. Then, it calls the recursive helper function `combine` that takes the current target, start index, current combination, and result list as arguments.

1. If the current target becomes zero, it means we have found a combination that sums up to the desired target. Add the current combination to the result list and return.
2. Iterate through the `candidates` list starting from the given index.
   - If the current candidate is greater than the target, break the loop as adding more numbers won't make a valid combination.
   - Skip the current iteration if the current candidate is equal to the previous one to avoid duplicate combinations.
   - Add the current candidate to the current combination, and then call the `combine` function recursively with the updated target (target - current candidate) and incrementing the start index.
   - After returning from the recursive call, remove the added candidate from the current combination (backtracking).

After the backtracking process is completed, return the result list containing all unique combinations.

## A solution in Python

```python
def combinationSum2(candidates, target):
    def combine(candidates, target, start, path, res):
        if target == 0:
            res.append(path)
            return
        for i in range(start, len(candidates)):
            if i > start and candidates[i] == candidates[i - 1]:
                continue
            if candidates[i] > target:
                break
            combine(candidates, target - candidates[i], i+1, path + [candidates[i]], res)

    candidates.sort()
    res = []
    combine(candidates, target, 0, [], res)
    return res
```
The algorithm uses a backtracking approach to find all possible combinations. It starts by sorting the input `candidates` array/list. Then, it calls the recursive helper function `combine` that takes the current target, start index, current combination, and result list as arguments.

1. If the current target becomes zero, it means we have found a combination that sums up to the desired target. Add the current combination to the result list and return.
2. Iterate through the `candidates` list starting from the given index.
   - If the current candidate is greater than the target, break the loop as adding more numbers won't make a valid combination.
   - Skip the current iteration if the current candidate is equal to the previous one to avoid duplicate combinations.
   - Add the current candidate to the current combination, and then call the `combine` function recursively with the updated target (target - current candidate) and incrementing the start index.
   - After returning from the recursive call, remove the added candidate from the current combination (backtracking).

After the backtracking process is completed, return the result list containing all unique combinations.

## A solution in Javascript

```javascript
function combinationSum2(candidates, target) {
    const result = [];
    candidates.sort((a, b) => a - b);
    combine(candidates, target, 0, [], result);
    return result;
}

function combine(candidates, target, start, current, result) {
    if (target === 0) {
        result.push([...current]);
        return;
    }

    for (let i = start; i < candidates.length && target >= candidates[i]; i++) {
        if (i === start || candidates[i] !== candidates[i - 1]) {
            current.push(candidates[i]);
            combine(candidates, target - candidates[i], i + 1, current, result);
            current.pop();
        }
    }
}
```
The algorithm uses a backtracking approach to find all possible combinations. It starts by sorting the input `candidates` array/list. Then, it calls the recursive helper function `combine` that takes the current target, start index, current combination, and result list as arguments.

1. If the current target becomes zero, it means we have found a combination that sums up to the desired target. Add the current combination to the result list and return.
2. Iterate through the `candidates` list starting from the given index.
   - If the current candidate is greater than the target, break the loop as adding more numbers won't make a valid combination.
   - Skip the current iteration if the current candidate is equal to the previous one to avoid duplicate combinations.
   - Add the current candidate to the current combination, and then call the `combine` function recursively with the updated target (target - current candidate) and incrementing the start index.
   - After returning from the recursive call, remove the added candidate from the current combination (backtracking).

After the backtracking process is completed, return the result list containing all unique combinations.


# First Missing Positive

- slug: first-missing-positive
- difficulty: Hard

Given an unsorted integer array `nums`, return the smallest missing positive integer.

You must implement an algorithm that runs in `O(n)` time and uses constant extra space.

**Example 1:**

**Input:** nums = \[1,2,0\]
**Output:** 3
**Explanation:** The numbers in the range \[1,2\] are all in the array.

**Example 2:**

**Input:** nums = \[3,4,-1,1\]
**Output:** 2
**Explanation:** 1 is in the array but 2 is missing.

**Example 3:**

**Input:** nums = \[7,8,9,11,12\]
**Output:** 1
**Explanation:** The smallest positive integer 1 is missing.

**Constraints:**

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

## A solution in Java

```java
public int firstMissingPositive(int[] nums) {
    int n = nums.length;
    for(int i = 0; i < n; i++) {
        while(nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
            int temp = nums[i];
            nums[i] = nums[temp - 1];
            nums[temp - 1] = temp;
        }
    }

    for(int i = 0; i < n; i++) {
        if(nums[i] != i + 1) {
            return i + 1;
        }
    }
    return n + 1;
}
```
In this algorithm, the elements are swapped with the values at their correct index if they are positive, in range, and not equal to the value already at that index. After the first loop, the array will have correct values at correct indices where possible (1-based), so we just need to find the index `i` where `nums[i] != i+1`. If not found, return the next positive integer `n + 1`. The loop has O(n) complexity, because each time at least one element gets placed at its correct position, so we need a max of n iterations on average.

## A solution in C++

```cpp
int firstMissingPositive(vector<int>& nums) {
    int n = nums.size();
    for(int i = 0; i < n; ++i)
        while(nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i])
            swap(nums[i], nums[nums[i] - 1]);

    for(int i = 0; i < n; ++i)
        if(nums[i] != i + 1)
            return i + 1;
    return n + 1;
}
```
In this algorithm, the elements are swapped with the values at their correct index if they are positive, in range, and not equal to the value already at that index. After the first loop, the array will have correct values at correct indices where possible (1-based), so we just need to find the index `i` where `nums[i] != i+1`. If not found, return the next positive integer `n + 1`. The loop has O(n) complexity, because each time at least one element gets placed at its correct position, so we need a max of n iterations on average.

## A solution in Python

```python
def firstMissingPositive(nums):
    n = len(nums)
    for i in range(n):
        while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
            nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]

    for i in range(n):
        if nums[i] != i + 1:
            return i + 1
    return n + 1
```
In this algorithm, the elements are swapped with the values at their correct index if they are positive, in range, and not equal to the value already at that index. After the first loop, the array will have correct values at correct indices where possible (1-based), so we just need to find the index `i` where `nums[i] != i+1`. If not found, return the next positive integer `n + 1`. The loop has O(n) complexity, because each time at least one element gets placed at its correct position, so we need a max of n iterations on average.

## A solution in Javascript

```javascript
function firstMissingPositive(nums) {
    let n = nums.length;
    for(let i = 0; i < n; i++) {
        while(nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {
            let temp = nums[i];
            nums[i] = nums[temp - 1];
            nums[temp - 1] = temp;
        }
    }

    for(let i = 0; i < n; i++) {
        if(nums[i] !== i + 1) {
            return i + 1;
        }
    }
    return n + 1;
}
```
In this algorithm, the elements are swapped with the values at their correct index if they are positive, in range, and not equal to the value already at that index. After the first loop, the array will have correct values at correct indices where possible (1-based), so we just need to find the index `i` where `nums[i] != i+1`. If not found, return the next positive integer `n + 1`. The loop has O(n) complexity, because each time at least one element gets placed at its correct position, so we need a max of n iterations on average.


# Trapping Rain Water

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

Given `n` non-negative integers representing an elevation map where the width of each bar is `1`, compute how much water it can trap after raining.

**Example 1:**

**Input:** height = \[0,1,0,2,1,0,1,3,2,1,2,1\]
**Output:** 6
**Explanation:** The above elevation map (black section) is represented by array \[0,1,0,2,1,0,1,3,2,1,2,1\]. In this case, 6 units of rain water (blue section) are being trapped.

**Example 2:**

**Input:** height = \[4,2,0,3,2,5\]
**Output:** 9

**Constraints:**

*   `n == height.length`
*   `1 <= n <= 2 * 104`
*   `0 <= height[i] <= 105`

## A solution in Java

```java
public int trap(int[] height) {
    int n = height.length, left = 0, right = n - 1, maxLeft = 0, maxRight = 0, water = 0;

    while (left < right) {
        if (height[left] <= height[right]) {
            maxLeft = Math.max(maxLeft, height[left]);
            water += maxLeft - height[left];
            left++;
        } else {
            maxRight = Math.max(maxRight, height[right]);
            water += maxRight - height[right];
            right--;
        }
    }

    return water;
}
```
The algorithm uses a two-pointer approach, initializing left and right pointers to the beginning and end of the elevation map, respectively. It also initializes two variables `maxLeft` and `maxRight` to keep track of the maximum heights on the left and right of the pointers, as well as a variable `water` to store the trapped water.

The algorithm iterates through the elevation map until the left pointer is less than the right pointer. In each iteration, it compares the values at both pointers to determine which side is shorter. If the value at the left pointer is less than or equal to the value at the right pointer, it means water can be trapped on the left side up to the height of the shorter bar. The algorithm updates `maxLeft` with the maximum height on the left side and then adds the trapped water (which is the difference between the maximum height and the current height) to the `water` variable. The left pointer is then incremented. If the value at the right pointer is smaller, the same logic is applied to the right side and the right pointer is decremented.

This process is repeated until the left pointer is no longer less than the right pointer, at which point the total trapped water has been calculated and the `water` variable is returned. This algorithm has a time complexity of O(n) and a space complexity of O(1) as it only uses constant extra space.

## A solution in C++

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

int trap(vector<int>& height) {
    int n = height.size();
    int left = 0, right = n - 1, maxLeft = 0, maxRight = 0, water = 0;

    while (left < right) {
        if (height[left] <= height[right]) {
            maxLeft = max(maxLeft, height[left]);
            water += maxLeft - height[left];
            left++;
        } else {
            maxRight = max(maxRight, height[right]);
            water += maxRight - height[right];
            right--;
        }
    }

    return water;
}
```
The algorithm uses a two-pointer approach, initializing left and right pointers to the beginning and end of the elevation map, respectively. It also initializes two variables `maxLeft` and `maxRight` to keep track of the maximum heights on the left and right of the pointers, as well as a variable `water` to store the trapped water.

The algorithm iterates through the elevation map until the left pointer is less than the right pointer. In each iteration, it compares the values at both pointers to determine which side is shorter. If the value at the left pointer is less than or equal to the value at the right pointer, it means water can be trapped on the left side up to the height of the shorter bar. The algorithm updates `maxLeft` with the maximum height on the left side and then adds the trapped water (which is the difference between the maximum height and the current height) to the `water` variable. The left pointer is then incremented. If the value at the right pointer is smaller, the same logic is applied to the right side and the right pointer is decremented.

This process is repeated until the left pointer is no longer less than the right pointer, at which point the total trapped water has been calculated and the `water` variable is returned. This algorithm has a time complexity of O(n) and a space complexity of O(1) as it only uses constant extra space.

## A solution in Python

```python
def trap(height):
    n = len(height)
    left, right, max_left, max_right, water = 0, n - 1, 0, 0, 0

    while left < right:
        if height[left] <= height[right]:
            max_left = max(max_left, height[left])
            water += max_left - height[left]
            left += 1
        else:
            max_right = max(max_right, height[right])
            water += max_right - height[right]
            right -= 1

    return water
```
The algorithm uses a two-pointer approach, initializing left and right pointers to the beginning and end of the elevation map, respectively. It also initializes two variables `maxLeft` and `maxRight` to keep track of the maximum heights on the left and right of the pointers, as well as a variable `water` to store the trapped water.

The algorithm iterates through the elevation map until the left pointer is less than the right pointer. In each iteration, it compares the values at both pointers to determine which side is shorter. If the value at the left pointer is less than or equal to the value at the right pointer, it means water can be trapped on the left side up to the height of the shorter bar. The algorithm updates `maxLeft` with the maximum height on the left side and then adds the trapped water (which is the difference between the maximum height and the current height) to the `water` variable. The left pointer is then incremented. If the value at the right pointer is smaller, the same logic is applied to the right side and the right pointer is decremented.

This process is repeated until the left pointer is no longer less than the right pointer, at which point the total trapped water has been calculated and the `water` variable is returned. This algorithm has a time complexity of O(n) and a space complexity of O(1) as it only uses constant extra space.

## A solution in Javascript

```javascript
function trap(height) {
    const n = height.length;
    let left = 0, right = n - 1, maxLeft = 0, maxRight = 0, water = 0;

    while (left < right) {
        if (height[left] <= height[right]) {
            maxLeft = Math.max(maxLeft, height[left]);
            water += maxLeft - height[left];
            left++;
        } else {
            maxRight = Math.max(maxRight, height[right]);
            water += maxRight - height[right];
            right--;
        }
    }

    return water;
}
```
The algorithm uses a two-pointer approach, initializing left and right pointers to the beginning and end of the elevation map, respectively. It also initializes two variables `maxLeft` and `maxRight` to keep track of the maximum heights on the left and right of the pointers, as well as a variable `water` to store the trapped water.

The algorithm iterates through the elevation map until the left pointer is less than the right pointer. In each iteration, it compares the values at both pointers to determine which side is shorter. If the value at the left pointer is less than or equal to the value at the right pointer, it means water can be trapped on the left side up to the height of the shorter bar. The algorithm updates `maxLeft` with the maximum height on the left side and then adds the trapped water (which is the difference between the maximum height and the current height) to the `water` variable. The left pointer is then incremented. If the value at the right pointer is smaller, the same logic is applied to the right side and the right pointer is decremented.

This process is repeated until the left pointer is no longer less than the right pointer, at which point the total trapped water has been calculated and the `water` variable is returned. This algorithm has a time complexity of O(n) and a space complexity of O(1) as it only uses constant extra space.


# Multiply Strings

- slug: multiply-strings
- difficulty: Medium

Given two non-negative integers `num1` and `num2` represented as strings, return the product of `num1` and `num2`, also represented as a string.

**Note:** You must not use any built-in BigInteger library or convert the inputs to integer directly.

**Example 1:**

**Input:** num1 = "2", num2 = "3"
**Output:** "6"

**Example 2:**

**Input:** num1 = "123", num2 = "456"
**Output:** "56088"

**Constraints:**

*   `1 <= num1.length, num2.length <= 200`
*   `num1` and `num2` consist of digits only.
*   Both `num1` and `num2` do not contain any leading zero, except the number `0` itself.

## A solution in Java

```java
public String multiply(String num1, String num2) {
    int m = num1.length(), n = num2.length();
    int[] pos = new int[m + n];

    for (int i = m - 1; i >= 0; i--) {
        for (int j = n - 1; j >= 0; j--) {
            int mult = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
            int p1 = i + j, p2 = i + j + 1;
            int sum = mult + pos[p2];
            pos[p1] += sum / 10;
            pos[p2] = sum % 10;
        }
    }

    StringBuilder res = new StringBuilder();
    for (int p : pos) if (!(res.length() == 0 && p == 0)) res.append(p);
    return res.length() == 0 ? "0" : res.toString();
}
```
The algorithm follows a typical multiplication method where each digit of both numbers is multiplied pairwise, with the correct position shifted as you move through the digits. Then, the products of these digits are combined to form the final result.

1. Initialize an array `pos` to store the intermediate results, with a size equal to the sum of the lengths of both input strings.
2. Run two nested loops for each digit of both input numbers (from right to left).
3. Calculate the product of the two digits.
4. Determine the indices to store the product values in the `pos` array, e.g., in the form of tens and units.
5. Update the `pos` array with the new product values.
6. Combine the values in the `pos` array to form the final result string.

The time complexity is O(m*n) where `m` and `n` are the lengths of the input strings, `num1` and `num2`. The space complexity is also O(m+n).

## A solution in C++

```cpp
string multiply(string num1, string num2) {
    int m = num1.size(), n = num2.size();
    string res(m + n, '0');
    for (int i = m - 1; i >= 0; i--) {
        for (int j = n - 1; j >= 0; j--) {
            int p1 = i + j, p2 = i + j + 1;
            int mult = (num1[i] - '0') * (num2[j] - '0') + (res[p2] - '0');
            res[p1] += mult / 10;
            res[p2] = (mult % 10) + '0';
        }
    }
    while (res.size() > 1 && res[0] == '0')
        res.erase(res.begin());
    return res;
}
```
The algorithm follows a typical multiplication method where each digit of both numbers is multiplied pairwise, with the correct position shifted as you move through the digits. Then, the products of these digits are combined to form the final result.

1. Initialize an array `pos` to store the intermediate results, with a size equal to the sum of the lengths of both input strings.
2. Run two nested loops for each digit of both input numbers (from right to left).
3. Calculate the product of the two digits.
4. Determine the indices to store the product values in the `pos` array, e.g., in the form of tens and units.
5. Update the `pos` array with the new product values.
6. Combine the values in the `pos` array to form the final result string.

The time complexity is O(m*n) where `m` and `n` are the lengths of the input strings, `num1` and `num2`. The space complexity is also O(m+n).

## A solution in Python

```python
def multiply(num1, num2):
    m, n = len(num1), len(num2)
    pos = [0] * (m + n)

    for i in range(m-1, -1, -1):
        for j in range(n-1, -1, -1):
            mult = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0'))
            p1, p2 = i + j, i + j + 1
            total_pos = mult + pos[p2]
            pos[p1] += total_pos // 10
            pos[p2] = total_pos % 10

    res = ''.join(str(p) for p in pos if not (len(res) == 0 and p == 0))
    return '0' if len(res) == 0 else res
```
The algorithm follows a typical multiplication method where each digit of both numbers is multiplied pairwise, with the correct position shifted as you move through the digits. Then, the products of these digits are combined to form the final result.

1. Initialize an array `pos` to store the intermediate results, with a size equal to the sum of the lengths of both input strings.
2. Run two nested loops for each digit of both input numbers (from right to left).
3. Calculate the product of the two digits.
4. Determine the indices to store the product values in the `pos` array, e.g., in the form of tens and units.
5. Update the `pos` array with the new product values.
6. Combine the values in the `pos` array to form the final result string.

The time complexity is O(m*n) where `m` and `n` are the lengths of the input strings, `num1` and `num2`. The space complexity is also O(m+n).

## A solution in Javascript

```javascript
function multiply(num1, num2) {
    let m = num1.length, n = num2.length;
    let pos = new Array(m + n).fill(0);

    for (let i = m - 1; i >= 0; i--) {
        for (let j = n - 1; j >= 0; j--) {
            let mult = (num1[i] - '0') * (num2[j] - '0');
            let p1 = i + j, p2 = i + j + 1;
            let sum = mult + pos[p2];
            pos[p1] += Math.floor(sum / 10);
            pos[p2] = sum % 10;
        }
    }

    while (pos.length > 1 && pos[0] == 0)
        pos.shift();
    return pos.join('');
}
```
The algorithm follows a typical multiplication method where each digit of both numbers is multiplied pairwise, with the correct position shifted as you move through the digits. Then, the products of these digits are combined to form the final result.

1. Initialize an array `pos` to store the intermediate results, with a size equal to the sum of the lengths of both input strings.
2. Run two nested loops for each digit of both input numbers (from right to left).
3. Calculate the product of the two digits.
4. Determine the indices to store the product values in the `pos` array, e.g., in the form of tens and units.
5. Update the `pos` array with the new product values.
6. Combine the values in the `pos` array to form the final result string.

The time complexity is O(m*n) where `m` and `n` are the lengths of the input strings, `num1` and `num2`. The space complexity is also O(m+n).


# Wildcard Matching

- slug: wildcard-matching
- difficulty: Hard

Given an input string (`s`) and a pattern (`p`), implement wildcard pattern matching with support for `'?'` and `'*'` where:

*   `'?'` Matches any single character.
*   `'*'` Matches any sequence of characters (including the empty sequence).

The matching should cover the **entire** input string (not partial).

**Example 1:**

**Input:** s =  "aa ", p =  "a "
**Output:** false
**Explanation:**  "a " does not match the entire string  "aa ".

**Example 2:**

**Input:** s =  "aa ", p =  "\* "
**Output:** true
**Explanation:** '\*' matches any sequence.

**Example 3:**

**Input:** s =  "cb ", p =  "?a "
**Output:** false
**Explanation:** '?' matches 'c', but the second letter is 'a', which does not match 'b'.

**Constraints:**

*   `0 <= s.length, p.length <= 2000`
*   `s` contains only lowercase English letters.
*   `p` contains only lowercase English letters, `'?'` or `'*'`.

## A solution in Java

```java
public boolean isMatch(String s, String p) {
    int m = s.length(), n = p.length();
    int i = 0, j = 0, asterisk = -1, match = 0;
    while (i < m) {
        if (j < n && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?')) {
            i++; j++;
        } else if (j < n && p.charAt(j) == '*') {
            match = i;
            asterisk = j++;
        } else if (asterisk != -1) {
            i = ++match;
            j = asterisk + 1;
        } else {
            return false;
        }
    }
    while (j < n && p.charAt(j) == '*') j++;
    return j == n;
}
```
- Initialize `m` and `n` as the lengths of the input string `s` and pattern `p`. Initialize `i`, `j`, `asterisk`, and `match` to 0.
- Use a `while` loop with a condition of `i < m`. Loop through the input string and pattern and compare the characters at the corresponding positions.
  - If the characters are equal or the pattern character is a question mark, increment both `i` and `j`.
  - If the pattern character is an asterisk, store the current positions in `match` and `asterisk`, then increment `j`.
  - If there is a stored `asterisk` position and the current characters don't match, increment match, set `i` to the incremented match value, and set `j` to the `asterisk` position plus one.
  - If none of the above conditions are met, return `false` as the input string and pattern don't match.
- After the loop, if there are remaining asterisks in the pattern, increment the pointer `j`.
- Return `true` if the pointer `j` reaches the end of the pattern, otherwise, return `false`.

## A solution in C++

```cpp
bool isMatch(const std::string& s, const std::string& p) {
    int m = s.size(), n = p.size();
    int i = 0, j = 0, asterisk = -1, match;
    while (i < m) {
        if (j < n && (s[i] == p[j] || p[j] == '?')) {
            i++; j++;
        } else if (j < n && p[j] == '*') {
            match = i;
            asterisk = j++;
        } else if (asterisk >= 0) {
            i = ++match;
            j = asterisk + 1;
        } else {
            return false;
        }
    }
    while (j < n && p[j] == '*') j++;
    return j == n;
}
```
- Initialize `m` and `n` as the lengths of the input string `s` and pattern `p`. Initialize `i`, `j`, `asterisk`, and `match` to 0.
- Use a `while` loop with a condition of `i < m`. Loop through the input string and pattern and compare the characters at the corresponding positions.
  - If the characters are equal or the pattern character is a question mark, increment both `i` and `j`.
  - If the pattern character is an asterisk, store the current positions in `match` and `asterisk`, then increment `j`.
  - If there is a stored `asterisk` position and the current characters don't match, increment match, set `i` to the incremented match value, and set `j` to the `asterisk` position plus one.
  - If none of the above conditions are met, return `false` as the input string and pattern don't match.
- After the loop, if there are remaining asterisks in the pattern, increment the pointer `j`.
- Return `true` if the pointer `j` reaches the end of the pattern, otherwise, return `false`.

## A solution in Python

```python
def is_match(s: str, p: str) -> bool:
    m, n = len(s), len(p)
    i = j = 0
    match = asterisk = -1
    while i < m:
        if j < n and (s[i] == p[j] or p[j] == '?'):
            i, j = i + 1, j + 1
        elif j < n and p[j] == '*':
            match, asterisk = i, j
            j += 1
        elif asterisk >= 0:
            i, j = match + 1, asterisk + 1
            match += 1
        else:
            return False
    while j < n and p[j] == '*':
        j += 1
    return j == n
```
- Initialize `m` and `n` as the lengths of the input string `s` and pattern `p`. Initialize `i`, `j`, `asterisk`, and `match` to 0.
- Use a `while` loop with a condition of `i < m`. Loop through the input string and pattern and compare the characters at the corresponding positions.
  - If the characters are equal or the pattern character is a question mark, increment both `i` and `j`.
  - If the pattern character is an asterisk, store the current positions in `match` and `asterisk`, then increment `j`.
  - If there is a stored `asterisk` position and the current characters don't match, increment match, set `i` to the incremented match value, and set `j` to the `asterisk` position plus one.
  - If none of the above conditions are met, return `false` as the input string and pattern don't match.
- After the loop, if there are remaining asterisks in the pattern, increment the pointer `j`.
- Return `true` if the pointer `j` reaches the end of the pattern, otherwise, return `false`.

## A solution in Javascript

```javascript
function isMatch(s, p) {
    let m = s.length,
        n = p.length;
    let i = 0,
        j = 0,
        asterisk = -1,
        match = 0;
    while (i < m) {
        if (j < n && (s[i] === p[j] || p[j] === '?')) {
            i++;
            j++;
        } else if (j < n && p[j] === '*') {
            match = i;
            asterisk = j++;
        } else if (asterisk >= 0) {
            i = ++match;
            j = asterisk + 1;
        } else {
            return false;
        }
    }
    while (j < n && p[j] === '*') j++;
    return j === n;
}
```
- Initialize `m` and `n` as the lengths of the input string `s` and pattern `p`. Initialize `i`, `j`, `asterisk`, and `match` to 0.
- Use a `while` loop with a condition of `i < m`. Loop through the input string and pattern and compare the characters at the corresponding positions.
  - If the characters are equal or the pattern character is a question mark, increment both `i` and `j`.
  - If the pattern character is an asterisk, store the current positions in `match` and `asterisk`, then increment `j`.
  - If there is a stored `asterisk` position and the current characters don't match, increment match, set `i` to the incremented match value, and set `j` to the `asterisk` position plus one.
  - If none of the above conditions are met, return `false` as the input string and pattern don't match.
- After the loop, if there are remaining asterisks in the pattern, increment the pointer `j`.
- Return `true` if the pointer `j` reaches the end of the pattern, otherwise, return `false`.


# Jump Game II

- slug: jump-game-ii
- difficulty: Medium

You are given a **0-indexed** array of integers `nums` of length `n`. You are initially positioned at `nums[0]`.

Each element `nums[i]` represents the maximum length of a forward jump from index `i`. In other words, if you are at `nums[i]`, you can jump to any `nums[i + j]` where:

*   `0 <= j <= nums[i]` and
*   `i + j < n`

Return _the minimum number of jumps to reach_ `nums[n - 1]`. The test cases are generated such that you can reach `nums[n - 1]`.

**Example 1:**

**Input:** nums = \[2,3,1,1,4\]
**Output:** 2
**Explanation:** The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.

**Example 2:**

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

**Constraints:**

*   `1 <= nums.length <= 104`
*   `0 <= nums[i] <= 1000`
*   It's guaranteed that you can reach `nums[n - 1]`.

## A solution in Java

```java
public int jump(int[] nums) {
    int jumps = 0, currentEnd = 0, currentFarthest = 0;

    for (int i = 0; i < nums.length - 1; i++) {
        currentFarthest = Math.max(currentFarthest, i + nums[i]);
        if (i == currentEnd) {
            jumps++;
            currentEnd = currentFarthest;
        }
    }
    return jumps;
}
```
We initialize jumps to count the number of jumps, current_end to keep track of the farthest index we can reach with the current number of jumps, and current_farthest to keep track of the farthest index that can be reached from the current position.

We loop through the array up to the second last element. For each index, we calculate and store the farthest index that can be reached from the current index. If the current index equals the current end, we increment the jumps, as we need one more jump to reach or go beyond the current end, and update the current_end with the current_farthest value.

Finally, we return the number of jumps which represents the minimum number of jumps needed to reach the last index.

## A solution in C++

```cpp
int jump(vector<int>& nums) {
    int jumps = 0, current_end = 0, current_farthest = 0;

    for (int i = 0; i < nums.size() - 1; i++) {
        current_farthest = max(current_farthest, i + nums[i]);
        if (i == current_end) {
            jumps++;
            current_end = current_farthest;
        }
    }
    return jumps;
}
```
We initialize jumps to count the number of jumps, current_end to keep track of the farthest index we can reach with the current number of jumps, and current_farthest to keep track of the farthest index that can be reached from the current position.

We loop through the array up to the second last element. For each index, we calculate and store the farthest index that can be reached from the current index. If the current index equals the current end, we increment the jumps, as we need one more jump to reach or go beyond the current end, and update the current_end with the current_farthest value.

Finally, we return the number of jumps which represents the minimum number of jumps needed to reach the last index.

## A solution in Python

```python
def jump(nums):
    jumps = 0
    current_end = 0
    current_farthest = 0

    for i in range(len(nums) - 1):
        current_farthest = max(current_farthest, i + nums[i])
        if i == current_end:
            jumps += 1
            current_end = current_farthest

    return jumps
```
We initialize jumps to count the number of jumps, current_end to keep track of the farthest index we can reach with the current number of jumps, and current_farthest to keep track of the farthest index that can be reached from the current position.

We loop through the array up to the second last element. For each index, we calculate and store the farthest index that can be reached from the current index. If the current index equals the current end, we increment the jumps, as we need one more jump to reach or go beyond the current end, and update the current_end with the current_farthest value.

Finally, we return the number of jumps which represents the minimum number of jumps needed to reach the last index.

## A solution in Javascript

```javascript
function jump(nums) {
    let jumps = 0, currentEnd = 0, currentFarthest = 0;

    for (let i = 0; i < nums.length - 1; i++) {
        currentFarthest = Math.max(currentFarthest, i + nums[i]);
        if (i === currentEnd) {
            jumps++;
            currentEnd = currentFarthest;
        }
    }
    return jumps;
}
```
We initialize jumps to count the number of jumps, current_end to keep track of the farthest index we can reach with the current number of jumps, and current_farthest to keep track of the farthest index that can be reached from the current position.

We loop through the array up to the second last element. For each index, we calculate and store the farthest index that can be reached from the current index. If the current index equals the current end, we increment the jumps, as we need one more jump to reach or go beyond the current end, and update the current_end with the current_farthest value.

Finally, we return the number of jumps which represents the minimum number of jumps needed to reach the last index.


# Permutations

- slug: permutations
- difficulty: Medium

Given an array `nums` of distinct integers, return _all the possible permutations_. You can return the answer in **any order**.

**Example 1:**

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

**Example 2:**

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

**Example 3:**

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

**Constraints:**

*   `1 <= nums.length <= 6`
*   `-10 <= nums[i] <= 10`
*   All the integers of `nums` are **unique**.

## A solution in Java

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

public List<List<Integer>> permute(int[] nums) {
    List<List<Integer>> results = new ArrayList<>();
    helper(nums, 0, results);
    return results;
}

private void helper(int[] nums, int index, List<List<Integer>> results) {
    if (index == nums.length - 1) {
        List<Integer> tempList = new ArrayList<>();
        for (int n : nums) {
            tempList.add(n);
        }
        results.add(tempList);
        return;
    }

    for (int i = index; i < nums.length; i++) {
        swap(nums, index, i);
        helper(nums, index + 1, results);
        swap(nums, index, i);
    }
}

private void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}
```
The algorithm uses backtracking to generate all possible permutations. It works by swapping the elements in the input array in a recursive manner.

1. The base case is when the index reaches the last element of the array; at this point, we append the current configuration to the "results" list.
2. For each index, we iterate from `index` to the end of the array, performing the following steps:
    a. Swap `index` and `i` elements.
    b. Recursively call the helper function with `index + 1`.
    c. Swap the elements back to their original positions.

This will generate all possible permutations, as it swaps elements in different positions while maintaining the original order in the input array. The termination condition for the recursion is the base case when we reach the end of the array. The complexity of this algorithm is O(N!), as there are N! permutations of an array of N elements.

## A solution in C++

```cpp
#include <vector>

void helper(std::vector<int>& nums, int index, std::vector<std::vector<int>>& results) {
    if (index == nums.size() - 1) {
        results.push_back(nums);
        return;
    }

    for (int i = index; i < nums.size(); i++) {
        std::swap(nums[index], nums[i]);
        helper(nums, index + 1, results);
        std::swap(nums[index], nums[i]);
    }
}

std::vector<std::vector<int>> permute(std::vector<int>& nums) {
    std::vector<std::vector<int>> results;
    helper(nums, 0, results);
    return results;
}
```
The algorithm uses backtracking to generate all possible permutations. It works by swapping the elements in the input array in a recursive manner.

1. The base case is when the index reaches the last element of the array; at this point, we append the current configuration to the "results" list.
2. For each index, we iterate from `index` to the end of the array, performing the following steps:
    a. Swap `index` and `i` elements.
    b. Recursively call the helper function with `index + 1`.
    c. Swap the elements back to their original positions.

This will generate all possible permutations, as it swaps elements in different positions while maintaining the original order in the input array. The termination condition for the recursion is the base case when we reach the end of the array. The complexity of this algorithm is O(N!), as there are N! permutations of an array of N elements.

## A solution in Python

```python
from typing import List

def permute(nums: List[int]) -> List[List[int]]:
    def helper(index):
        if index == len(nums) - 1:
            results.append(nums[:])
            return

        for i in range(index, len(nums)):
            nums[index], nums[i] = nums[i], nums[index]
            helper(index + 1)
            nums[index], nums[i] = nums[i], nums[index]

    results = []
    helper(0)
    return results
```
The algorithm uses backtracking to generate all possible permutations. It works by swapping the elements in the input array in a recursive manner.

1. The base case is when the index reaches the last element of the array; at this point, we append the current configuration to the "results" list.
2. For each index, we iterate from `index` to the end of the array, performing the following steps:
    a. Swap `index` and `i` elements.
    b. Recursively call the helper function with `index + 1`.
    c. Swap the elements back to their original positions.

This will generate all possible permutations, as it swaps elements in different positions while maintaining the original order in the input array. The termination condition for the recursion is the base case when we reach the end of the array. The complexity of this algorithm is O(N!), as there are N! permutations of an array of N elements.

## A solution in Javascript

```javascript
function permute(nums) {
  const results = [];
  helper(nums, 0, results);
  return results;
}

function helper(nums, index, results) {
  if (index === nums.length - 1) {
    results.push(nums.slice());
    return;
  }

  for (let i = index; i < nums.length; i++) {
    [nums[index], nums[i]] = [nums[i], nums[index]];
    helper(nums, index + 1, results);
    [nums[index], nums[i]] = [nums[i], nums[index]];
  }
}
```
The algorithm uses backtracking to generate all possible permutations. It works by swapping the elements in the input array in a recursive manner.

1. The base case is when the index reaches the last element of the array; at this point, we append the current configuration to the "results" list.
2. For each index, we iterate from `index` to the end of the array, performing the following steps:
    a. Swap `index` and `i` elements.
    b. Recursively call the helper function with `index + 1`.
    c. Swap the elements back to their original positions.

This will generate all possible permutations, as it swaps elements in different positions while maintaining the original order in the input array. The termination condition for the recursion is the base case when we reach the end of the array. The complexity of this algorithm is O(N!), as there are N! permutations of an array of N elements.


# Permutations II

- slug: permutations-ii
- difficulty: Medium

Given a collection of numbers, `nums`, that might contain duplicates, return _all possible unique permutations **in any order**._

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `1 <= nums.length <= 8`
*   `-10 <= nums[i] <= 10`

## A solution in Java

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

public List<List<Integer>> permuteUnique(int[] nums) {
    Arrays.sort(nums);
    List<List<Integer>> result = new ArrayList<>();
    boolean[] visited = new boolean[nums.length];
    backtrack(result, new ArrayList<>(), nums, visited);
    return result;
}

private void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] nums, boolean[] visited) {
    if (tempList.size() == nums.length) {
        result.add(new ArrayList<>(tempList));
    } else {
        for (int i = 0; i < nums.length; i++) {
            if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1])) continue;
            visited[i] = true;
            tempList.add(nums[i]);
            backtrack(result, tempList, nums, visited);
            tempList.remove(tempList.size() - 1);
            visited[i] = false;
        }
    }
}
```
We use backtracking to generate permutations. Firstly, we sort the `nums` array to make sure that duplicate numbers are located together. Then, for each recursive backtracking call, we swap the elements in the range `[start, len(nums) - 1]` with `nums[start]`, ignoring already-visited elements by using a `visited` array.

We also skip any element that is equal to the current `start` element to avoid duplicates. After generating a valid permutation by iterating through all indices, we append the current permutation to the result array. When backtracking, we maintain the original order of elements before moving to the next level.

The time complexity of this approach is O(n! * n) since there are n! available permutations and each permutation requires O(n) time to build the solution. The space complexity is O(n) to store the `visited` array and temporary lists.

## A solution in C++

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

void backtrack(std::vector<std::vector<int>>& result, std::vector<int>& nums, int start) {
    if (start == nums.size()) {
        result.push_back(nums);
        return;
    }
    for (int i = start; i < nums.size(); i++) {
        if (i > start && nums[i] == nums[start]) continue;
        std::swap(nums[start], nums[i]);
        backtrack(result, nums, start + 1);
        std::swap(nums[start], nums[i]);
    }
}

std::vector<std::vector<int>> permuteUnique(std::vector<int>& nums) {
    std::sort(nums.begin(), nums.end());
    std::vector<std::vector<int>> result;
    backtrack(result, nums, 0);
    return result;
}
```
We use backtracking to generate permutations. Firstly, we sort the `nums` array to make sure that duplicate numbers are located together. Then, for each recursive backtracking call, we swap the elements in the range `[start, len(nums) - 1]` with `nums[start]`, ignoring already-visited elements by using a `visited` array.

We also skip any element that is equal to the current `start` element to avoid duplicates. After generating a valid permutation by iterating through all indices, we append the current permutation to the result array. When backtracking, we maintain the original order of elements before moving to the next level.

The time complexity of this approach is O(n! * n) since there are n! available permutations and each permutation requires O(n) time to build the solution. The space complexity is O(n) to store the `visited` array and temporary lists.

## A solution in Python

```python
from typing import List

def permuteUnique(nums: List[int]) -> List[List[int]]:
    def backtrack(start):
        if start == len(nums):
            result.append(nums[:])
        for i in range(start, len(nums)):
            if i > start and nums[i] == nums[start]:
                continue
            nums[start], nums[i] = nums[i], nums[start]
            backtrack(start + 1)
            nums[start], nums[i] = nums[i], nums[start]

    nums.sort()
    result = []
    backtrack(0)
    return result
```
We use backtracking to generate permutations. Firstly, we sort the `nums` array to make sure that duplicate numbers are located together. Then, for each recursive backtracking call, we swap the elements in the range `[start, len(nums) - 1]` with `nums[start]`, ignoring already-visited elements by using a `visited` array.

We also skip any element that is equal to the current `start` element to avoid duplicates. After generating a valid permutation by iterating through all indices, we append the current permutation to the result array. When backtracking, we maintain the original order of elements before moving to the next level.

The time complexity of this approach is O(n! * n) since there are n! available permutations and each permutation requires O(n) time to build the solution. The space complexity is O(n) to store the `visited` array and temporary lists.

## A solution in Javascript

```javascript
function permuteUnique(nums) {
    nums.sort((a, b) => a - b);
    const result = [];
    const visited = new Array(nums.length).fill(false);

    function backtrack(tempList) {
        if (tempList.length === nums.length) {
            result.push([...tempList]);
            return;
        }
        for (let i = 0; i < nums.length; i++) {
            if (visited[i] || (i > 0 && nums[i] === nums[i - 1] && !visited[i - 1])) continue;
            visited[i] = true;
            tempList.push(nums[i]);
            backtrack(tempList);
            tempList.pop();
            visited[i] = false;
        }
    }

    backtrack([]);
    return result;
}
```
We use backtracking to generate permutations. Firstly, we sort the `nums` array to make sure that duplicate numbers are located together. Then, for each recursive backtracking call, we swap the elements in the range `[start, len(nums) - 1]` with `nums[start]`, ignoring already-visited elements by using a `visited` array.

We also skip any element that is equal to the current `start` element to avoid duplicates. After generating a valid permutation by iterating through all indices, we append the current permutation to the result array. When backtracking, we maintain the original order of elements before moving to the next level.

The time complexity of this approach is O(n! * n) since there are n! available permutations and each permutation requires O(n) time to build the solution. The space complexity is O(n) to store the `visited` array and temporary lists.


# Rotate Image

- slug: rotate-image
- difficulty: Medium

You are given an `n x n` 2D `matrix` representing an image, rotate the image by **90** degrees (clockwise).

You have to rotate the image [**in-place**](https://en.wikipedia.org/wiki/In-place_algorithm), which means you have to modify the input 2D matrix directly. **DO NOT** allocate another 2D matrix and do the rotation.

**Example 1:**

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

**Example 2:**

**Input:** matrix = \[\[5,1,9,11\],\[2,4,8,10\],\[13,3,6,7\],\[15,14,12,16\]\]
**Output:** \[\[15,13,2,5\],\[14,3,4,1\],\[12,6,8,9\],\[16,7,10,11\]\]

**Constraints:**

*   `n == matrix.length == matrix[i].length`
*   `1 <= n <= 20`
*   `-1000 <= matrix[i][j] <= 1000`

## A solution in Java

```java
public void rotate(int[][] matrix) {
    int n = matrix.length;
    for (int i = 0; i < n / 2; i++) {
        for (int j = i; j < n - i - 1; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[n - j - 1][i];
            matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
            matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
            matrix[j][n - i - 1] = temp;
        }
    }
}
```
The algorithm iterates over each layer of the matrix gradually working inwards. For each element in the current layer, it performs a 4-way swap (moving elements from left -> top, bottom -> left, right -> bottom, and top -> right). This moves each element in the layer to its new position after rotation without using any additional memory. The algorithm proceeds with this strategy until it reaches the center of the matrix, ensuring that all elements are correctly rotated.

## A solution in C++

```cpp
void rotate(vector<vector<int>>& matrix) {
    int n = matrix.size();
    for (int i = 0; i < n / 2; i++) {
        for (int j = i; j < n - i - 1; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[n - j - 1][i];
            matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
            matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
            matrix[j][n - i - 1] = temp;
        }
    }
}
```
The algorithm iterates over each layer of the matrix gradually working inwards. For each element in the current layer, it performs a 4-way swap (moving elements from left -> top, bottom -> left, right -> bottom, and top -> right). This moves each element in the layer to its new position after rotation without using any additional memory. The algorithm proceeds with this strategy until it reaches the center of the matrix, ensuring that all elements are correctly rotated.

## A solution in Python

```python
def rotate(matrix):
    n = len(matrix)
    for i in range(n // 2):
        for j in range(i, n - i - 1):
            temp = matrix[i][j]
            matrix[i][j] = matrix[n - j - 1][i]
            matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1]
            matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1]
            matrix[j][n - i - 1] = temp
```
The algorithm iterates over each layer of the matrix gradually working inwards. For each element in the current layer, it performs a 4-way swap (moving elements from left -> top, bottom -> left, right -> bottom, and top -> right). This moves each element in the layer to its new position after rotation without using any additional memory. The algorithm proceeds with this strategy until it reaches the center of the matrix, ensuring that all elements are correctly rotated.

## A solution in Javascript

```javascript
function rotate(matrix) {
    let n = matrix.length;
    for (let i = 0; i < Math.floor(n / 2); i++) {
        for (let j = i; j < n - i - 1; j++) {
            let temp = matrix[i][j];
            matrix[i][j] = matrix[n - j - 1][i];
            matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
            matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
            matrix[j][n - i - 1] = temp;
        }
    }
}
```
The algorithm iterates over each layer of the matrix gradually working inwards. For each element in the current layer, it performs a 4-way swap (moving elements from left -> top, bottom -> left, right -> bottom, and top -> right). This moves each element in the layer to its new position after rotation without using any additional memory. The algorithm proceeds with this strategy until it reaches the center of the matrix, ensuring that all elements are correctly rotated.


# Group Anagrams

- slug: group-anagrams
- difficulty: Medium

Given an array of strings `strs`, group **the anagrams** together. You can return the answer in **any order**.

An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

**Example 1:**

**Input:** strs = \["eat","tea","tan","ate","nat","bat"\]
**Output:** \[\["bat"\],\["nat","tan"\],\["ate","eat","tea"\]\]

**Example 2:**

**Input:** strs = \[""\]
**Output:** \[\[""\]\]

**Example 3:**

**Input:** strs = \["a"\]
**Output:** \[\["a"\]\]

**Constraints:**

*   `1 <= strs.length <= 104`
*   `0 <= strs[i].length <= 100`
*   `strs[i]` consists of lowercase English letters.

## A solution in Java

```java
import java.util.*;

public List<List<String>> groupAnagrams(String[] strs) {
    Map<String, List<String>> anagramMap = new HashMap<>();

    for (String str : strs) {
        char[] keyChars = str.toCharArray();
        Arrays.sort(keyChars);
        String key = new String(keyChars);

        anagramMap.putIfAbsent(key, new ArrayList<>());
        anagramMap.get(key).add(str);
    }

    return new ArrayList<>(anagramMap.values());
}
```
The algorithm iterates through the input array of strings. For each string, create a sorted version of the string as key, and store the original strings as values. Use a data structure like a map or dictionary to store the grouped anagrams in these key-value pairs. The keys will represent the different anagrams, while the values will be lists of the original strings that fit the anagram. Finally, extract the values (lists of anagrams) from the map or dictionary and return them. This works because anagrams will produce the same sorted strings as keys.

## A solution in C++

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

std::vector<std::vector<std::string>> groupAnagrams(std::vector<std::string>& strs) {
    std::map<std::string, std::vector<std::string>> anagramMap;

    for (std::string str : strs) {
        std::string key = str;
        std::sort(key.begin(), key.end());
        anagramMap[key].push_back(str);
    }

    std::vector<std::vector<std::string>> result;
    for (auto &entry : anagramMap) {
        result.push_back(entry.second);
    }

    return result;
}
```
The algorithm iterates through the input array of strings. For each string, create a sorted version of the string as key, and store the original strings as values. Use a data structure like a map or dictionary to store the grouped anagrams in these key-value pairs. The keys will represent the different anagrams, while the values will be lists of the original strings that fit the anagram. Finally, extract the values (lists of anagrams) from the map or dictionary and return them. This works because anagrams will produce the same sorted strings as keys.

## A solution in Python

```python
from collections import defaultdict

def group_anagrams(strs):
    anagram_map = defaultdict(list)

    for s in strs:
        key = ''.join(sorted(s))
        anagram_map[key].append(s)

    return list(anagram_map.values())
```
The algorithm iterates through the input array of strings. For each string, create a sorted version of the string as key, and store the original strings as values. Use a data structure like a map or dictionary to store the grouped anagrams in these key-value pairs. The keys will represent the different anagrams, while the values will be lists of the original strings that fit the anagram. Finally, extract the values (lists of anagrams) from the map or dictionary and return them. This works because anagrams will produce the same sorted strings as keys.

## A solution in Javascript

```javascript
function groupAnagrams(strs) {
    const anagramMap = new Map();

    for (const str of strs) {
        const key = str.split('').sort().join('');

        if (!anagramMap.has(key)) {
            anagramMap.set(key, []);
        }
        anagramMap.get(key).push(str);
    }

    return Array.from(anagramMap.values());
}
```
The algorithm iterates through the input array of strings. For each string, create a sorted version of the string as key, and store the original strings as values. Use a data structure like a map or dictionary to store the grouped anagrams in these key-value pairs. The keys will represent the different anagrams, while the values will be lists of the original strings that fit the anagram. Finally, extract the values (lists of anagrams) from the map or dictionary and return them. This works because anagrams will produce the same sorted strings as keys.