# Add Binary

- slug: add-binary
- difficulty: Easy

Given two binary strings `a` and `b`, return _their sum as a binary string_.

**Example 1:**

**Input:** a = "11", b = "1"
**Output:** "100"

**Example 2:**

**Input:** a = "1010", b = "1011"
**Output:** "10101"

**Constraints:**

*   `1 <= a.length, b.length <= 104`
*   `a` and `b` consist only of `'0'` or `'1'` characters.
*   Each string does not contain leading zeros except for the zero itself.

## A solution in Java

```java
public String addBinary(String a, String b) {
    StringBuilder result = new StringBuilder();
    int i = a.length() - 1, j = b.length() - 1, carry = 0;
    while (i >= 0 || j >= 0 || carry != 0) {
        if (i >= 0) carry += a.charAt(i--) - '0';
        if (j >= 0) carry += b.charAt(j--) - '0';
        result.insert(0, carry % 2);
        carry /= 2;
    }
    return result.toString();
}
```
The algorithm initializes an empty result binary string, carry, and two pointers i and j pointing to the last element of strings a and b respectively.
In each iteration:
- If i is not out of bounds, add the corresponding binary number to the carry.
- If j is not out of bounds, add the corresponding binary number to the carry.
- Append the remainder of dividing carry by 2 to the result binary string (left side).
- Update carry by dividing it by 2 (integer division).

This process continues until i and j pointers become out of bounds and there is no carry left.

Finally, return the result binary string.

## A solution in C++

```cpp
std::string addBinary(std::string a, std::string b) {
    std::string result = "";
    int i = a.size() - 1, j = b.size() - 1, carry = 0;
    while (i >= 0 || j >= 0 || carry) {
        if (i >= 0) carry += a[i--] - '0';
        if (j >= 0) carry += b[j--] - '0';
        result = char(carry % 2 + '0') + result;
        carry /= 2;
    }
    return result;
}
```
The algorithm initializes an empty result binary string, carry, and two pointers i and j pointing to the last element of strings a and b respectively.
In each iteration:
- If i is not out of bounds, add the corresponding binary number to the carry.
- If j is not out of bounds, add the corresponding binary number to the carry.
- Append the remainder of dividing carry by 2 to the result binary string (left side).
- Update carry by dividing it by 2 (integer division).

This process continues until i and j pointers become out of bounds and there is no carry left.

Finally, return the result binary string.

## A solution in Python

```python
def addBinary(a: str, b: str) -> str:
    result, carry, i, j = "", 0, len(a) - 1, len(b) - 1
    while i >= 0 or j >= 0 or carry:
        if i >= 0:
            carry += int(a[i])
            i -= 1
        if j >= 0:
            carry += int(b[j])
            j -= 1
        result = str(carry % 2) + result
        carry //= 2
    return result
```
The algorithm initializes an empty result binary string, carry, and two pointers i and j pointing to the last element of strings a and b respectively.
In each iteration:
- If i is not out of bounds, add the corresponding binary number to the carry.
- If j is not out of bounds, add the corresponding binary number to the carry.
- Append the remainder of dividing carry by 2 to the result binary string (left side).
- Update carry by dividing it by 2 (integer division).

This process continues until i and j pointers become out of bounds and there is no carry left.

Finally, return the result binary string.

## A solution in Javascript

```javascript
function addBinary(a, b) {
    let result = "";
    let i = a.length - 1, j = b.length - 1, carry = 0;
    while (i >= 0 || j >= 0 || carry) {
        if (i >= 0) carry += parseInt(a[i--], 10);
        if (j >= 0) carry += parseInt(b[j--], 10);
        result = (carry % 2) + result;
        carry = Math.floor(carry / 2);
    }
    return result;
}
```
The algorithm initializes an empty result binary string, carry, and two pointers i and j pointing to the last element of strings a and b respectively.
In each iteration:
- If i is not out of bounds, add the corresponding binary number to the carry.
- If j is not out of bounds, add the corresponding binary number to the carry.
- Append the remainder of dividing carry by 2 to the result binary string (left side).
- Update carry by dividing it by 2 (integer division).

This process continues until i and j pointers become out of bounds and there is no carry left.

Finally, return the result binary string.


# Text Justification

- slug: text-justification
- difficulty: Hard

Given an array of strings `words` and a width `maxWidth`, format the text such that each line has exactly `maxWidth` characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces `' '` when necessary so that each line has exactly `maxWidth` characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line does not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left-justified, and no extra space is inserted between words.

**Note:**

*   A word is defined as a character sequence consisting of non-space characters only.
*   Each word's length is guaranteed to be greater than `0` and not exceed `maxWidth`.
*   The input array `words` contains at least one word.

**Example 1:**

**Input:** words = \[ "This ",  "is ",  "an ",  "example ",  "of ",  "text ",  "justification. "\], maxWidth = 16
**Output:**
\[
    "This    is    an ",
    "example  of text ",
    "justification.   "
\]

**Example 2:**

**Input:** words = \[ "What ", "must ", "be ", "acknowledgment ", "shall ", "be "\], maxWidth = 16
**Output:**
\[
   "What   must   be ",
   "acknowledgment   ",
   "shall be         "
\]
**Explanation:** Note that the last line is  "shall be     " instead of  "shall     be ", because the last line must be left-justified instead of fully-justified.
Note that the second line is also left-justified because it contains only one word.

**Example 3:**

**Input:** words = \[ "Science ", "is ", "what ", "we ", "understand ", "well ", "enough ", "to ", "explain ", "to ", "a ", "computer. ", "Art ", "is ", "everything ", "else ", "we ", "do "\], maxWidth = 20
**Output:**
\[
   "Science  is  what we ",
   "understand      well ",
   "enough to explain to ",
   "a  computer.  Art is ",
   "everything  else  we ",
   "do                   "
\]

**Constraints:**

*   `1 <= words.length <= 300`
*   `1 <= words[i].length <= 20`
*   `words[i]` consists of only English letters and symbols.
*   `1 <= maxWidth <= 100`
*   `words[i].length <= maxWidth`

## A solution in Java

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

public List<String> fullJustify(String[] words, int maxWidth) {
    List<String> result = new ArrayList<>();
    int idx = 0;
    while (idx < words.length) {
        int totalChars = words[idx].length();
        int last = idx + 1;
        while (last < words.length) {
            if (totalChars + 1 + words[last].length() > maxWidth) break;
            totalChars += 1 + words[last].length();
            last++;
        }
        int gaps = last - idx - 1;
        StringBuilder line = new StringBuilder();
        if (last == words.length || gaps == 0) {
            for (int i = idx; i < last; i++) {
                line.append(words[i]);
                if (i < last - 1) line.append(" ");
            }
            while (line.length() < maxWidth) line.append(" ");
        } else {
            int evenSpaces = (maxWidth - totalChars) / gaps;
            int extraSpaces = (maxWidth - totalChars) % gaps;
            for (int i = idx; i < last; i++) {
                line.append(words[i]);
                if (i < last - 1) {
                    line.append(" ".repeat(evenSpaces + (i - idx < extraSpaces ? 1 : 0)));
                }
            }
        }
        idx = last;
        result.add(line.toString());
    }
    return result;
}
```
The algorithm works as follows:
1. Initialize an empty result list.
2. Use `idx` to keep track of the start of the line. `idx` initially starts at 0, i.e., the first word.
3. Calculate the total number of characters from `idx` to the last word in a line by testing whether adding the next word, with an extra space before it, would exceed `maxWidth`.
4. Find the number of gaps in the current line. If it is the last line or there is only one word, left-justify the words and pad the remaining space with spaces.
5. If it's not the last line, distribute spaces as evenly as possible between words: calculate `evenSpaces` and `extraSpaces`, and add an extra space to the left gaps until there are no more `extraSpaces`.
6. Append the constructed line to the result list and update the `idx` to the start of the next line.
7. Repeat steps 3 to 6 until reaching the last word.
8. Return the result list.

## A solution in C++

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

vector<string> fullJustify(vector<string>& words, int maxWidth) {
    vector<string> result;
    int idx = 0;
    while (idx < words.size()) {
        int totalChars = words[idx].size();
        int last = idx + 1;
        while (last < words.size()) {
            if (totalChars + 1 + words[last].length() > maxWidth) break;
            totalChars += 1 + words[last].length();
            last++;
        }
        int gaps = last - idx - 1;
        stringstream line;
        if (last == words.size() || gaps == 0) {
            for (int i = idx; i < last; i++) {
                line << words[i];
                if (i < last - 1) line << " ";
            }
            line << string(maxWidth - line.str().size(), ' ');
        } else {
            int evenSpaces = (maxWidth - totalChars) / gaps;
            int extraSpaces = (maxWidth - totalChars) % gaps;
            for (int i = idx; i < last; i++) {
                line << words[i];
                if (i < last - 1) {
                    line << string(evenSpaces + (i - idx < extraSpaces ? 1 : 0), ' ');
                }
            }
        }
        idx = last;
        result.push_back(line.str());
    }
    return result;
}
```
The algorithm works as follows:
1. Initialize an empty result list.
2. Use `idx` to keep track of the start of the line. `idx` initially starts at 0, i.e., the first word.
3. Calculate the total number of characters from `idx` to the last word in a line by testing whether adding the next word, with an extra space before it, would exceed `maxWidth`.
4. Find the number of gaps in the current line. If it is the last line or there is only one word, left-justify the words and pad the remaining space with spaces.
5. If it's not the last line, distribute spaces as evenly as possible between words: calculate `evenSpaces` and `extraSpaces`, and add an extra space to the left gaps until there are no more `extraSpaces`.
6. Append the constructed line to the result list and update the `idx` to the start of the next line.
7. Repeat steps 3 to 6 until reaching the last word.
8. Return the result list.

## A solution in Python

```python
def fullJustify(words, maxWidth):
    result = []
    idx = 0
    while idx < len(words):
        total_chars = len(words[idx])
        last = idx + 1
        while last < len(words):
            if total_chars + 1 + len(words[last]) > maxWidth:
                break
            total_chars += 1 + len(words[last])
            last += 1
        gaps = last - idx - 1
        line = []
        if last == len(words) or gaps == 0:
            for i in range(idx, last):
                line.append(words[i])
                if i < last - 1:
                    line.append(" ")
            while sum(len(w) for w in line) < maxWidth:
                line.append(" ")
        else:
            even_spaces = (maxWidth - total_chars) // gaps
            extra_spaces = (maxWidth - total_chars) % gaps
            for i in range(idx, last):
                line.append(words[i])
                if i < last - 1:
                    line.append(" " * (even_spaces + (1 if i - idx < extra_spaces else 0)))
        idx = last
        result.append("".join(line))
    return result
```
The algorithm works as follows:
1. Initialize an empty result list.
2. Use `idx` to keep track of the start of the line. `idx` initially starts at 0, i.e., the first word.
3. Calculate the total number of characters from `idx` to the last word in a line by testing whether adding the next word, with an extra space before it, would exceed `maxWidth`.
4. Find the number of gaps in the current line. If it is the last line or there is only one word, left-justify the words and pad the remaining space with spaces.
5. If it's not the last line, distribute spaces as evenly as possible between words: calculate `evenSpaces` and `extraSpaces`, and add an extra space to the left gaps until there are no more `extraSpaces`.
6. Append the constructed line to the result list and update the `idx` to the start of the next line.
7. Repeat steps 3 to 6 until reaching the last word.
8. Return the result list.

## A solution in Javascript

```javascript
function fullJustify(words, maxWidth) {
    const result = [];
    let idx = 0;
    while (idx < words.length) {
        let totalChars = words[idx].length;
        let last = idx + 1;
        while (last < words.length) {
            if (totalChars + 1 + words[last].length > maxWidth) break;
            totalChars += 1 + words[last].length;
            last++;
        }
        const gaps = last - idx - 1;
        let line = "";
        if (last === words.length || gaps === 0) {
            for (let i = idx; i < last; i++) {
                line += words[i];
                if (i < last - 1) line += " ";
            }
            while (line.length < maxWidth) line += " ";
        } else {
            const evenSpaces = Math.floor((maxWidth - totalChars) / gaps);
            const extraSpaces = (maxWidth - totalChars) % gaps;
            for (let i = idx; i < last; i++) {
                line += words[i];
                if (i < last - 1) {
                    line += " ".repeat(evenSpaces + (i - idx < extraSpaces ? 1 : 0));
                }
            }
        }
        idx = last;
        result.push(line);
    }
    return result;
}
```
The algorithm works as follows:
1. Initialize an empty result list.
2. Use `idx` to keep track of the start of the line. `idx` initially starts at 0, i.e., the first word.
3. Calculate the total number of characters from `idx` to the last word in a line by testing whether adding the next word, with an extra space before it, would exceed `maxWidth`.
4. Find the number of gaps in the current line. If it is the last line or there is only one word, left-justify the words and pad the remaining space with spaces.
5. If it's not the last line, distribute spaces as evenly as possible between words: calculate `evenSpaces` and `extraSpaces`, and add an extra space to the left gaps until there are no more `extraSpaces`.
6. Append the constructed line to the result list and update the `idx` to the start of the next line.
7. Repeat steps 3 to 6 until reaching the last word.
8. Return the result list.


# Sqrt(x)

- slug: sqrtx
- difficulty: Easy

Given a non-negative integer `x`, return _the square root of_ `x` _rounded down to the nearest integer_. The returned integer should be **non-negative** as well.

You **must not use** any built-in exponent function or operator.

*   For example, do not use `pow(x, 0.5)` in c++ or `x ** 0.5` in python.

**Example 1:**

**Input:** x = 4
**Output:** 2
**Explanation:** The square root of 4 is 2, so we return 2.

**Example 2:**

**Input:** x = 8
**Output:** 2
**Explanation:** The square root of 8 is 2.82842..., and since we round it down to the nearest integer, 2 is returned.

**Constraints:**

*   `0 <= x <= 231 - 1`

## A solution in Java

```java
public int mySqrt(int x) {
    if (x == 0 || x == 1) return x;
    int start = 1, end = x, ans = 0;
    while (start <= end) {
        int mid = (start + end) / 2;
        if (mid * mid == x) return mid;
        if (mid <= x / mid) {
            start = mid + 1;
            ans = mid;
        } else {
            end = mid - 1;
        }
    }
    return ans;
}
```
The algorithm uses a binary search approach to find the integer square root of the given number `x`. It starts with the smallest possible answer (1) and the largest possible answer (x), updating the "start" and "end" positions based on whether the current midpoint squared is smaller or larger than x. The integer square root of the number is found when `mid * mid == x`, or when the closest integer (under or equal to x) value has been located. The binary search approach keeps the time complexity at O(log(x)), making it an efficient solution.

## A solution in C++

```cpp
int mySqrt(int x) {
    if (x == 0 || x == 1) return x;
    int start = 1, end = x, ans;
    while (start <= end) {
        int mid = (start + end) / 2;
        if (mid * mid == x) return mid;
        if (mid * mid < x) {
            start = mid + 1;
            ans = mid;
        } else {
            end = mid - 1;
        }
    }
    return ans;
}
```
The algorithm uses a binary search approach to find the integer square root of the given number `x`. It starts with the smallest possible answer (1) and the largest possible answer (x), updating the "start" and "end" positions based on whether the current midpoint squared is smaller or larger than x. The integer square root of the number is found when `mid * mid == x`, or when the closest integer (under or equal to x) value has been located. The binary search approach keeps the time complexity at O(log(x)), making it an efficient solution.

## A solution in Python

```python
def mySqrt(x):
    if x == 0 or x == 1:
        return x
    start, end, ans = 1, x, 0
    while start <= end:
        mid = (start + end) // 2
        if mid * mid == x:
            return mid
        if mid * mid < x:
            start = mid + 1
            ans = mid
        else:
            end = mid - 1
    return ans
```
The algorithm uses a binary search approach to find the integer square root of the given number `x`. It starts with the smallest possible answer (1) and the largest possible answer (x), updating the "start" and "end" positions based on whether the current midpoint squared is smaller or larger than x. The integer square root of the number is found when `mid * mid == x`, or when the closest integer (under or equal to x) value has been located. The binary search approach keeps the time complexity at O(log(x)), making it an efficient solution.

## A solution in Javascript

```javascript
function mySqrt(x) {
    if (x === 0 || x === 1) return x;
    let start = 1, end = x, ans;
    while (start <= end) {
        let mid = Math.floor((start + end) / 2);
        if (mid * mid === x) return mid;
        if (mid * mid < x) {
            start = mid + 1;
            ans = mid;
        } else {
            end = mid - 1;
        }
    }
    return ans;
}
```
The algorithm uses a binary search approach to find the integer square root of the given number `x`. It starts with the smallest possible answer (1) and the largest possible answer (x), updating the "start" and "end" positions based on whether the current midpoint squared is smaller or larger than x. The integer square root of the number is found when `mid * mid == x`, or when the closest integer (under or equal to x) value has been located. The binary search approach keeps the time complexity at O(log(x)), making it an efficient solution.


# Climbing Stairs

- slug: climbing-stairs
- difficulty: Easy

You are climbing a staircase. It takes `n` steps to reach the top.

Each time you can either climb `1` or `2` steps. In how many distinct ways can you climb to the top?

**Example 1:**

**Input:** n = 2
**Output:** 2
**Explanation:** There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps

**Example 2:**

**Input:** n = 3
**Output:** 3
**Explanation:** There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step

**Constraints:**

*   `1 <= n <= 45`

## A solution in Java

```java
public int climbStairs(int n) {
    if(n <= 2) return n;
    int a = 1, b = 2, c;
    for(int i = 3; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}
```
This problem can be solved using dynamic programming. The number of ways to reach the top can be calculated by finding the sum of the ways to reach the previous two steps. We start with the base cases where `n` is 1 or 2, and then iteratively build up the solution. In each iteration, we update `a` and `b` with the new number of ways to reach steps `n-2` and `n-1` respectively, and keep calculating the number of ways to reach step `n` using `a + b`. This continues until we reach the top and return the final result.

## A solution in C++

```cpp
int climbStairs(int n) {
    if(n <= 2) return n;
    int a = 1, b = 2, c;
    for(int i = 3; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}
```
This problem can be solved using dynamic programming. The number of ways to reach the top can be calculated by finding the sum of the ways to reach the previous two steps. We start with the base cases where `n` is 1 or 2, and then iteratively build up the solution. In each iteration, we update `a` and `b` with the new number of ways to reach steps `n-2` and `n-1` respectively, and keep calculating the number of ways to reach step `n` using `a + b`. This continues until we reach the top and return the final result.

## A solution in Python

```python
def climbStairs(n):
    if n <= 2:
        return n
    a, b = 1, 2
    for _ in range(3, n+1):
        a, b = b, a + b
    return b
```
This problem can be solved using dynamic programming. The number of ways to reach the top can be calculated by finding the sum of the ways to reach the previous two steps. We start with the base cases where `n` is 1 or 2, and then iteratively build up the solution. In each iteration, we update `a` and `b` with the new number of ways to reach steps `n-2` and `n-1` respectively, and keep calculating the number of ways to reach step `n` using `a + b`. This continues until we reach the top and return the final result.

## A solution in Javascript

```javascript
function climbStairs(n) {
    if(n <= 2) return n;
    let a = 1, b = 2, c;
    for(let i = 3; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}
```
This problem can be solved using dynamic programming. The number of ways to reach the top can be calculated by finding the sum of the ways to reach the previous two steps. We start with the base cases where `n` is 1 or 2, and then iteratively build up the solution. In each iteration, we update `a` and `b` with the new number of ways to reach steps `n-2` and `n-1` respectively, and keep calculating the number of ways to reach step `n` using `a + b`. This continues until we reach the top and return the final result.


# Simplify Path

- slug: simplify-path
- difficulty: Medium

Given a string `path`, which is an **absolute path** (starting with a slash `'/'`) to a file or directory in a Unix-style file system, convert it to the simplified **canonical path**.

In a Unix-style file system, a period `'.'` refers to the current directory, a double period `'..'` refers to the directory up a level, and any multiple consecutive slashes (i.e. `'//'`) are treated as a single slash `'/'`. For this problem, any other format of periods such as `'...'` are treated as file/directory names.

The **canonical path** should have the following format:

*   The path starts with a single slash `'/'`.
*   Any two directories are separated by a single slash `'/'`.
*   The path does not end with a trailing `'/'`.
*   The path only contains the directories on the path from the root directory to the target file or directory (i.e., no period `'.'` or double period `'..'`)

Return _the simplified **canonical path**_.

**Example 1:**

**Input:** path =  "/home/ "
**Output:**  "/home "
**Explanation:** Note that there is no trailing slash after the last directory name.

**Example 2:**

**Input:** path =  "/../ "
**Output:**  "/ "
**Explanation:** Going one level up from the root directory is a no-op, as the root level is the highest level you can go.

**Example 3:**

**Input:** path =  "/home//foo/ "
**Output:**  "/home/foo "
**Explanation:** In the canonical path, multiple consecutive slashes are replaced by a single one.

**Constraints:**

*   `1 <= path.length <= 3000`
*   `path` consists of English letters, digits, period `'.'`, slash `'/'` or `'_'`.
*   `path` is a valid absolute Unix path.

## A solution in Java

```java
import java.util.LinkedList;

public String simplifyPath(String path) {
    String[] parts = path.split("/");
    LinkedList<String> stack = new LinkedList<>();

    for (String part : parts) {
        if (part.isEmpty() || part.equals(".")) continue;
        if (part.equals("..")) {
            if (!stack.isEmpty()) stack.removeLast();
        } else {
            stack.addLast(part);
        }
    }

    StringBuilder canonicalPath = new StringBuilder();
    for (String piece : stack) {
        canonicalPath.append('/').append(piece);
    }
    return stack.isEmpty() ? "/" : canonicalPath.toString();
}
```
The algorithm uses a stack to keep track of the directory hierarchy. It starts by splitting the input string by '/', iterating over each part, and processing them according to the following rules:
1. If the part is empty or ".", skip it.
2. If the part is "..", pop off the top element of the stack (if it's non-empty).
3. Otherwise, push the part onto the stack.

After processing all parts, concatenate the elements in the stack separated by '/' and return the canonical path.

The implementations are very similar across the four languages, with differences stemming primarily from the syntax and conventions of each language.

## A solution in C++

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

std::string simplifyPath(std::string path) {
    std::vector<std::string> stack;
    std::istringstream ss{path};
    std::string part;

    while (std::getline(ss, part, '/')) {
        if (part.empty() || part == ".") continue;
        if (part == "..") {
            if (!stack.empty()) stack.pop_back();
        } else {
            stack.push_back(part);
        }
    }

    std::string canonicalPath;
    for (const auto &piece : stack) {
        canonicalPath += '/' + piece;
    }
    return stack.empty() ? "/" : canonicalPath;
}
```
The algorithm uses a stack to keep track of the directory hierarchy. It starts by splitting the input string by '/', iterating over each part, and processing them according to the following rules:
1. If the part is empty or ".", skip it.
2. If the part is "..", pop off the top element of the stack (if it's non-empty).
3. Otherwise, push the part onto the stack.

After processing all parts, concatenate the elements in the stack separated by '/' and return the canonical path.

The implementations are very similar across the four languages, with differences stemming primarily from the syntax and conventions of each language.

## A solution in Python

```python
def simplifyPath(path: str) -> str:
    stack = []
    parts = path.split("/")

    for part in parts:
        if not part or part == ".":
            continue
        if part == "..":
            if stack:
                stack.pop()
        else:
            stack.append(part)

    return "/" + "/".join(stack)
```
The algorithm uses a stack to keep track of the directory hierarchy. It starts by splitting the input string by '/', iterating over each part, and processing them according to the following rules:
1. If the part is empty or ".", skip it.
2. If the part is "..", pop off the top element of the stack (if it's non-empty).
3. Otherwise, push the part onto the stack.

After processing all parts, concatenate the elements in the stack separated by '/' and return the canonical path.

The implementations are very similar across the four languages, with differences stemming primarily from the syntax and conventions of each language.

## A solution in Javascript

```javascript
function simplifyPath(path) {
    let stack = [];
    let parts = path.split("/");

    for (let part of parts) {
        if (!part || part === ".") continue;
        if (part === "..") {
            if (stack.length) stack.pop();
        } else {
            stack.push(part);
        }
    }

    return "/" + stack.join("/");
}
```
The algorithm uses a stack to keep track of the directory hierarchy. It starts by splitting the input string by '/', iterating over each part, and processing them according to the following rules:
1. If the part is empty or ".", skip it.
2. If the part is "..", pop off the top element of the stack (if it's non-empty).
3. Otherwise, push the part onto the stack.

After processing all parts, concatenate the elements in the stack separated by '/' and return the canonical path.

The implementations are very similar across the four languages, with differences stemming primarily from the syntax and conventions of each language.


# Edit Distance

- slug: edit-distance
- difficulty: Hard

Given two strings `word1` and `word2`, return _the minimum number of operations required to convert `word1` to `word2`_.

You have the following three operations permitted on a word:

*   Insert a character
*   Delete a character
*   Replace a character

**Example 1:**

**Input:** word1 =  "horse ", word2 =  "ros "
**Output:** 3
**Explanation:**
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')

**Example 2:**

**Input:** word1 =  "intention ", word2 =  "execution "
**Output:** 5
**Explanation:**
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')

**Constraints:**

*   `0 <= word1.length, word2.length <= 500`
*   `word1` and `word2` consist of lowercase English letters.

## A solution in Java

```java
public int minDistance(String word1, String word2) {
    int m = word1.length();
    int n = word2.length();
    int[][] dp = new int[m + 1][n + 1];

    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0) {
                dp[i][j] = j;
            } else if (j == 0) {
                dp[i][j] = i;
            } else if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
            }
        }
    }

    return dp[m][n];
}
```
The algorithm used is dynamic programming. We create a 2D table dp with dimensions (m+1) x (n+1), where m is the length of word1 and n is the length of word2. Each cell dp[i][j] represents the minimum number of operations required to convert word1[0...i-1] to word2[0...j-1].

For each cell, we have the following conditions:
1. If either i or j is 0, it means one of the strings is empty, so the minimum number of operations needed is the length of the non-empty string (i or j).
2. If the current characters of the two strings are equal (word1[i-1] == word2[j-1]), we don't have to do anything, so dp[i][j] = dp[i-1][j-1].
3. If the current characters are different, we take the minimum of the following and add 1:
    a. dp[i-1][j]: Delete operation
    b. dp[i][j-1]: Insert operation
    c. dp[i-1][j-1]: Replace operation

After filling the table, the minimum number of operations will be at dp[m][n].

## A solution in C++

```cpp
int minDistance(string word1, string word2) {
    int m = word1.size();
    int n = word2.size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0) {
                dp[i][j] = j;
            } else if (j == 0) {
                dp[i][j] = i;
            } else if (word1[i - 1] == word2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
            }
        }
    }

    return dp[m][n];
}
```
The algorithm used is dynamic programming. We create a 2D table dp with dimensions (m+1) x (n+1), where m is the length of word1 and n is the length of word2. Each cell dp[i][j] represents the minimum number of operations required to convert word1[0...i-1] to word2[0...j-1].

For each cell, we have the following conditions:
1. If either i or j is 0, it means one of the strings is empty, so the minimum number of operations needed is the length of the non-empty string (i or j).
2. If the current characters of the two strings are equal (word1[i-1] == word2[j-1]), we don't have to do anything, so dp[i][j] = dp[i-1][j-1].
3. If the current characters are different, we take the minimum of the following and add 1:
    a. dp[i-1][j]: Delete operation
    b. dp[i][j-1]: Insert operation
    c. dp[i-1][j-1]: Replace operation

After filling the table, the minimum number of operations will be at dp[m][n].

## A solution in Python

```python
def minDistance(word1: str, word2: str) -> int:
    m, n = len(word1), len(word2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    for i in range(m + 1):
        for j in range(n + 1):
            if i == 0:
                dp[i][j] = j
            elif j == 0:
                dp[i][j] = i
            elif word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1

    return dp[m][n]
```
The algorithm used is dynamic programming. We create a 2D table dp with dimensions (m+1) x (n+1), where m is the length of word1 and n is the length of word2. Each cell dp[i][j] represents the minimum number of operations required to convert word1[0...i-1] to word2[0...j-1].

For each cell, we have the following conditions:
1. If either i or j is 0, it means one of the strings is empty, so the minimum number of operations needed is the length of the non-empty string (i or j).
2. If the current characters of the two strings are equal (word1[i-1] == word2[j-1]), we don't have to do anything, so dp[i][j] = dp[i-1][j-1].
3. If the current characters are different, we take the minimum of the following and add 1:
    a. dp[i-1][j]: Delete operation
    b. dp[i][j-1]: Insert operation
    c. dp[i-1][j-1]: Replace operation

After filling the table, the minimum number of operations will be at dp[m][n].

## A solution in Javascript

```javascript
function minDistance(word1, word2) {
    const m = word1.length;
    const n = word2.length;
    const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));

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

    return dp[m][n];
}
```
The algorithm used is dynamic programming. We create a 2D table dp with dimensions (m+1) x (n+1), where m is the length of word1 and n is the length of word2. Each cell dp[i][j] represents the minimum number of operations required to convert word1[0...i-1] to word2[0...j-1].

For each cell, we have the following conditions:
1. If either i or j is 0, it means one of the strings is empty, so the minimum number of operations needed is the length of the non-empty string (i or j).
2. If the current characters of the two strings are equal (word1[i-1] == word2[j-1]), we don't have to do anything, so dp[i][j] = dp[i-1][j-1].
3. If the current characters are different, we take the minimum of the following and add 1:
    a. dp[i-1][j]: Delete operation
    b. dp[i][j-1]: Insert operation
    c. dp[i-1][j-1]: Replace operation

After filling the table, the minimum number of operations will be at dp[m][n].


# Set Matrix Zeroes

- slug: set-matrix-zeroes
- difficulty: Medium

Given an `m x n` integer matrix `matrix`, if an element is `0`, set its entire row and column to `0`'s.

You must do it [in place](https://en.wikipedia.org/wiki/In-place_algorithm).

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `m == matrix.length`
*   `n == matrix[0].length`
*   `1 <= m, n <= 200`
*   `-231 <= matrix[i][j] <= 231 - 1`

**Follow up:**

*   A straightforward solution using `O(mn)` space is probably a bad idea.
*   A simple improvement uses `O(m + n)` space, but still not the best solution.
*   Could you devise a constant space solution?

## A solution in Java

```java
public void setZeroes(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    boolean firstRow = false, firstCol = false;

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (matrix[i][j] == 0) {
                if (i == 0) firstRow = true;
                if (j == 0) firstCol = true;
                matrix[i][0] = 0;
                matrix[0][j] = 0;
            }
        }
    }

    for (int i = 1; i < rows; i++) {
        for (int j = 1; j < cols; j++) {
            if (matrix[i][0] == 0 || matrix[0][j] == 0)
                matrix[i][j] = 0;
        }
    }

    if (firstRow) {
        for (int j = 0; j < cols; j++)
            matrix[0][j] = 0;
    }

    if (firstCol) {
        for (int i = 0; i < rows; i++)
            matrix[i][0] = 0;
    }
}
```
1. Iterate over the matrix, marking the first element of the row and column for every 0 encountered.
2. Set a flag if the first row or the first column has a 0.
3. Iterate over the matrix, ignoring the first row and first column. Set the element to 0 if the corresponding first row or column is marked.
4. Finally, set the first row and column to 0 if their flags are set.

## A solution in C++

```cpp
void setZeroes(vector<vector<int>>& matrix) {
    int rows = matrix.size();
    int cols = matrix[0].size();
    bool firstRow = false, firstCol = false;

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (matrix[i][j] == 0) {
                if (i == 0) firstRow = true;
                if (j == 0) firstCol = true;
                matrix[i][0] = 0;
                matrix[0][j] = 0;
            }
        }
    }

    for (int i = 1; i < rows; i++) {
        for (int j = 1; j < cols; j++) {
            if (matrix[i][0] == 0 || matrix[0][j] == 0)
                matrix[i][j] = 0;
        }
    }

    if (firstRow) {
        for (int j = 0; j < cols; j++)
            matrix[0][j] = 0;
    }

    if (firstCol) {
        for (int i = 0; i < rows; i++)
            matrix[i][0] = 0;
    }
}
```
1. Iterate over the matrix, marking the first element of the row and column for every 0 encountered.
2. Set a flag if the first row or the first column has a 0.
3. Iterate over the matrix, ignoring the first row and first column. Set the element to 0 if the corresponding first row or column is marked.
4. Finally, set the first row and column to 0 if their flags are set.

## A solution in Python

```python
def setZeroes(matrix):
    rows = len(matrix)
    cols = len(matrix[0])
    firstRow, firstCol = False, False

    for i in range(rows):
        for j in range(cols):
            if matrix[i][j] == 0:
                if i == 0: firstRow = True
                if j == 0: firstCol = True
                matrix[i][0] = 0
                matrix[0][j] = 0

    for i in range(1, rows):
        for j in range(1, cols):
            if matrix[i][0] == 0 or matrix[0][j] == 0:
                matrix[i][j] = 0

    if firstRow:
        for j in range(cols):
            matrix[0][j] = 0

    if firstCol:
        for i in range(rows):
            matrix[i][0] = 0
```
1. Iterate over the matrix, marking the first element of the row and column for every 0 encountered.
2. Set a flag if the first row or the first column has a 0.
3. Iterate over the matrix, ignoring the first row and first column. Set the element to 0 if the corresponding first row or column is marked.
4. Finally, set the first row and column to 0 if their flags are set.

## A solution in Javascript

```javascript
function setZeroes(matrix) {
    let rows = matrix.length;
    let cols = matrix[0].length;
    let firstRow = false;
    let firstCol = false;

    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (matrix[i][j] === 0) {
                if (i === 0) firstRow = true;
                if (j === 0) firstCol = true;
                matrix[i][0] = 0;
                matrix[0][j] = 0;
            }
        }
    }

    for (let i = 1; i < rows; i++) {
        for (let j = 1; j < cols; j++) {
            if (matrix[i][0] === 0 || matrix[0][j] === 0) {
                matrix[i][j] = 0;
            }
        }
    }

    if (firstRow) {
        for (let j = 0; j < cols; j++)
            matrix[0][j] = 0;
    }

    if (firstCol) {
        for (let i = 0; i < rows; i++)
            matrix[i][0] = 0;
    }
}
```
1. Iterate over the matrix, marking the first element of the row and column for every 0 encountered.
2. Set a flag if the first row or the first column has a 0.
3. Iterate over the matrix, ignoring the first row and first column. Set the element to 0 if the corresponding first row or column is marked.
4. Finally, set the first row and column to 0 if their flags are set.


# Search a 2D Matrix

- slug: search-a-2d-matrix
- difficulty: Medium

You are given an `m x n` integer matrix `matrix` with the following two properties:

*   Each row is sorted in non-decreasing order.
*   The first integer of each row is greater than the last integer of the previous row.

Given an integer `target`, return `true` _if_ `target` _is in_ `matrix` _or_ `false` _otherwise_.

You must write a solution in `O(log(m * n))` time complexity.

**Example 1:**

**Input:** matrix = \[\[1,3,5,7\],\[10,11,16,20\],\[23,30,34,60\]\], target = 3
**Output:** true

**Example 2:**

**Input:** matrix = \[\[1,3,5,7\],\[10,11,16,20\],\[23,30,34,60\]\], target = 13
**Output:** false

**Constraints:**

*   `m == matrix.length`
*   `n == matrix[i].length`
*   `1 <= m, n <= 100`
*   `-104 <= matrix[i][j], target <= 104`

## A solution in Java

```java
public boolean searchMatrix(int[][] matrix, int target) {
    int m = matrix.length;
    int n = matrix[0].length;
    int l = 0, r = m * n - 1;

    while (l <= r) {
        int mid = l + (r - l) / 2;
        int midVal = matrix[mid / n][mid % n];

        if (midVal == target) {
            return true;
        } else if (midVal < target) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }

    return false;
}
```
The algorithm uses binary search on an m x n matrix.

Firstly, the number of rows and columns (m and n) are computed. Then, we initialize the left and right pointers (l and r).

In each step of the binary search, we calculate the middle index (mid) and get the corresponding value (mid_val) in the matrix. To get the value in the matrix, we divide mid by n and take the remainder.

We then compare the mid_val with the target. If it is equal to the target, we return true. If it's less than the target, we move the left pointer to the next position (mid + 1). Otherwise, we move the right pointer (mid - 1).

If the search space has been fully explored and the target is not found, we return false.

## A solution in C++

```cpp
bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int m = matrix.size();
    int n = matrix[0].size();
    int l = 0, r = m * n - 1;

    while (l <= r) {
        int mid = l + (r - l) / 2;
        int midVal = matrix[mid / n][mid % n];

        if (midVal == target) {
            return true;
        } else if (midVal < target) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }

    return false;
}
```
The algorithm uses binary search on an m x n matrix.

Firstly, the number of rows and columns (m and n) are computed. Then, we initialize the left and right pointers (l and r).

In each step of the binary search, we calculate the middle index (mid) and get the corresponding value (mid_val) in the matrix. To get the value in the matrix, we divide mid by n and take the remainder.

We then compare the mid_val with the target. If it is equal to the target, we return true. If it's less than the target, we move the left pointer to the next position (mid + 1). Otherwise, we move the right pointer (mid - 1).

If the search space has been fully explored and the target is not found, we return false.

## A solution in Python

```python
def searchMatrix(matrix, target):
    m, n = len(matrix), len(matrix[0])
    l, r = 0, m * n - 1

    while l <= r:
        mid = l + (r - l) // 2
        mid_val = matrix[mid // n][mid % n]

        if mid_val == target:
            return True
        elif mid_val < target:
            l = mid + 1
        else:
            r = mid - 1

    return False
```
The algorithm uses binary search on an m x n matrix.

Firstly, the number of rows and columns (m and n) are computed. Then, we initialize the left and right pointers (l and r).

In each step of the binary search, we calculate the middle index (mid) and get the corresponding value (mid_val) in the matrix. To get the value in the matrix, we divide mid by n and take the remainder.

We then compare the mid_val with the target. If it is equal to the target, we return true. If it's less than the target, we move the left pointer to the next position (mid + 1). Otherwise, we move the right pointer (mid - 1).

If the search space has been fully explored and the target is not found, we return false.

## A solution in Javascript

```javascript
function searchMatrix(matrix, target) {
    const m = matrix.length;
    const n = matrix[0].length;
    let l = 0, r = m * n - 1;

    while (l <= r) {
        const mid = l+ Math.floor((r - l) / 2);
        const midVal = matrix[Math.floor(mid / n)][mid % n];

        if (midVal === target) {
            return true;
        } else if (midVal < target) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }

    return false;
}
```
The algorithm uses binary search on an m x n matrix.

Firstly, the number of rows and columns (m and n) are computed. Then, we initialize the left and right pointers (l and r).

In each step of the binary search, we calculate the middle index (mid) and get the corresponding value (mid_val) in the matrix. To get the value in the matrix, we divide mid by n and take the remainder.

We then compare the mid_val with the target. If it is equal to the target, we return true. If it's less than the target, we move the left pointer to the next position (mid + 1). Otherwise, we move the right pointer (mid - 1).

If the search space has been fully explored and the target is not found, we return false.


# Sort Colors

- slug: sort-colors
- difficulty: Medium

Given an array `nums` with `n` objects colored red, white, or blue, sort them **[in-place](https://en.wikipedia.org/wiki/In-place_algorithm)** so that objects of the same color are adjacent, with the colors in the order red, white, and blue.

We will use the integers `0`, `1`, and `2` to represent the color red, white, and blue, respectively.

You must solve this problem without using the library's sort function.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `n == nums.length`
*   `1 <= n <= 300`
*   `nums[i]` is either `0`, `1`, or `2`.

**Follow up:** Could you come up with a one-pass algorithm using only constant extra space?

## A solution in Java

```java
public void sortColors(int[] nums) {
    int red = 0, white = 0, blue = nums.length - 1;
    while (white <= blue) {
        if (nums[white] == 0) {
            int temp = nums[red];
            nums[red++] = nums[white];
            nums[white++] = temp;
        } else if (nums[white] == 1) {
            white++;
        } else {
            int temp = nums[white];
            nums[white] = nums[blue];
            nums[blue--] = temp;
        }
    }
}
```
The algorithm can be explained using three pointers: `red`, `white`, and `blue`. `red` is responsible for tracking the position where the next 0 should be moved to, starting from the beginning of the array. Likewise, `blue` is responsible for tracking the position where the next 2 should be swapped to, starting from the end of the array. `white` is responsible for iterating through the array.

While `white` is less than or equal to `blue`, check the current `nums[white]` value. If it is 0, swap it with the value at index `red`, and increment both `red` and `white`. If it is 1, simply increment `white`. If it is 2, swap the value at index `white` with the value at index `blue`, and decrement `blue` without incrementing `white` since the newly swapped value at index `white` might be 0 or 2.

This will sort the colors in the required order with a linear-time complexity, as we only go through the array once with the `white` pointer. Also, it sorts the colors in-place without the need for additional storage.

## A solution in C++

```cpp
void sortColors(vector<int>& nums) {
    int red = 0, white = 0, blue = nums.size() - 1;
    while (white <= blue) {
        if (nums[white] == 0) {
            swap(nums[red++], nums[white++]);
        } else if (nums[white] == 1) {
            white++;
        } else {
            swap(nums[white], nums[blue--]);
        }
    }
}
```
The algorithm can be explained using three pointers: `red`, `white`, and `blue`. `red` is responsible for tracking the position where the next 0 should be moved to, starting from the beginning of the array. Likewise, `blue` is responsible for tracking the position where the next 2 should be swapped to, starting from the end of the array. `white` is responsible for iterating through the array.

While `white` is less than or equal to `blue`, check the current `nums[white]` value. If it is 0, swap it with the value at index `red`, and increment both `red` and `white`. If it is 1, simply increment `white`. If it is 2, swap the value at index `white` with the value at index `blue`, and decrement `blue` without incrementing `white` since the newly swapped value at index `white` might be 0 or 2.

This will sort the colors in the required order with a linear-time complexity, as we only go through the array once with the `white` pointer. Also, it sorts the colors in-place without the need for additional storage.

## A solution in Python

```python
def sortColors(nums: List[int]) -> None:
    red, white, blue = 0, 0, len(nums) - 1
    while white <= blue:
        if nums[white] == 0:
            nums[red], nums[white] = nums[white], nums[red]
            red += 1
            white += 1
        elif nums[white] == 1:
            white += 1
        else:
            nums[white], nums[blue] = nums[blue], nums[white]
            blue -= 1
```
The algorithm can be explained using three pointers: `red`, `white`, and `blue`. `red` is responsible for tracking the position where the next 0 should be moved to, starting from the beginning of the array. Likewise, `blue` is responsible for tracking the position where the next 2 should be swapped to, starting from the end of the array. `white` is responsible for iterating through the array.

While `white` is less than or equal to `blue`, check the current `nums[white]` value. If it is 0, swap it with the value at index `red`, and increment both `red` and `white`. If it is 1, simply increment `white`. If it is 2, swap the value at index `white` with the value at index `blue`, and decrement `blue` without incrementing `white` since the newly swapped value at index `white` might be 0 or 2.

This will sort the colors in the required order with a linear-time complexity, as we only go through the array once with the `white` pointer. Also, it sorts the colors in-place without the need for additional storage.

## A solution in Javascript

```javascript
function sortColors(nums) {
    let red = 0, white = 0, blue = nums.length - 1;
    while (white <= blue) {
        if (nums[white] === 0) {
            [nums[red], nums[white]] = [nums[white], nums[red]];
            red++;
            white++;
        } else if (nums[white] === 1) {
            white++;
        } else {
            [nums[white], nums[blue]] = [nums[blue], nums[white]];
            blue--;
        }
    }
}
```
The algorithm can be explained using three pointers: `red`, `white`, and `blue`. `red` is responsible for tracking the position where the next 0 should be moved to, starting from the beginning of the array. Likewise, `blue` is responsible for tracking the position where the next 2 should be swapped to, starting from the end of the array. `white` is responsible for iterating through the array.

While `white` is less than or equal to `blue`, check the current `nums[white]` value. If it is 0, swap it with the value at index `red`, and increment both `red` and `white`. If it is 1, simply increment `white`. If it is 2, swap the value at index `white` with the value at index `blue`, and decrement `blue` without incrementing `white` since the newly swapped value at index `white` might be 0 or 2.

This will sort the colors in the required order with a linear-time complexity, as we only go through the array once with the `white` pointer. Also, it sorts the colors in-place without the need for additional storage.


# Minimum Window Substring

- slug: minimum-window-substring
- difficulty: Hard

Given two strings `s` and `t` of lengths `m` and `n` respectively, return _the **minimum window**_ **_substring_** _of_ `s` _such that every character in_ `t` _(**including duplicates**) is included in the window_. If there is no such substring, return _the empty string_ `" "`.

The testcases will be generated such that the answer is **unique**.

**Example 1:**

**Input:** s =  "ADOBECODEBANC ", t =  "ABC "
**Output:**  "BANC "
**Explanation:** The minimum window substring  "BANC " includes 'A', 'B', and 'C' from string t.

**Example 2:**

**Input:** s =  "a ", t =  "a "
**Output:**  "a "
**Explanation:** The entire string s is the minimum window.

**Example 3:**

**Input:** s =  "a ", t =  "aa "
**Output:**  " "
**Explanation:** Both 'a's from t must be included in the window.
Since the largest window of s only has one 'a', return empty string.

**Constraints:**

*   `m == s.length`
*   `n == t.length`
*   `1 <= m, n <= 105`
*   `s` and `t` consist of uppercase and lowercase English letters.

**Follow up:** Could you find an algorithm that runs in `O(m + n)` time?

## A solution in Java

```java
import java.util.HashMap;

public String minWindow(String s, String t) {
    HashMap<Character, Integer> need = new HashMap<>();
    HashMap<Character, Integer> window = new HashMap<>();
    for (char c : t.toCharArray()) need.put(c, need.getOrDefault(c, 0) + 1);

    int left = 0, right = 0;
    int valid = 0;
    int start = 0, length = Integer.MAX_VALUE;

    while (right < s.length()) {
        char c = s.charAt(right);
        right++;
        if (need.containsKey(c)) {
            window.put(c, window.getOrDefault(c, 0) + 1);
            if (window.get(c) <= need.get(c)) valid++;
        }

        while (valid == t.length()) {
            if (right - left < length) {
                start = left;
                length = right - left;
            }

            char d = s.charAt(left);
            left++;
            if (need.containsKey(d)) {
                if (window.get(d) <= need.get(d)) valid--;
                window.put(d, window.get(d) - 1);
            }
        }
    }
    return length == Integer.MAX_VALUE ? "" : s.substring(start, start + length);
}
```
The algorithm uses a sliding window approach to find the minimum window substring. We use two pointers, `left` and `right`, to represent the current window.

1. Initialize an unordered_map or dictionary for `need` to store characters and their counts in `t`, and another for `window` to store characters and their counts in the current window.
2. Initialize `left` and `right` pointers, `valid` counter for keeping track of characters satisfying the criteria, and `start` and `length` for holding the answer substring information.
3. Iterate through the string `s` using the `right` pointer, and:
    - If the current character exists in the `need` map, update the count of the character in the `window` map, and increment `valid` if the count in the window is less than or equal to the count in need.
4. Check the validity by comparing `valid` with the length of `t`.
    - If valid, update the answer substring's `start` and `length` if the current window's length is less than the current minimum.
    - Then, increment the `left` pointer to slide the window until the current character count in the window goes below the count in `need`. Update the `valid` counter accordingly.
5. Return the answer substring, or empty string if no window was found.

## A solution in C++

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

std::string min_window(std::string s, std::string t) {
    std::unordered_map<char, int> need, window;
    for (char c : t) need[c]++;

    int left = 0, right = 0;
    int valid = 0;
    int start = 0, length = INT_MAX;

    while (right < s.length()) {
        char c = s[right];
        right++;
        if (need.count(c)) {
            window[c]++;
            if (window[c] <= need[c]) valid++;
        }

        while (valid == t.length()) {
            if (right - left < length) {
                start = left;
                length = right - left;
            }

            char d = s[left];
            left++;
            if (need.count(d)) {
                if (window[d] <= need[d]) valid--;
                window[d]--;
            }
        }
    }
    return length == INT_MAX ? "" : s.substr(start, length);
}
```
The algorithm uses a sliding window approach to find the minimum window substring. We use two pointers, `left` and `right`, to represent the current window.

1. Initialize an unordered_map or dictionary for `need` to store characters and their counts in `t`, and another for `window` to store characters and their counts in the current window.
2. Initialize `left` and `right` pointers, `valid` counter for keeping track of characters satisfying the criteria, and `start` and `length` for holding the answer substring information.
3. Iterate through the string `s` using the `right` pointer, and:
    - If the current character exists in the `need` map, update the count of the character in the `window` map, and increment `valid` if the count in the window is less than or equal to the count in need.
4. Check the validity by comparing `valid` with the length of `t`.
    - If valid, update the answer substring's `start` and `length` if the current window's length is less than the current minimum.
    - Then, increment the `left` pointer to slide the window until the current character count in the window goes below the count in `need`. Update the `valid` counter accordingly.
5. Return the answer substring, or empty string if no window was found.

## A solution in Python

```python
from collections import Counter

def min_window(s, t):
    need = Counter(t)
    window = {}

    left = 0
    right = 0
    valid = 0
    start = 0
    length = float('inf')

    while right < len(s):
        c = s[right]
        right += 1
        if c in need:
            window[c] = window.get(c, 0) + 1
            if window[c] <= need[c]:
                valid += 1

        while valid == len(t):
            if right - left < length:
                start = left
                length = right - left

            d = s[left]
            left += 1
            if d in need:
                if window[d] <= need[d]:
                    valid -= 1
                window[d] -= 1

    return "" if length == float('inf') else s[start : start + length]
```
The algorithm uses a sliding window approach to find the minimum window substring. We use two pointers, `left` and `right`, to represent the current window.

1. Initialize an unordered_map or dictionary for `need` to store characters and their counts in `t`, and another for `window` to store characters and their counts in the current window.
2. Initialize `left` and `right` pointers, `valid` counter for keeping track of characters satisfying the criteria, and `start` and `length` for holding the answer substring information.
3. Iterate through the string `s` using the `right` pointer, and:
    - If the current character exists in the `need` map, update the count of the character in the `window` map, and increment `valid` if the count in the window is less than or equal to the count in need.
4. Check the validity by comparing `valid` with the length of `t`.
    - If valid, update the answer substring's `start` and `length` if the current window's length is less than the current minimum.
    - Then, increment the `left` pointer to slide the window until the current character count in the window goes below the count in `need`. Update the `valid` counter accordingly.
5. Return the answer substring, or empty string if no window was found.

## A solution in Javascript

```javascript
function minWindow(s, t) {
    const need = new Map();
    const window = new Map();

    for (const c of t) {
        need.set(c, (need.get(c) || 0) + 1);
    }

    let left = 0, right = 0;
    let valid = 0;
    let start = 0, length = Infinity;

    while (right < s.length) {
        const c = s[right];
        right++;
        if (need.has(c)) {
            window.set(c, (window.get(c) || 0) + 1);
            if (window.get(c) <= need.get(c)) valid++;
        }

        while (valid === t.length) {
            if (right - left < length) {
                start = left;
                length = right - left;
            }

            const d = s[left];
            left++;
            if (need.has(d)) {
                if (window.get(d) <= need.get(d)) valid--;
                window.set(d, window.get(d) - 1);
            }
        }
    }
    return length === Infinity ? "" : s.substring(start, start + length);
}
```
The algorithm uses a sliding window approach to find the minimum window substring. We use two pointers, `left` and `right`, to represent the current window.

1. Initialize an unordered_map or dictionary for `need` to store characters and their counts in `t`, and another for `window` to store characters and their counts in the current window.
2. Initialize `left` and `right` pointers, `valid` counter for keeping track of characters satisfying the criteria, and `start` and `length` for holding the answer substring information.
3. Iterate through the string `s` using the `right` pointer, and:
    - If the current character exists in the `need` map, update the count of the character in the `window` map, and increment `valid` if the count in the window is less than or equal to the count in need.
4. Check the validity by comparing `valid` with the length of `t`.
    - If valid, update the answer substring's `start` and `length` if the current window's length is less than the current minimum.
    - Then, increment the `left` pointer to slide the window until the current character count in the window goes below the count in `need`. Update the `valid` counter accordingly.
5. Return the answer substring, or empty string if no window was found.


# Combinations

- slug: combinations
- difficulty: Medium

Given two integers `n` and `k`, return _all possible combinations of_ `k` _numbers chosen from the range_ `[1, n]`.

You may return the answer in **any order**.

**Example 1:**

**Input:** n = 4, k = 2
**Output:** \[\[1,2\],\[1,3\],\[1,4\],\[2,3\],\[2,4\],\[3,4\]\]
**Explanation:** There are 4 choose 2 = 6 total combinations.
Note that combinations are unordered, i.e., \[1,2\] and \[2,1\] are considered to be the same combination.

**Example 2:**

**Input:** n = 1, k = 1
**Output:** \[\[1\]\]
**Explanation:** There is 1 choose 1 = 1 total combination.

**Constraints:**

*   `1 <= n <= 20`
*   `1 <= k <= n`

## A solution in Java

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

public List<List<Integer>> combine(int n, int k) {
    List<List<Integer>> result = new ArrayList<>();
    backtrack(n, k, 1, new ArrayList<>(), result);
    return result;
}

private void backtrack(int n, int k, int start, List<Integer> current, List<List<Integer>> result) {
    if (current.size() == k) {
        result.add(new ArrayList<>(current));
        return;
    }

    for (int i = start; i <= n; i++) {
        current.add(i);
        backtrack(n, k, i + 1, current, result);
        current.remove(current.size() - 1);
    }
}
```
The algorithm uses a backtracking approach to generate all possible combinations of k numbers out of the range [1, n]. We create a helper function called `backtrack` that recursively generates combinations. In this helper function, we have a base case where if the size of the current combination is equal to k, we add it to the result. Otherwise, we iterate through the numbers from the start index to n, add the current number to the current combination, and make a recursive call with an incremented start index. After the call, we "undo" the decision by removing the number from the current combination (backtracking).

The main function initializes an empty result list, calls the `backtrack` function with a start index of 1 and an empty current combination list, and then returns the result list.

## A solution in C++

```cpp
#include <vector>

void backtrack(int n, int k, int start, std::vector<int>& current, std::vector<std::vector<int>>& result) {
    if (current.size() == k) {
        result.push_back(current);
        return;
    }

    for (int i = start; i <= n; ++i) {
        current.push_back(i);
        backtrack(n, k, i + 1, current, result);
        current.pop_back();
    }
}

std::vector<std::vector<int>> combine(int n, int k) {
    std::vector<std::vector<int>> result;
    std::vector<int> current;
    backtrack(n, k, 1, current, result);
    return result;
}
```
The algorithm uses a backtracking approach to generate all possible combinations of k numbers out of the range [1, n]. We create a helper function called `backtrack` that recursively generates combinations. In this helper function, we have a base case where if the size of the current combination is equal to k, we add it to the result. Otherwise, we iterate through the numbers from the start index to n, add the current number to the current combination, and make a recursive call with an incremented start index. After the call, we "undo" the decision by removing the number from the current combination (backtracking).

The main function initializes an empty result list, calls the `backtrack` function with a start index of 1 and an empty current combination list, and then returns the result list.

## A solution in Python

```python
from typing import List

def combine(n: int, k: int) -> List[List[int]]:
    def backtrack(start, current_combination):
        if len(current_combination) == k:
            result.append(current_combination[:])

        for i in range(start, n + 1):
            current_combination.append(i)
            backtrack(i + 1, current_combination)
            current_combination.pop()

    result = []
    backtrack(1, [])
    return result
```
The algorithm uses a backtracking approach to generate all possible combinations of k numbers out of the range [1, n]. We create a helper function called `backtrack` that recursively generates combinations. In this helper function, we have a base case where if the size of the current combination is equal to k, we add it to the result. Otherwise, we iterate through the numbers from the start index to n, add the current number to the current combination, and make a recursive call with an incremented start index. After the call, we "undo" the decision by removing the number from the current combination (backtracking).

The main function initializes an empty result list, calls the `backtrack` function with a start index of 1 and an empty current combination list, and then returns the result list.

## A solution in Javascript

```javascript
function combine(n, k) {
    const result = [];
    backtrack(n, k, 1, [], result);
    return result;
}

function backtrack(n, k, start, current, result) {
    if (current.length === k) {
        result.push([...current]);
        return;
    }

    for (let i = start; i <= n; i++) {
        current.push(i);
        backtrack(n, k, i + 1, current, result);
        current.pop();
    }
}
```
The algorithm uses a backtracking approach to generate all possible combinations of k numbers out of the range [1, n]. We create a helper function called `backtrack` that recursively generates combinations. In this helper function, we have a base case where if the size of the current combination is equal to k, we add it to the result. Otherwise, we iterate through the numbers from the start index to n, add the current number to the current combination, and make a recursive call with an incremented start index. After the call, we "undo" the decision by removing the number from the current combination (backtracking).

The main function initializes an empty result list, calls the `backtrack` function with a start index of 1 and an empty current combination list, and then returns the result list.


# Subsets

- slug: subsets
- difficulty: Medium

Given an integer array `nums` of **unique** elements, return _all possible_ _subsets_ _(the power set)_.

The solution set **must not** contain duplicate subsets. Return the solution in **any order**.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

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

## A solution in Java

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

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> result = new ArrayList<>();
    int n = nums.length;
    int num_subsets = 1 << n;

    for (int i = 0; i < num_subsets; ++i) {
        List<Integer> subset = new ArrayList<>();
        for (int j = 0; j < n; ++j) {
            if ((i & (1 << j)) != 0) {
                subset.add(nums[j]);
            }
        }
        result.add(subset);
    }
    return result;
}
```
1. Calculate the number of subsets in the power set (2^n) using bit manipulation.
2. Loop through all numbers from 0 to 2^n - 1.
3. For each number, loop through its bits, and if the bit is set (1), include the corresponding element from the input array in the current subset.
4. Add the current subset to the result list.
5. After the loops finish, return the result list containing all subsets.

## A solution in C++

```cpp
#include <vector>

std::vector<std::vector<int>> subsets(std::vector<int>& nums) {
    std::vector<std::vector<int>> result;
    int n = nums.size();
    int num_subsets = 1 << n;

    for (int i = 0; i < num_subsets; ++i) {
        std::vector<int> subset;
        for (int j = 0; j < n; ++j) {
            if (i & (1 << j)) {
                subset.push_back(nums[j]);
            }
        }
        result.push_back(subset);
    }
    return result;
}
```
1. Calculate the number of subsets in the power set (2^n) using bit manipulation.
2. Loop through all numbers from 0 to 2^n - 1.
3. For each number, loop through its bits, and if the bit is set (1), include the corresponding element from the input array in the current subset.
4. Add the current subset to the result list.
5. After the loops finish, return the result list containing all subsets.

## A solution in Python

```python
def subsets(nums):
    n = len(nums)
    num_subsets = 1 << n
    result = []

    for i in range(num_subsets):
        subset = []
        for j in range(n):
            if i & (1 << j):
                subset.append(nums[j])
        result.append(subset)
    return result
```
1. Calculate the number of subsets in the power set (2^n) using bit manipulation.
2. Loop through all numbers from 0 to 2^n - 1.
3. For each number, loop through its bits, and if the bit is set (1), include the corresponding element from the input array in the current subset.
4. Add the current subset to the result list.
5. After the loops finish, return the result list containing all subsets.

## A solution in Javascript

```javascript
function subsets(nums) {
    let result = [];
    let n = nums.length;
    let num_subsets = 1 << n;

    for (let i = 0; i < num_subsets; ++i) {
        let subset = [];
        for (let j = 0; j < n; ++j) {
            if (i & (1 << j)) {
                subset.push(nums[j]);
            }
        }
        result.push(subset);
    }
    return result;
}
```
1. Calculate the number of subsets in the power set (2^n) using bit manipulation.
2. Loop through all numbers from 0 to 2^n - 1.
3. For each number, loop through its bits, and if the bit is set (1), include the corresponding element from the input array in the current subset.
4. Add the current subset to the result list.
5. After the loops finish, return the result list containing all subsets.


# Word Search

- slug: word-search
- difficulty: Medium

Given an `m x n` grid of characters `board` and a string `word`, return `true` _if_ `word` _exists in the grid_.

The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.

**Example 1:**

**Input:** board = \[\[ "A ", "B ", "C ", "E "\],\[ "S ", "F ", "C ", "S "\],\[ "A ", "D ", "E ", "E "\]\], word =  "ABCCED "
**Output:** true

**Example 2:**

**Input:** board = \[\[ "A ", "B ", "C ", "E "\],\[ "S ", "F ", "C ", "S "\],\[ "A ", "D ", "E ", "E "\]\], word =  "SEE "
**Output:** true

**Example 3:**

**Input:** board = \[\[ "A ", "B ", "C ", "E "\],\[ "S ", "F ", "C ", "S "\],\[ "A ", "D ", "E ", "E "\]\], word =  "ABCB "
**Output:** false

**Constraints:**

*   `m == board.length`
*   `n = board[i].length`
*   `1 <= m, n <= 6`
*   `1 <= word.length <= 15`
*   `board` and `word` consists of only lowercase and uppercase English letters.

**Follow up:** Could you use search pruning to make your solution faster with a larger `board`?

## A solution in Java

```java
public boolean exist(char[][] board, String word) {
    int m = board.length;
    int n = board[0].length;

    boolean[][] visited = new boolean[m][n];

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (dfs(board, i, j, 0, word, visited)) {
                return true;
            }
        }
    }
    return false;
}

private boolean dfs(char[][] board, int i, int j, int k, String word, boolean[][] visited) {
    if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(k) || visited[i][j]) {
        return false;
    }

    if (k == word.length() - 1) {
        return true;
    }

    visited[i][j] = true;
    boolean result = dfs(board, i + 1, j, k + 1, word, visited)
            || dfs(board, i - 1, j, k + 1, word, visited)
            || dfs(board, i, j + 1, k + 1, word, visited)
            || dfs(board, i, j - 1, k + 1, word, visited);
    visited[i][j] = false;

    return result;
}
```
For each of the implementation above, we use a Depth-First Search (DFS) based algorithm to traverse the grid board. The DFS function takes the current cell index i and j and the index of the character in the input word that we are looking for (k).

The base cases are:
- If the cell indexes i or j are out of boundaries, or the board[i][j] character does not match word[k], return false.
- If k (current character index) is equal to word.length - 1, we find the word in the grid, so return true.

For each cell, we run the DFS function with the given input parameters. If DFS returns true (found the word), the whole function will return true.

## A solution in C++

```cpp
bool exist(vector<vector<char>>& board, string word) {
    int m = board.size();
    int n = board[0].size();

    function<bool(int, int, int)> dfs = [&](int i, int j, int k) {
        if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[k])
            return false;
        if (k == word.length() - 1)
            return true;

        char temp = board[i][j];
        board[i][j] = '/';
        bool res = dfs(i + 1, j, k + 1) || dfs(i - 1, j, k + 1) || dfs(i, j + 1, k + 1) || dfs(i, j - 1, k + 1);
        board[i][j] = temp;
        return res;
    };

    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            if (dfs(i, j, 0))
                return true;
    return false;
}
```
For each of the implementation above, we use a Depth-First Search (DFS) based algorithm to traverse the grid board. The DFS function takes the current cell index i and j and the index of the character in the input word that we are looking for (k).

The base cases are:
- If the cell indexes i or j are out of boundaries, or the board[i][j] character does not match word[k], return false.
- If k (current character index) is equal to word.length - 1, we find the word in the grid, so return true.

For each cell, we run the DFS function with the given input parameters. If DFS returns true (found the word), the whole function will return true.

## A solution in Python

```python
def exist(board, word):
    m, n = len(board), len(board[0])

    def dfs(i, j, k):
        if not 0 <= i < m or not 0 <= j < n or board[i][j] != word[k]:
            return False
        if k == len(word) - 1:
            return True

        tmp, board[i][j] = board[i][j], '/'
        res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
        board[i][j] = tmp
        return res

    for i in range(m):
        for j in range(n):
            if dfs(i, j, 0):
                return True
    return False
```
For each of the implementation above, we use a Depth-First Search (DFS) based algorithm to traverse the grid board. The DFS function takes the current cell index i and j and the index of the character in the input word that we are looking for (k).

The base cases are:
- If the cell indexes i or j are out of boundaries, or the board[i][j] character does not match word[k], return false.
- If k (current character index) is equal to word.length - 1, we find the word in the grid, so return true.

For each cell, we run the DFS function with the given input parameters. If DFS returns true (found the word), the whole function will return true.

## A solution in Javascript

```javascript
function exist(board, word) {
    const m = board.length;
    const n = board[0].length;

    function dfs(i, j, k) {
        if (i < 0 || i === m || j < 0 || j === n || board[i][j] !== word[k])
            return false;
        if (k === word.length - 1)
            return true;

        const temp = board[i][j];
        board[i][j] = '/';
        const res = dfs(i + 1, j, k +1) || dfs(i - 1, j, k + 1) || dfs(i, j + 1, k + 1) || dfs(i, j - 1, k + 1);
        board[i][j] = temp;
        return res;
    }

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (dfs(i, j, 0))
                return true;
        }
    }
    return false;
}
```
For each of the implementation above, we use a Depth-First Search (DFS) based algorithm to traverse the grid board. The DFS function takes the current cell index i and j and the index of the character in the input word that we are looking for (k).

The base cases are:
- If the cell indexes i or j are out of boundaries, or the board[i][j] character does not match word[k], return false.
- If k (current character index) is equal to word.length - 1, we find the word in the grid, so return true.

For each cell, we run the DFS function with the given input parameters. If DFS returns true (found the word), the whole function will return true.


# Remove Duplicates from Sorted Array II

- slug: remove-duplicates-from-sorted-array-ii
- difficulty: Medium

Given an integer array `nums` sorted in **non-decreasing order**, remove some duplicates [**in-place**](https://en.wikipedia.org/wiki/In-place_algorithm) such that each unique element appears **at most twice**. The **relative order** of the elements should be kept the **same**.

Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the **first part** of the array `nums`. More formally, if there are `k` elements after removing the duplicates, then the first `k` elements of `nums` should hold the final result. It does not matter what you leave beyond the first `k` elements.

Return `k` _after placing the final result in the first_ `k` _slots of_ `nums`.

Do **not** allocate extra space for another array. You must do this by **modifying the input array [in-place](https://en.wikipedia.org/wiki/In-place_algorithm)** with O(1) extra memory.

**Custom Judge:**

The judge will test your solution with the following code:

int\[\] nums = \[...\]; // Input array
int\[\] expectedNums = \[...\]; // The expected answer with correct length

int k = removeDuplicates(nums); // Calls your implementation

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums\[i\] == expectedNums\[i\];
}

If all assertions pass, then your solution will be **accepted**.

**Example 1:**

**Input:** nums = \[1,1,1,2,2,3\]
**Output:** 5, nums = \[1,1,2,2,3,\_\]
**Explanation:** Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

**Example 2:**

**Input:** nums = \[0,0,1,1,1,1,2,3,3\]
**Output:** 7, nums = \[0,0,1,1,2,3,3,\_,\_\]
**Explanation:** Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

**Constraints:**

*   `1 <= nums.length <= 3 * 104`
*   `-104 <= nums[i] <= 104`
*   `nums` is sorted in **non-decreasing** order.

## A solution in Java

```java
public int removeDuplicates(int[] nums) {
    int i = 0;
    for (int num : nums) {
        if (i < 2 || num > nums[i - 2]) {
            nums[i++] = num;
        }
    }
    return i;
}
```
The algorithm uses a two-pointer technique. The variable `i` represents the pointer to the position in the array where the next unique element will be placed. For each element in the input array, we check if either `i < 2` (meaning we haven't encountered 2 unique elements yet) or the current element (`num`) is greater than the element in the array at index `i - 2` (this condition ensures that the current element appears at most twice in the array). If either of these conditions are true, we place the current element at index `i` and increment `i`. The function returns the value of `i` at the end, which represents the length of the modified array after removing duplicates.

## A solution in C++

```cpp
int removeDuplicates(vector<int>& nums) {
    int i = 0;
    for (int num : nums) {
        if (i < 2 || num > nums[i - 2]) {
            nums[i++] = num;
        }
    }
    return i;
}
```
The algorithm uses a two-pointer technique. The variable `i` represents the pointer to the position in the array where the next unique element will be placed. For each element in the input array, we check if either `i < 2` (meaning we haven't encountered 2 unique elements yet) or the current element (`num`) is greater than the element in the array at index `i - 2` (this condition ensures that the current element appears at most twice in the array). If either of these conditions are true, we place the current element at index `i` and increment `i`. The function returns the value of `i` at the end, which represents the length of the modified array after removing duplicates.

## A solution in Python

```python
def remove_duplicates(nums):
    i = 0
    for num in nums:
        if i < 2 or num > nums[i - 2]:
            nums[i] = num
            i += 1
    return i
```
The algorithm uses a two-pointer technique. The variable `i` represents the pointer to the position in the array where the next unique element will be placed. For each element in the input array, we check if either `i < 2` (meaning we haven't encountered 2 unique elements yet) or the current element (`num`) is greater than the element in the array at index `i - 2` (this condition ensures that the current element appears at most twice in the array). If either of these conditions are true, we place the current element at index `i` and increment `i`. The function returns the value of `i` at the end, which represents the length of the modified array after removing duplicates.

## A solution in Javascript

```javascript
function removeDuplicates(nums) {
    let i = 0;
    for (let num of nums) {
        if (i < 2 || num > nums[i - 2]) {
            nums[i++] = num;
        }
    }
    return i;
}
```
The algorithm uses a two-pointer technique. The variable `i` represents the pointer to the position in the array where the next unique element will be placed. For each element in the input array, we check if either `i < 2` (meaning we haven't encountered 2 unique elements yet) or the current element (`num`) is greater than the element in the array at index `i - 2` (this condition ensures that the current element appears at most twice in the array). If either of these conditions are true, we place the current element at index `i` and increment `i`. The function returns the value of `i` at the end, which represents the length of the modified array after removing duplicates.


# Search in Rotated Sorted Array II

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

There is an integer array `nums` sorted in non-decreasing order (not necessarily with **distinct** values).

Before being passed to your function, `nums` is **rotated** at an unknown pivot index `k` (`0 <= 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,4,4,5,6,6,7]` might be rotated at pivot index `5` and become `[4,5,6,6,7,0,1,2,4,4]`.

Given the array `nums` **after** the rotation and an integer `target`, return `true` _if_ `target` _is in_ `nums`_, or_ `false` _if it is not in_ `nums`_._

You must decrease the overall operation steps as much as possible.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `1 <= nums.length <= 5000`
*   `-104 <= nums[i] <= 104`
*   `nums` is guaranteed to be rotated at some pivot.
*   `-104 <= target <= 104`

**Follow up:** This problem is similar to Search in Rotated Sorted Array, but `nums` may contain **duplicates**. Would this affect the runtime complexity? How and why?

## A solution in Java

```java
public boolean 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 true;

        if (nums[mid] == nums[left]) {
            left++;
        } else if (nums[mid] > nums[left]) {
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return false;
}
```
The algorithm is based on a modified binary search. We start by setting two pointers named `left` and `right` at the first and last element of the array, respectively. We then enter a loop, which continues until the `left` pointer is less than or equal to the `right` pointer.

Inside the loop, we first calculate the middle index `mid` using the `left` and `right` pointers. If the middle element of the array is equal to the target, we return true, indicating that the target is found.

If the middle element is equal to the left element, we increment the `left` pointer. If the middle element is greater than the left element, we check if the target is within the left and middle elements. If it is, we set the `right` pointer to the middle index minus one. Otherwise, we set the `left` pointer to the middle index plus one.

If the middle element is still smaller than the left element, we then check if the target is within the middle and right elements. If it is, we set the `left` pointer to the middle index plus one. Otherwise, we set the `right` pointer to the middle index minus one.

After the loop, we return false if the target is not found in the array.

## A solution in C++

```cpp
bool 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 true;

        if (nums[mid] == nums[left]) {
            left++;
        } else if (nums[mid] > nums[left]) {
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return false;
}
```
The algorithm is based on a modified binary search. We start by setting two pointers named `left` and `right` at the first and last element of the array, respectively. We then enter a loop, which continues until the `left` pointer is less than or equal to the `right` pointer.

Inside the loop, we first calculate the middle index `mid` using the `left` and `right` pointers. If the middle element of the array is equal to the target, we return true, indicating that the target is found.

If the middle element is equal to the left element, we increment the `left` pointer. If the middle element is greater than the left element, we check if the target is within the left and middle elements. If it is, we set the `right` pointer to the middle index minus one. Otherwise, we set the `left` pointer to the middle index plus one.

If the middle element is still smaller than the left element, we then check if the target is within the middle and right elements. If it is, we set the `left` pointer to the middle index plus one. Otherwise, we set the `right` pointer to the middle index minus one.

After the loop, we return false if the target is not found in the array.

## 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 True

        if nums[mid] == nums[left]:
            left += 1
        elif nums[mid] > nums[left]:
            if nums[left] <= target < nums[mid]:
                right = mid - 1
            else:
                left = mid + 1
        else:
            if nums[mid] < target <= nums[right]:
                left = mid + 1
            else:
                right = mid - 1
    return False
```
The algorithm is based on a modified binary search. We start by setting two pointers named `left` and `right` at the first and last element of the array, respectively. We then enter a loop, which continues until the `left` pointer is less than or equal to the `right` pointer.

Inside the loop, we first calculate the middle index `mid` using the `left` and `right` pointers. If the middle element of the array is equal to the target, we return true, indicating that the target is found.

If the middle element is equal to the left element, we increment the `left` pointer. If the middle element is greater than the left element, we check if the target is within the left and middle elements. If it is, we set the `right` pointer to the middle index minus one. Otherwise, we set the `left` pointer to the middle index plus one.

If the middle element is still smaller than the left element, we then check if the target is within the middle and right elements. If it is, we set the `left` pointer to the middle index plus one. Otherwise, we set the `right` pointer to the middle index minus one.

After the loop, we return false if the target is not found in the array.

## A solution in Javascript

```javascript
function search(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        const mid = left + Math.floor((right - left) / 2);
        if (nums[mid] === target) return true;

        if (nums[mid] === nums[left]) {
            left++;
        } else if (nums[mid] > nums[left]) {
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        } else {
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
    }
    return false;
}
```
The algorithm is based on a modified binary search. We start by setting two pointers named `left` and `right` at the first and last element of the array, respectively. We then enter a loop, which continues until the `left` pointer is less than or equal to the `right` pointer.

Inside the loop, we first calculate the middle index `mid` using the `left` and `right` pointers. If the middle element of the array is equal to the target, we return true, indicating that the target is found.

If the middle element is equal to the left element, we increment the `left` pointer. If the middle element is greater than the left element, we check if the target is within the left and middle elements. If it is, we set the `right` pointer to the middle index minus one. Otherwise, we set the `left` pointer to the middle index plus one.

If the middle element is still smaller than the left element, we then check if the target is within the middle and right elements. If it is, we set the `left` pointer to the middle index plus one. Otherwise, we set the `right` pointer to the middle index minus one.

After the loop, we return false if the target is not found in the array.