# Moving Average from Data Stream

- slug: moving-average-from-data-stream
- difficulty: Easy

Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.

Implement the `MovingAverage` class:

*   `MovingAverage(int size)` Initializes the object with the size of the window `size`.
*   `double next(int val)` Returns the moving average of the last `size` values of the stream.

**Example 1:**

**Input**
\[ "MovingAverage ",  "next ",  "next ",  "next ",  "next "\]
\[\[3\], \[1\], \[10\], \[3\], \[5\]\]
**Output**
\[null, 1.0, 5.5, 4.66667, 6.0\]

**Explanation**
MovingAverage movingAverage = new MovingAverage(3);
movingAverage.next(1); // return 1.0 = 1 / 1
movingAverage.next(10); // return 5.5 = (1 + 10) / 2
movingAverage.next(3); // return 4.66667 = (1 + 10 + 3) / 3
movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3

**Constraints:**

*   `1 <= size <= 1000`
*   `-105 <= val <= 105`
*   At most `104` calls will be made to `next`.

## A solution in Java

```java
import java.util.LinkedList;
import java.util.Queue;

class MovingAverage {
    private Queue<Integer> queue;
    private int maxSize;
    private double sum;

    public MovingAverage(int size) {
        queue = new LinkedList<>();
        maxSize = size;
        sum = 0.0;
    }

    public double next(int val) {
        if (queue.size() == maxSize) {
            sum -= queue.remove();
        }
        queue.add(val);
        sum += val;
        return sum / queue.size();
    }
}
```
The algorithm uses a queue to maintain a sliding window of the last `size` values of the stream. When a new value is added, the algorithm checks the size of the queue. If it equals `size`, the oldest value is removed from the front of the queue by updating the sum and popping it. Then, the new value is added to the back of the queue, and the sum is updated. The average is returned by dividing the sum by the number of values currently in the queue. The time complexity of the `next` function is O(1).

## A solution in C++

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

class MovingAverage {
public:
    queue<int> q;
    int maxSize;
    double sum;

    MovingAverage(int size) {
        maxSize = size;
        sum = 0;
    }

    double next(int val) {
        if (q.size() == maxSize) {
            sum -= q.front();
            q.pop();
        }
        q.push(val);
        sum += val;
        return sum / q.size();
    }
};
```
The algorithm uses a queue to maintain a sliding window of the last `size` values of the stream. When a new value is added, the algorithm checks the size of the queue. If it equals `size`, the oldest value is removed from the front of the queue by updating the sum and popping it. Then, the new value is added to the back of the queue, and the sum is updated. The average is returned by dividing the sum by the number of values currently in the queue. The time complexity of the `next` function is O(1).

## A solution in Python

```python
from collections import deque

class MovingAverage:
    def __init__(self, size: int):
        self.queue = deque()
        self.maxSize = size
        self.sum = 0.0

    def next(self, val: int) -> float:
        if len(self.queue) == self.maxSize:
            self.sum -= self.queue.popleft()
        self.queue.append(val)
        self.sum += val
        return self.sum / len(self.queue)
```
The algorithm uses a queue to maintain a sliding window of the last `size` values of the stream. When a new value is added, the algorithm checks the size of the queue. If it equals `size`, the oldest value is removed from the front of the queue by updating the sum and popping it. Then, the new value is added to the back of the queue, and the sum is updated. The average is returned by dividing the sum by the number of values currently in the queue. The time complexity of the `next` function is O(1).

## A solution in Javascript

```javascript
class MovingAverage {
    constructor(size) {
        this.queue = [];
        this.maxSize = size;
        this.sum = 0;
    }

    next(val) {
        if (this.queue.length === this.maxSize) {
            this.sum -= this.queue.shift();
        }
        this.queue.push(val);
        this.sum += val;
        return this.sum / this.queue.length;
    }
}
```
The algorithm uses a queue to maintain a sliding window of the last `size` values of the stream. When a new value is added, the algorithm checks the size of the queue. If it equals `size`, the oldest value is removed from the front of the queue by updating the sum and popping it. Then, the new value is added to the back of the queue, and the sum is updated. The average is returned by dividing the sum by the number of values currently in the queue. The time complexity of the `next` function is O(1).


# Top K Frequent Elements

- slug: top-k-frequent-elements
- difficulty: Medium

Given an integer array `nums` and an integer `k`, return _the_ `k` _most frequent elements_. You may return the answer in **any order**.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `1 <= nums.length <= 105`
*   `-104 <= nums[i] <= 104`
*   `k` is in the range `[1, the number of unique elements in the array]`.
*   It is **guaranteed** that the answer is **unique**.

**Follow up:** Your algorithm's time complexity must be better than `O(n log n)`, where n is the array's size.

## A solution in Java

```java
import java.util.*;

public List<Integer> kMostFrequent(int[] nums, int k) {
    Map<Integer, Integer> frequency = new HashMap<>();
    for (int num : nums) {
        frequency.put(num, frequency.getOrDefault(num, 0) + 1);
    }

    PriorityQueue<Map.Entry<Integer, Integer>> min_heap = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
    for (Map.Entry<Integer, Integer> entry : frequency.entrySet()) {
        min_heap.offer(entry);
        if (min_heap.size() > k) {
            min_heap.poll();
        }
    }

    List<Integer> result = new ArrayList<>();
    while (!min_heap.isEmpty()) {
        result.add(min_heap.poll().getKey());
    }
    return result;
}
```
1. We use a hash map or dictionary to store the frequency of each element in the given input array.
2. We create a min-heap and insert the elements in it as pairs of frequency and number itself.
3. Whenever the size of the min-heap exceeds 'k', we pop the element with minimum frequency from the heap.
4. After inserting all elements in the heap, the final heap will contain 'k' most frequent elements.
5. We then return the elements in the min-heap and disregard their frequency. This is done using lists or arrays.

## A solution in C++

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

vector<int> kMostFrequent(vector<int>& nums, int k) {
    unordered_map<int, int> frequency;
    for (int num : nums) {
        frequency[num]++;
    }

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> min_heap;
    for (const auto& entry : frequency) {
        min_heap.push({entry.second, entry.first});
        if (min_heap.size() > k) {
            min_heap.pop();
        }
    }

    vector<int> result;
    while (!min_heap.empty()) {
        result.push_back(min_heap.top().second);
        min_heap.pop();
    }

    return result;
}
```
1. We use a hash map or dictionary to store the frequency of each element in the given input array.
2. We create a min-heap and insert the elements in it as pairs of frequency and number itself.
3. Whenever the size of the min-heap exceeds 'k', we pop the element with minimum frequency from the heap.
4. After inserting all elements in the heap, the final heap will contain 'k' most frequent elements.
5. We then return the elements in the min-heap and disregard their frequency. This is done using lists or arrays.

## A solution in Python

```python
from heapq import heappush, heappop
from collections import Counter

def k_most_frequent(nums, k):
    frequency = Counter(nums)
    min_heap = []

    for num, freq in frequency.items():
        heappush(min_heap, (freq, num))
        if len(min_heap) > k:
            heappop(min_heap)

    return [heappop(min_heap)[1] for _ in range(k)]
```
1. We use a hash map or dictionary to store the frequency of each element in the given input array.
2. We create a min-heap and insert the elements in it as pairs of frequency and number itself.
3. Whenever the size of the min-heap exceeds 'k', we pop the element with minimum frequency from the heap.
4. After inserting all elements in the heap, the final heap will contain 'k' most frequent elements.
5. We then return the elements in the min-heap and disregard their frequency. This is done using lists or arrays.

## A solution in Javascript

```javascript
function kMostFrequent(nums, k) {
  const frequency = new Map();
  for (const num of nums) {
    frequency.set(num, (frequency.get(num) || 0) + 1);
  }

  const minHeap = [];

  for (const [num, freq] of frequency) {
    minHeap.push([freq, num]);
    if (minHeap.length > k) {
      minHeap.sort((a, b) => a[0] - b[0]).shift();
    }
  }

  return minHeap.map(entry => entry[1]);
}
```
1. We use a hash map or dictionary to store the frequency of each element in the given input array.
2. We create a min-heap and insert the elements in it as pairs of frequency and number itself.
3. Whenever the size of the min-heap exceeds 'k', we pop the element with minimum frequency from the heap.
4. After inserting all elements in the heap, the final heap will contain 'k' most frequent elements.
5. We then return the elements in the min-heap and disregard their frequency. This is done using lists or arrays.


# Design Tic-Tac-Toe

- slug: design-tic-tac-toe
- difficulty: Medium

Assume the following rules are for the tic-tac-toe game on an `n x n` board between two players:

1.  A move is guaranteed to be valid and is placed on an empty block.
2.  Once a winning condition is reached, no more moves are allowed.
3.  A player who succeeds in placing `n` of their marks in a horizontal, vertical, or diagonal row wins the game.

Implement the `TicTacToe` class:

*   `TicTacToe(int n)` Initializes the object the size of the board `n`.
*   `int move(int row, int col, int player)` Indicates that the player with id `player` plays at the cell `(row, col)` of the board. The move is guaranteed to be a valid move, and the two players alternate in making moves. Return
    *   `0` if there is **no winner** after the move,
    *   `1` if **player 1** is the winner after the move, or
    *   `2` if **player 2** is the winner after the move.

**Example 1:**

**Input**
\[ "TicTacToe ",  "move ",  "move ",  "move ",  "move ",  "move ",  "move ",  "move "\]
\[\[3\], \[0, 0, 1\], \[0, 2, 2\], \[2, 2, 1\], \[1, 1, 2\], \[2, 0, 1\], \[1, 0, 2\], \[2, 1, 1\]\]
**Output**
\[null, 0, 0, 0, 0, 0, 0, 1\]

**Explanation**
TicTacToe ticTacToe = new TicTacToe(3);
Assume that player 1 is  "X " and player 2 is  "O " in the board.
ticTacToe.move(0, 0, 1); // return 0 (no one wins)
|X| | |
| | | |    // Player 1 makes a move at (0, 0).
| | | |

ticTacToe.move(0, 2, 2); // return 0 (no one wins)
|X| |O|
| | | |    // Player 2 makes a move at (0, 2).
| | | |

ticTacToe.move(2, 2, 1); // return 0 (no one wins)
|X| |O|
| | | |    // Player 1 makes a move at (2, 2).
| | |X|

ticTacToe.move(1, 1, 2); // return 0 (no one wins)
|X| |O|
| |O| |    // Player 2 makes a move at (1, 1).
| | |X|

ticTacToe.move(2, 0, 1); // return 0 (no one wins)
|X| |O|
| |O| |    // Player 1 makes a move at (2, 0).
|X| |X|

ticTacToe.move(1, 0, 2); // return 0 (no one wins)
|X| |O|
|O|O| |    // Player 2 makes a move at (1, 0).
|X| |X|

ticTacToe.move(2, 1, 1); // return 1 (player 1 wins)
|X| |O|
|O|O| |    // Player 1 makes a move at (2, 1).
|X|X|X|

**Constraints:**

*   `2 <= n <= 100`
*   player is `1` or `2`.
*   `0 <= row, col < n`
*   `(row, col)` are **unique** for each different call to `move`.
*   At most `n2` calls will be made to `move`.

**Follow-up:** Could you do better than `O(n2)` per `move()` operation?

## A solution in Java

```java
class TicTacToe {
    int[] rows, cols;
    int diagonal, anti_diagonal, n;

    public TicTacToe(int n) {
        this.n = n;
        rows = new int[n];
        cols = new int[n];
        diagonal = 0;
        anti_diagonal = 0;
    }

    public int move(int row, int col, int player) {
        int toAdd = (player == 1) ? 1 : -1;

        rows[row] += toAdd;
        cols[col] += toAdd;

        if (row == col) diagonal += toAdd;
        if (row + col == n - 1) anti_diagonal += toAdd;

        if (Math.abs(rows[row]) == n ||
            Math.abs(cols[col]) == n ||
            Math.abs(diagonal) == n ||
            Math.abs(anti_diagonal) == n)
            return player;

        return 0;
    }
}
```
We can use four extra arrays (rows, cols, diagonal, and anti_diagonal) to keep track of the sum of the marks for each player (1 for player 1 and -1 for player 2) in each row, column, diagonal, and anti-diagonal. When the absolute value of any entry in these arrays becomes equal to `n`, we know that a player has won.

To implement the `move` function, we first determine the value `toAdd` as 1 if the player is 1 or -1 if the player is 2. Then, we update the corresponding row, col, diagonal (if row == col), and anti_diagonal (if row + col == n - 1) by adding `toAdd` to their respective values. Finally, we check if the absolute values of the updated entries are equal to `n`, and return the player number if the winning condition is met; otherwise, return 0. This solution has a time complexity of O(1) per `move` operation.

## A solution in C++

```cpp
class TicTacToe {
public:
    vector<int> rows, cols;
    int diagonal, anti_diagonal, n;

    TicTacToe(int n) {
        this->n = n;
        rows = vector<int>(n, 0);
        cols = vector<int>(n, 0);
        diagonal = 0;
        anti_diagonal = 0;
    }

    int move(int row, int col, int player) {
        int toAdd = (player == 1) ? 1 : -1;

        rows[row] += toAdd;
        cols[col] += toAdd;

        if (row == col) diagonal += toAdd;
        if (row + col == n - 1) anti_diagonal += toAdd;

        if (abs(rows[row]) == n ||
            abs(cols[col]) == n ||
            abs(diagonal) == n ||
            abs(anti_diagonal) == n)
            return player;

        return 0;
    }
};
```
We can use four extra arrays (rows, cols, diagonal, and anti_diagonal) to keep track of the sum of the marks for each player (1 for player 1 and -1 for player 2) in each row, column, diagonal, and anti-diagonal. When the absolute value of any entry in these arrays becomes equal to `n`, we know that a player has won.

To implement the `move` function, we first determine the value `toAdd` as 1 if the player is 1 or -1 if the player is 2. Then, we update the corresponding row, col, diagonal (if row == col), and anti_diagonal (if row + col == n - 1) by adding `toAdd` to their respective values. Finally, we check if the absolute values of the updated entries are equal to `n`, and return the player number if the winning condition is met; otherwise, return 0. This solution has a time complexity of O(1) per `move` operation.

## A solution in Python

```python
class TicTacToe:
    def __init__(self, n: int):
        self.rows, self.cols = [0] * n, [0] * n
        self.diagonal = self.anti_diagonal = self.n = n

    def move(self, row: int, col: int, player: int) -> int:
        to_add = 1 if player == 1 else -1

        self.rows[row] += to_add
        self.cols[col] += to_add

        if row == col:
            self.diagonal += to_add
        if row + col == self.n - 1:
            self.anti_diagonal += to_add

        if (abs(self.rows[row]) == self.n or abs(self.cols[col]) == self.n
                or abs(self.diagonal) == self.n or abs(self.anti_diagonal) == self.n):
            return player

        return 0
```
We can use four extra arrays (rows, cols, diagonal, and anti_diagonal) to keep track of the sum of the marks for each player (1 for player 1 and -1 for player 2) in each row, column, diagonal, and anti-diagonal. When the absolute value of any entry in these arrays becomes equal to `n`, we know that a player has won.

To implement the `move` function, we first determine the value `toAdd` as 1 if the player is 1 or -1 if the player is 2. Then, we update the corresponding row, col, diagonal (if row == col), and anti_diagonal (if row + col == n - 1) by adding `toAdd` to their respective values. Finally, we check if the absolute values of the updated entries are equal to `n`, and return the player number if the winning condition is met; otherwise, return 0. This solution has a time complexity of O(1) per `move` operation.

## A solution in Javascript

```javascript
class TicTacToe {
    constructor(n) {
        this.rows = new Array(n).fill(0);
        this.cols = new Array(n).fill(0);
        this.diagonal = 0;
        this.anti_diagonal = 0;
        this.n = n;
    }

    move(row, col, player) {
        const toAdd = player === 1 ? 1 : -1;

        this.rows[row] += toAdd;
        this.cols[col] += toAdd;

        if (row === col) this.diagonal += toAdd;
        if (row + col === this.n - 1) this.anti_diagonal += toAdd;

        if (Math.abs(this.rows[row]) === this.n ||
            Math.abs(this.cols[col]) === this.n ||
            Math.abs(this.diagonal) === this.n ||
            Math.abs(this.anti_diagonal) === this.n)
            return player;

        return 0;
    }
}
```
We can use four extra arrays (rows, cols, diagonal, and anti_diagonal) to keep track of the sum of the marks for each player (1 for player 1 and -1 for player 2) in each row, column, diagonal, and anti-diagonal. When the absolute value of any entry in these arrays becomes equal to `n`, we know that a player has won.

To implement the `move` function, we first determine the value `toAdd` as 1 if the player is 1 or -1 if the player is 2. Then, we update the corresponding row, col, diagonal (if row == col), and anti_diagonal (if row + col == n - 1) by adding `toAdd` to their respective values. Finally, we check if the absolute values of the updated entries are equal to `n`, and return the player number if the winning condition is met; otherwise, return 0. This solution has a time complexity of O(1) per `move` operation.


# Intersection of Two Arrays

- slug: intersection-of-two-arrays
- difficulty: Easy

Given two integer arrays `nums1` and `nums2`, return _an array of their intersection_. Each element in the result must be **unique** and you may return the result in **any order**.

**Example 1:**

**Input:** nums1 = \[1,2,2,1\], nums2 = \[2,2\]
**Output:** \[2\]

**Example 2:**

**Input:** nums1 = \[4,9,5\], nums2 = \[9,4,9,8,4\]
**Output:** \[9,4\]
**Explanation:** \[4,9\] is also accepted.

**Constraints:**

*   `1 <= nums1.length, nums2.length <= 1000`
*   `0 <= nums1[i], nums2[i] <= 1000`

## A solution in Java

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

public int[] intersection(int[] nums1, int[] nums2) {
    Set<Integer> set1 = new HashSet<>();
    for (int num : nums1) {
        set1.add(num);
    }

    Set<Integer> resultSet = new HashSet<>();
    for (int num : nums2) {
        if (set1.contains(num)) {
            resultSet.add(num);
        }
    }

    int[] result = new int[resultSet.size()];
    int i = 0;
    for (int num : resultSet) {
        result[i++] = num;
    }
    return result;
}
```
The function first creates a set `set1` from the first array `nums1`, which eliminates duplicate elements in it. Then, the function iterates through the second array `nums2`. For each element in `nums2`, it checks whether it exists in the `set1`. If so, this element is added to the result set `resultSet`. Finally, the result set is converted to an array and returned.

## A solution in C++

```cpp
#include <vector>
#include <set>

std::vector<int> intersection(std::vector<int>& nums1, std::vector<int>& nums2) {
    std::set<int> set1(nums1.begin(), nums1.end());
    std::set<int> result;
    for (int num : nums2) {
        if (set1.count(num)) {
            result.insert(num);
        }
    }
    return std::vector<int>(result.begin(), result.end());
}
```
The function first creates a set `set1` from the first array `nums1`, which eliminates duplicate elements in it. Then, the function iterates through the second array `nums2`. For each element in `nums2`, it checks whether it exists in the `set1`. If so, this element is added to the result set `resultSet`. Finally, the result set is converted to an array and returned.

## A solution in Python

```python
def intersection(nums1, nums2):
    set1 = set(nums1)
    result = set1.intersection(nums2)
    return list(result)
```
The function first creates a set `set1` from the first array `nums1`, which eliminates duplicate elements in it. Then, the function iterates through the second array `nums2`. For each element in `nums2`, it checks whether it exists in the `set1`. If so, this element is added to the result set `resultSet`. Finally, the result set is converted to an array and returned.

## A solution in Javascript

```javascript
function intersection(nums1, nums2) {
    const set1 = new Set(nums1);
    const resultSet = new Set();

    for (const num of nums2) {
        if (set1.has(num)) {
            resultSet.add(num);
        }
    }

    return Array.from(resultSet);
}
```
The function first creates a set `set1` from the first array `nums1`, which eliminates duplicate elements in it. Then, the function iterates through the second array `nums2`. For each element in `nums2`, it checks whether it exists in the `set1`. If so, this element is added to the result set `resultSet`. Finally, the result set is converted to an array and returned.


# Intersection of Two Arrays II

- slug: intersection-of-two-arrays-ii
- difficulty: Easy

Given two integer arrays `nums1` and `nums2`, return _an array of their intersection_. Each element in the result must appear as many times as it shows in both arrays and you may return the result in **any order**.

**Example 1:**

**Input:** nums1 = \[1,2,2,1\], nums2 = \[2,2\]
**Output:** \[2,2\]

**Example 2:**

**Input:** nums1 = \[4,9,5\], nums2 = \[9,4,9,8,4\]
**Output:** \[4,9\]
**Explanation:** \[9,4\] is also accepted.

**Constraints:**

*   `1 <= nums1.length, nums2.length <= 1000`
*   `0 <= nums1[i], nums2[i] <= 1000`

**Follow up:**

*   What if the given array is already sorted? How would you optimize your algorithm?
*   What if `nums1`'s size is small compared to `nums2`'s size? Which algorithm is better?
*   What if elements of `nums2` are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

## A solution in Java

```java
import java.util.ArrayList;
import java.util.HashMap;

public int[] intersect(int[] nums1, int[] nums2) {
    HashMap<Integer, Integer> countMap = new HashMap<>();
    ArrayList<Integer> result = new ArrayList<>();

    for (int num : nums1) {
        countMap.put(num, countMap.getOrDefault(num, 0) + 1);
    }

    for (int num : nums2) {
        if (countMap.getOrDefault(num, 0) > 0) {
            result.add(num);
            countMap.put(num, countMap.get(num) - 1);
        }
    }

    return result.stream().mapToInt(i -> i).toArray();
}
```
1. Create a hashmap (or dictionary) to count the occurrences of each integer in the first input array, nums1.
2. Iterate through the second input array, nums2.
   a. For each element in nums2, check if the element exists in the hashmap and has a count greater than 0.
   b. If yes, append the element to the result array and decrement the count in the hashmap for that element.
3. Return the result array containing the intersection elements.

## A solution in C++

```cpp
#include <vector>
#include <unordered_map>

std::vector<int> intersect(std::vector<int>& nums1, std::vector<int>& nums2) {
    std::unordered_map<int, int> count_map;
    std::vector<int> result;

    for (int num : nums1) {
        count_map[num]++;
    }

    for (int num : nums2) {
        if (count_map[num] > 0) {
            result.push_back(num);
            count_map[num]--;
        }
    }

    return result;
}
```
1. Create a hashmap (or dictionary) to count the occurrences of each integer in the first input array, nums1.
2. Iterate through the second input array, nums2.
   a. For each element in nums2, check if the element exists in the hashmap and has a count greater than 0.
   b. If yes, append the element to the result array and decrement the count in the hashmap for that element.
3. Return the result array containing the intersection elements.

## A solution in Python

```python
def intersect(nums1, nums2):
    count_map = {}
    result = []

    for num in nums1:
        count_map[num] = count_map.get(num, 0) + 1

    for num in nums2:
        if count_map.get(num, 0) > 0:
            result.append(num)
            count_map[num] -= 1

    return result
```
1. Create a hashmap (or dictionary) to count the occurrences of each integer in the first input array, nums1.
2. Iterate through the second input array, nums2.
   a. For each element in nums2, check if the element exists in the hashmap and has a count greater than 0.
   b. If yes, append the element to the result array and decrement the count in the hashmap for that element.
3. Return the result array containing the intersection elements.

## A solution in Javascript

```javascript
function intersect(nums1, nums2) {
    const countMap = {};
    const result = [];

    for (const num of nums1) {
        countMap[num] = (countMap[num] || 0) + 1;
    }

    for (const num of nums2) {
        if (countMap[num] > 0) {
            result.push(num);
            countMap[num]--;
        }
    }

    return result;
}
```
1. Create a hashmap (or dictionary) to count the occurrences of each integer in the first input array, nums1.
2. Iterate through the second input array, nums2.
   a. For each element in nums2, check if the element exists in the hashmap and has a count greater than 0.
   b. If yes, append the element to the result array and decrement the count in the hashmap for that element.
3. Return the result array containing the intersection elements.


# Android Unlock Patterns

- slug: android-unlock-patterns
- difficulty: Medium

Android devices have a special lock screen with a `3 x 3` grid of dots. Users can set an "unlock pattern " by connecting the dots in a specific sequence, forming a series of joined line segments where each segment's endpoints are two consecutive dots in the sequence. A sequence of `k` dots is a **valid** unlock pattern if both of the following are true:

*   All the dots in the sequence are **distinct**.
*   If the line segment connecting two consecutive dots in the sequence passes through the **center** of any other dot, the other dot **must have previously appeared** in the sequence. No jumps through the center non-selected dots are allowed.
    *   For example, connecting dots `2` and `9` without dots `5` or `6` appearing beforehand is valid because the line from dot `2` to dot `9` does not pass through the center of either dot `5` or `6`.
    *   However, connecting dots `1` and `3` without dot `2` appearing beforehand is invalid because the line from dot `1` to dot `3` passes through the center of dot `2`.

Here are some example valid and invalid unlock patterns:

*   The 1st pattern `[4,1,3,6]` is invalid because the line connecting dots `1` and `3` pass through dot `2`, but dot `2` did not previously appear in the sequence.
*   The 2nd pattern `[4,1,9,2]` is invalid because the line connecting dots `1` and `9` pass through dot `5`, but dot `5` did not previously appear in the sequence.
*   The 3rd pattern `[2,4,1,3,6]` is valid because it follows the conditions. The line connecting dots `1` and `3` meets the condition because dot `2` previously appeared in the sequence.
*   The 4th pattern `[6,5,4,1,9,2]` is valid because it follows the conditions. The line connecting dots `1` and `9` meets the condition because dot `5` previously appeared in the sequence.

Given two integers `m` and `n`, return _the **number of unique and valid unlock patterns** of the Android grid lock screen that consist of **at least**_ `m` _keys and **at most**_ `n` _keys._

Two unlock patterns are considered **unique** if there is a dot in one sequence that is not in the other, or the order of the dots is different.

**Example 1:**

**Input:** m = 1, n = 1
**Output:** 9

**Example 2:**

**Input:** m = 1, n = 2
**Output:** 65

**Constraints:**

*   `1 <= m, n <= 9`

## A solution in Java

```java
public int numberOfPatterns(int m, int n) {
    int[][] jumps = new int[10][10];
    jumps[1][3] = jumps[3][1] = 2;
    jumps[1][7] = jumps[7][1] = 4;
    jumps[3][9] = jumps[9][3] = 6;
    jumps[7][9] = jumps[9][7] = 8;
    jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5;

    boolean[] visited = new boolean[10];

    int cnt = 0;
    for (int i = m; i <= n; ++i) {
        cnt += dfs(jumps, visited, 1, i - 1) * 4; // 1, 3, 7, 9
        cnt += dfs(jumps, visited, 2, i - 1) * 4; // 2, 4, 6, 8
        cnt += dfs(jumps, visited, 5, i - 1);     // 5
    }

    return cnt;
}

private int dfs(int[][] jumps, boolean[] visited, int curr, int remaining) {
    if (remaining < 0) return 0;
    if (remaining == 0) return 1;

    visited[curr] = true;
    int cnt = 0;
    for (int next = 1; next <= 9; ++next) {
        if (!visited[next] && (jumps[curr][next] == 0 || visited[jumps[curr][next]])) {
            cnt += dfs(jumps, visited, next, remaining - 1);
        }
    }
    visited[curr] = false;

    return cnt;
}
```
The algorithm starts with a depth-first search (DFS) approach to explore all the possible combinations of the unlock patterns. We create a `jumps` matrix to store the condition that if a line segment between any two points passes through another point, the number in the `jumps` matrix represents the middle point.

The DFS function starts at a certain point and recursively explores all the possible points that can be reached according to the rules. It keeps track of visited points using the `visited` array. The DFS function returns the count of valid patterns for the range of `m` to `n`.

For each iteration from `m` to `n`, we calculate the number of valid unlock patterns, and we multiply the results by 4 since the grid is symmetric (e.g., patterns starting with 1, 3, 7, 9 are equivalent, and patterns starting with 2, 4, 6, 8 are equivalent). We do this for each corner and side midpoints separately. Finally, we add the count for the center point (5), and return the total count.

## A solution in C++

```cpp
int numberOfPatterns(int m, int n) {
    const vector<vector<int>> jumps(10, vector<int>(10, 0));
    jumps[1][3] = jumps[3][1] = 2;
    jumps[1][7] = jumps[7][1] = 4;
    jumps[3][9] = jumps[9][3] = 6;
    jumps[7][9] = jumps[9][7] = 8;
    jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5;

    vector<bool> visited(10, false);

    int cnt = 0;
    for (int i = m; i <= n; ++i) {
        cnt += dfs(jumps, visited, 1, i - 1) * 4; // 1, 3, 7, 9
        cnt += dfs(jumps, visited, 2, i - 1) * 4; // 2, 4, 6, 8
        cnt += dfs(jumps, visited, 5, i - 1);     // 5
    }

    return cnt;
}

int dfs(const vector<vector<int>>& jumps, vector<bool>& visited, int curr, int remaining) {
    if (remaining < 0) return 0;
    if (remaining == 0) return 1;

    visited[curr] = true;
    int cnt = 0;
    for (int next = 1; next <= 9; ++next) {
        if (!visited[next] && (jumps[curr][next] == 0 || visited[jumps[curr][next]])) {
            cnt += dfs(jumps, visited, next, remaining - 1);
        }
    }
    visited[curr] = false;

    return cnt;
}
```
The algorithm starts with a depth-first search (DFS) approach to explore all the possible combinations of the unlock patterns. We create a `jumps` matrix to store the condition that if a line segment between any two points passes through another point, the number in the `jumps` matrix represents the middle point.

The DFS function starts at a certain point and recursively explores all the possible points that can be reached according to the rules. It keeps track of visited points using the `visited` array. The DFS function returns the count of valid patterns for the range of `m` to `n`.

For each iteration from `m` to `n`, we calculate the number of valid unlock patterns, and we multiply the results by 4 since the grid is symmetric (e.g., patterns starting with 1, 3, 7, 9 are equivalent, and patterns starting with 2, 4, 6, 8 are equivalent). We do this for each corner and side midpoints separately. Finally, we add the count for the center point (5), and return the total count.

## A solution in Python

```python
def numberOfPatterns(m: int, n: int) -> int:
    def dfs(curr, remaining):
        if remaining < 0:
            return 0
        if remaining == 0:
            return 1

        visited[curr] = True
        cnt = 0
        for next in range(1, 10):
            if not visited[next] and (jumps[curr][next] == 0 or visited[jumps[curr][next]]):
                cnt += dfs(next, remaining - 1)
        visited[curr] = False

        return cnt

    jumps = [[0] * 10 for _ in range(10)]
    jumps[1][3] = jumps[3][1] = 2
    jumps[1][7] = jumps[7][1] = 4
    jumps[3][9] = jumps[9][3] = 6
    jumps[7][9] = jumps[9][7] = 8
    jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5

    visited = [False] * 10

    cnt = 0
    for i in range(m, n + 1):
        cnt += dfs(1, i - 1) * 4  # 1, 3, 7, 9
        cnt += dfs(2, i - 1) * 4  # 2, 4, 6, 8
        cnt += dfs(5, i - 1)      # 5

    return cnt
```
The algorithm starts with a depth-first search (DFS) approach to explore all the possible combinations of the unlock patterns. We create a `jumps` matrix to store the condition that if a line segment between any two points passes through another point, the number in the `jumps` matrix represents the middle point.

The DFS function starts at a certain point and recursively explores all the possible points that can be reached according to the rules. It keeps track of visited points using the `visited` array. The DFS function returns the count of valid patterns for the range of `m` to `n`.

For each iteration from `m` to `n`, we calculate the number of valid unlock patterns, and we multiply the results by 4 since the grid is symmetric (e.g., patterns starting with 1, 3, 7, 9 are equivalent, and patterns starting with 2, 4, 6, 8 are equivalent). We do this for each corner and side midpoints separately. Finally, we add the count for the center point (5), and return the total count.

## A solution in Javascript

```javascript
var numberOfPatterns = function(m, n) {
    const jumps = Array.from({length: 10}, () => Array(10).fill(0));
    jumps[1][3] = jumps[3][1] = 2;
    jumps[1][7] = jumps[7][1] = 4;
    jumps[3][9] = jumps[9][3] = 6;
    jumps[7][9] = jumps[9][7] = 8;
    jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5;

    const visited = Array(10).fill(false);

    let cnt = 0;
    for (let i = m; i <= n; ++i) {
        cnt += dfs(jumps, visited, 1, i - 1) * 4; // 1, 3, 7, 9
        cnt += dfs(jumps, visited, 2, i - 1) * 4; // 2, 4, 6, 8
        cnt += dfs(jumps, visited, 5, i - 1);     // 5
    }

    return cnt;
};

function dfs(jumps, visited, curr, remaining) {
    if (remaining < 0) return 0;
    if (remaining === 0) return 1;

    visited[curr] = true;
    let cnt = 0;
    for (let next = 1; next <= 9; ++next) {
        if (!visited[next] && (jumps[curr][next] === 0 || visited[jumps[curr][next]])) {
            cnt += dfs(jumps, visited, next, remaining - 1);
        }
    }
    visited[curr] = false;

    return cnt;
}
```
The algorithm starts with a depth-first search (DFS) approach to explore all the possible combinations of the unlock patterns. We create a `jumps` matrix to store the condition that if a line segment between any two points passes through another point, the number in the `jumps` matrix represents the middle point.

The DFS function starts at a certain point and recursively explores all the possible points that can be reached according to the rules. It keeps track of visited points using the `visited` array. The DFS function returns the count of valid patterns for the range of `m` to `n`.

For each iteration from `m` to `n`, we calculate the number of valid unlock patterns, and we multiply the results by 4 since the grid is symmetric (e.g., patterns starting with 1, 3, 7, 9 are equivalent, and patterns starting with 2, 4, 6, 8 are equivalent). We do this for each corner and side midpoints separately. Finally, we add the count for the center point (5), and return the total count.


# Data Stream as Disjoint Intervals

- slug: data-stream-as-disjoint-intervals
- difficulty: Hard

Given a data stream input of non-negative integers `a1, a2, ..., an`, summarize the numbers seen so far as a list of disjoint intervals.

Implement the `SummaryRanges` class:

*   `SummaryRanges()` Initializes the object with an empty stream.
*   `void addNum(int value)` Adds the integer `value` to the stream.
*   `int[][] getIntervals()` Returns a summary of the integers in the stream currently as a list of disjoint intervals `[starti, endi]`. The answer should be sorted by `starti`.

**Example 1:**

**Input**
\[ "SummaryRanges ",  "addNum ",  "getIntervals ",  "addNum ",  "getIntervals ",  "addNum ",  "getIntervals ",  "addNum ",  "getIntervals ",  "addNum ",  "getIntervals "\]
\[\[\], \[1\], \[\], \[3\], \[\], \[7\], \[\], \[2\], \[\], \[6\], \[\]\]
**Output**
\[null, null, \[\[1, 1\]\], null, \[\[1, 1\], \[3, 3\]\], null, \[\[1, 1\], \[3, 3\], \[7, 7\]\], null, \[\[1, 3\], \[7, 7\]\], null, \[\[1, 3\], \[6, 7\]\]\]

**Explanation**
SummaryRanges summaryRanges = new SummaryRanges();
summaryRanges.addNum(1);      // arr = \[1\]
summaryRanges.getIntervals(); // return \[\[1, 1\]\]
summaryRanges.addNum(3);      // arr = \[1, 3\]
summaryRanges.getIntervals(); // return \[\[1, 1\], \[3, 3\]\]
summaryRanges.addNum(7);      // arr = \[1, 3, 7\]
summaryRanges.getIntervals(); // return \[\[1, 1\], \[3, 3\], \[7, 7\]\]
summaryRanges.addNum(2);      // arr = \[1, 2, 3, 7\]
summaryRanges.getIntervals(); // return \[\[1, 3\], \[7, 7\]\]
summaryRanges.addNum(6);      // arr = \[1, 2, 3, 6, 7\]
summaryRanges.getIntervals(); // return \[\[1, 3\], \[6, 7\]\]

**Constraints:**

*   `0 <= value <= 104`
*   At most `3 * 104` calls will be made to `addNum` and `getIntervals`.
*   At most `102` calls will be made to `getIntervals`.

**Follow up:** What if there are lots of merges and the number of disjoint intervals is small compared to the size of the data stream?

## A solution in Java

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

public class SummaryRanges {

    private TreeMap<Integer, Integer> intervals = new TreeMap<>();

    public void addNum(int val) {
        if (intervals.isEmpty() || intervals.firstKey() > val + 1) {
            intervals.put(val, val);
            return;
        }
        Integer lower = intervals.lowerKey(val);
        Integer upper = intervals.higherKey(val);
        if (lower != null && intervals.get(lower) + 1 == val) {
            intervals.put(lower, intervals.get(lower) + 1);

            if (upper != null && val + 1 == upper) {
                intervals.put(lower, intervals.get(upper));
                intervals.remove(upper);
            }
        } else if (upper != null && val + 1 == upper) {
            intervals.put(val, intervals.get(upper));
            intervals.remove(upper);
        } else {
            intervals.put(val, val);
        }
    }

    public List<List<Integer>> getIntervals() {
        List<List<Integer>> result = new ArrayList<>();
        for (Integer key : intervals.keySet()) {
            List<Integer> range = new ArrayList<>();
            range.add(key);
            range.add(intervals.get(key));
            result.add(range);
        }
        return result;
    }
}
```
We will maintain a map (a TreeMap in Java, an OrderedDict in Python, and a Map in JavaScript) to store start and end points of disjoint intervals. The keys of the map represent the start of an interval, and their corresponding values are the end of the interval.

1. If the map is empty, or there is no previous interval that can be merged with the current number, we will create a new disjoint interval starting and ending at the current number and store it in the map.
2. Otherwise, we try to merge the number with existing intervals. We find the exact location where the number would fit in the map. If the number lies between any pre-existing interval, we ignore it. If the number is to the left of any existing interval and can be merged, we update the end value of the interval. If the number is to the right of any existing interval, we create a new entry in the map with start and end as the current number.

To output the intervals, we just convert the key-value pairs of the map to a list of lists representing the intervals.

## A solution in C++

```cpp
#include <map>

class SummaryRanges {
public:
    void addNum(int val) {
        if (intervals.empty() || intervals.begin()->first > val + 1) {
            intervals[val] = val;
        } else {
            auto it = intervals.lower_bound(val);
            auto left = prev(it), right = it;

            if (left != intervals.end() && left->second + 1 == val) {
                left->second++;
                if (right != intervals.end() && val + 1 == right->first) {
                    left->second = right->second;
                    intervals.erase(right);
                }
            } else if (right != intervals.end() && val + 1 == right->first) {
                intervals[val] = right->second;
                intervals.erase(right);
            } else {
                intervals[val] = val;
            }
        }
    }

    vector<vector<int>> getIntervals() {
        vector<vector<int>> result;
        for (const auto& interval : intervals) {
            result.push_back({interval.first, interval.second});
        }
        return result;
    }

private:
    map<int, int> intervals;
};
```
We will maintain a map (a TreeMap in Java, an OrderedDict in Python, and a Map in JavaScript) to store start and end points of disjoint intervals. The keys of the map represent the start of an interval, and their corresponding values are the end of the interval.

1. If the map is empty, or there is no previous interval that can be merged with the current number, we will create a new disjoint interval starting and ending at the current number and store it in the map.
2. Otherwise, we try to merge the number with existing intervals. We find the exact location where the number would fit in the map. If the number lies between any pre-existing interval, we ignore it. If the number is to the left of any existing interval and can be merged, we update the end value of the interval. If the number is to the right of any existing interval, we create a new entry in the map with start and end as the current number.

To output the intervals, we just convert the key-value pairs of the map to a list of lists representing the intervals.

## A solution in Python

```python
from collections import OrderedDict

class SummaryRanges:

    def __init__(self):
        self.intervals = OrderedDict()

    def addNum(self, val: int) -> None:
        if not self.intervals or next(iter(self.intervals)) > val + 1:
            self.intervals[val] = val
        else:
            keys = list(self.intervals.keys())
            idx = bisect_left(keys, val)
            if idx > 0 and keys[idx - 1] <= val <= self.intervals[keys[idx - 1]]:
                pass
            elif idx < len(keys) and val + 1 == keys[idx]:
                self.intervals[val] = self.intervals[keys[idx]]
                del self.intervals[keys[idx]]
            else:
                self.intervals[val] = val

    def getIntervals(self):
        return list(self.intervals.items())
```
We will maintain a map (a TreeMap in Java, an OrderedDict in Python, and a Map in JavaScript) to store start and end points of disjoint intervals. The keys of the map represent the start of an interval, and their corresponding values are the end of the interval.

1. If the map is empty, or there is no previous interval that can be merged with the current number, we will create a new disjoint interval starting and ending at the current number and store it in the map.
2. Otherwise, we try to merge the number with existing intervals. We find the exact location where the number would fit in the map. If the number lies between any pre-existing interval, we ignore it. If the number is to the left of any existing interval and can be merged, we update the end value of the interval. If the number is to the right of any existing interval, we create a new entry in the map with start and end as the current number.

To output the intervals, we just convert the key-value pairs of the map to a list of lists representing the intervals.

## A solution in Javascript

```javascript
class SummaryRanges {
    constructor() {
        this.intervals = new Map();
    }

    addNum(val) {
        if (!this.intervals.size || [...this.intervals.keys()][0] > val + 1) {
            this.intervals.set(val, val);
        } else {
            let keys = [...this.intervals.keys()];
            let index = keys.findIndex(key => key > val);

            if (index > 0 && keys[index - 1] <= val && val <= this.intervals.get(keys[index - 1])) {
                return;
            } else if (index !== -1 && val + 1 === keys[index]) {
                this.intervals.set(val, this.intervals.get(keys[index]));
                this.intervals.delete(keys[index]);
            } else {
                this.intervals.set(val, val);
            }
        }
    }

    getIntervals() {
        return [...this.intervals.entries()].map(([start, end]) => [start, end]);
    }
}
```
We will maintain a map (a TreeMap in Java, an OrderedDict in Python, and a Map in JavaScript) to store start and end points of disjoint intervals. The keys of the map represent the start of an interval, and their corresponding values are the end of the interval.

1. If the map is empty, or there is no previous interval that can be merged with the current number, we will create a new disjoint interval starting and ending at the current number and store it in the map.
2. Otherwise, we try to merge the number with existing intervals. We find the exact location where the number would fit in the map. If the number lies between any pre-existing interval, we ignore it. If the number is to the left of any existing interval and can be merged, we update the end value of the interval. If the number is to the right of any existing interval, we create a new entry in the map with start and end as the current number.

To output the intervals, we just convert the key-value pairs of the map to a list of lists representing the intervals.


# Design Snake Game

- slug: design-snake-game
- difficulty: Medium

Design a [Snake game](https://en.wikipedia.org/wiki/Snake_(video_game)) that is played on a device with screen size `height x width`. [Play the game online](http://patorjk.com/games/snake/) if you are not familiar with the game.

The snake is initially positioned at the top left corner `(0, 0)` with a length of `1` unit.

You are given an array `food` where `food[i] = (ri, ci)` is the row and column position of a piece of food that the snake can eat. When a snake eats a piece of food, its length and the game's score both increase by `1`.

Each piece of food appears one by one on the screen, meaning the second piece of food will not appear until the snake eats the first piece of food.

When a piece of food appears on the screen, it is **guaranteed** that it will not appear on a block occupied by the snake.

The game is over if the snake goes out of bounds (hits a wall) or if its head occupies a space that its body occupies **after** moving (i.e. a snake of length 4 cannot run into itself).

Implement the `SnakeGame` class:

*   `SnakeGame(int width, int height, int[][] food)` Initializes the object with a screen of size `height x width` and the positions of the `food`.
*   `int move(String direction)` Returns the score of the game after applying one `direction` move by the snake. If the game is over, return `-1`.

**Example 1:**

**Input**
\[ "SnakeGame ",  "move ",  "move ",  "move ",  "move ",  "move ",  "move "\]
\[\[3, 2, \[\[1, 2\], \[0, 1\]\]\], \[ "R "\], \[ "D "\], \[ "R "\], \[ "U "\], \[ "L "\], \[ "U "\]\]
**Output**
\[null, 0, 0, 1, 1, 2, -1\]

**Explanation**
SnakeGame snakeGame = new SnakeGame(3, 2, \[\[1, 2\], \[0, 1\]\]);
snakeGame.move( "R "); // return 0
snakeGame.move( "D "); // return 0
snakeGame.move( "R "); // return 1, snake eats the first piece of food. The second piece of food appears at (0, 1).
snakeGame.move( "U "); // return 1
snakeGame.move( "L "); // return 2, snake eats the second food. No more food appears.
snakeGame.move( "U "); // return -1, game over because snake collides with border

**Constraints:**

*   `1 <= width, height <= 104`
*   `1 <= food.length <= 50`
*   `food[i].length == 2`
*   `0 <= ri < height`
*   `0 <= ci < width`
*   `direction.length == 1`
*   `direction` is `'U'`, `'D'`, `'L'`, or `'R'`.
*   At most `104` calls will be made to `move`.

## A solution in Java

```java
import java.util.*;

class SnakeGame {
    private int width, height, pos, score;
    private int[][] food;
    private LinkedList<int[]> snake;
    private Set<String> occupied;

    public SnakeGame(int width, int height, int[][] food) {
        this.width = width;
        this.height = height;
        this.food = food;
        pos = 0;
        score = 0;
        snake = new LinkedList<>();
        occupied = new HashSet<>();
        snake.add(new int[]{0, 0});
        occupied.add("0_0");
    }

    public int move(String direction) {
        int newX = snake.peekLast()[0] + dx.get(direction);
        int newY = snake.peekLast()[1] + dy.get(direction);

        if (newX < 0 || newX >= height || newY < 0 || newY >= width) {
            return -1;
        }

        int[] newHead = new int[]{newX, newY};
        int[] tail = snake.poll();

        if (pos < food.length && food[pos][0] == newX && food[pos][1] == newY) {
            score++;
            pos++;
        } else {
            occupied.remove(tail[0] + "_" + tail[1]);
        }

        if (occupied.contains(newX + "_" + newY)) {
            return -1;
        }

        snake.add(newHead);
        occupied.add(newX + "_" + newY);
        return score;
    }

    private static final Map<String, Integer> dx = Map.of("U", -1, "D", 1, "L", 0, "R", 0);
    private static final Map<String, Integer> dy = Map.of("U", 0, "D", 0, "L", -1, "R", 1);
}
```
1. Initialize variables width, height, food, pos (food position), score, snake deque with initial position (0, 0), occupied set with initial position, dx and dy dictionary to update coordinate values based on given direction.
2. In the move method, calculate the next possible coordinates new_x and new_y using dx and dy dictionary.
3. Check if the new_x and new_y are out of the boundary, if yes then return -1 as it's a game over.
4. Check if the new position matches with food, if yes then update the score and increment the pos otherwise remove the tail block from the snake and occupied set.
5. If new_head is already in the occupied set, return -1, Because after moving the snake is colliding itself.
6. Otherwise, add the new_head in the snake deque and occupied set then return the current score.

## A solution in C++

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

class SnakeGame {
public:
    SnakeGame(int width, int height, std::vector<std::vector<int>>& food)
        : width(width), height(height), food(food), pos(0), score(0) {
        snake.push_back({0, 0});
        occupied.insert(0);
    }

    int move(std::string direction) {
        int new_x = snake.back().first + dx[direction];
        int new_y = snake.back().second + dy[direction];

        if (new_x < 0 || new_x >= height || new_y < 0 || new_y >= width) {
            return -1;
        }

        std::pair<int, int> new_head = std::make_pair(new_x, new_y);
        std::pair<int, int> tail = snake.front();

        if (pos < food.size() && food[pos][0] == new_x && food[pos][1] == new_y) {
            score++;
            pos++;
        } else {
            snake.pop_front();
            occupied.erase(tail.first * width + tail.second);
        }

        if (occupied.count(new_head.first * width + new_head.second)) {
            return -1;
        }

        snake.push_back(new_head);
        occupied.insert(new_head.first * width + new_head.second);
        return score;
    }

private:
    int width;
    int height;
    std::vector<std::vector<int>> food;
    int pos;
    int score;
    std::list<std::pair<int, int>> snake;
    std::unordered_set<int> occupied;
    std::unordered_map<std::string, int> dx = {{"U", -1}, {"D", 1}, {"L", 0}, {"R", 0}};
    std::unordered_map<std::string, int> dy = {{"U", 0}, {"D", 0}, {"L", -1}, {"R", 1}};
};
```
1. Initialize variables width, height, food, pos (food position), score, snake deque with initial position (0, 0), occupied set with initial position, dx and dy dictionary to update coordinate values based on given direction.
2. In the move method, calculate the next possible coordinates new_x and new_y using dx and dy dictionary.
3. Check if the new_x and new_y are out of the boundary, if yes then return -1 as it's a game over.
4. Check if the new position matches with food, if yes then update the score and increment the pos otherwise remove the tail block from the snake and occupied set.
5. If new_head is already in the occupied set, return -1, Because after moving the snake is colliding itself.
6. Otherwise, add the new_head in the snake deque and occupied set then return the current score.

## A solution in Python

```python
from collections import deque

class SnakeGame:
    def __init__(self, width: int, height: int, food: List[List[int]]):
        self.width = width
        self.height = height
        self.food = food
        self.pos = 0
        self.score = 0
        self.snake = deque([(0, 0)])
        self.occupied = {(0, 0)}
        self.dx = {'U': -1, 'D': 1, 'L': 0, 'R': 0}
        self.dy = {'U': 0, 'D': 0, 'L': -1, 'R': 1}

    def move(self, direction: str) -> int:
        new_x = self.snake[-1][0] + self.dx[direction]
        new_y = self.snake[-1][1] + self.dy[direction]

        if new_x < 0 or new_x >= self.height or new_y < 0 or new_y >= self.width:
            return -1

        new_head = (new_x, new_y)
        tail = self.snake.popleft()

        if self.pos < len(self.food) and self.food[self.pos] == list(new_head):
            self.score += 1
            self.pos += 1
        else:
            self.occupied.remove(tail)

        if new_head in self.occupied:
            return -1

        self.snake.append(new_head)
        self.occupied.add(new_head)
        return self.score
```
1. Initialize variables width, height, food, pos (food position), score, snake deque with initial position (0, 0), occupied set with initial position, dx and dy dictionary to update coordinate values based on given direction.
2. In the move method, calculate the next possible coordinates new_x and new_y using dx and dy dictionary.
3. Check if the new_x and new_y are out of the boundary, if yes then return -1 as it's a game over.
4. Check if the new position matches with food, if yes then update the score and increment the pos otherwise remove the tail block from the snake and occupied set.
5. If new_head is already in the occupied set, return -1, Because after moving the snake is colliding itself.
6. Otherwise, add the new_head in the snake deque and occupied set then return the current score.

## A solution in Javascript

```javascript
class SnakeGame {
    constructor(width, height, food) {
        this.width = width;
        this.height = height;
        this.food = food;
        this.pos = 0;
        this.score = 0;
        this.snake = [[0, 0]];
        this.occupied = new Set(['0_0']);
        this.dx = {'U': -1, 'D': 1, 'L': 0, 'R': 0};
        this.dy = {'U': 0, 'D': 0, 'L': -1, 'R': 1};
    }

    move(direction) {
        let newX = this.snake[this.snake.length - 1][0] + this.dx[direction];
        let newY = this.snake[this.snake.length - 1][1] + this.dy[direction];

        if (newX < 0 || newX >= this.height || newY < 0 || newY >= this.width) {
            return -1;
        }

        let newHead = [newX, newY];
        let tail = this.snake.shift();

        if (this.pos < this.food.length && this.food[this.pos][0] === newX && this.food[this.pos][1] === newY) {
            this.score++;
            this.pos++;
        } else {
            this.occupied.delete(tail[0] + '_' + tail[1]);
        }

        if (this.occupied.has(newX + '_' + newY)) {
            return -1;
        }

        this.snake.push(newHead);
        this.occupied.add(newX + '_' + newY);
        return this.score;
    }
}
```
1. Initialize variables width, height, food, pos (food position), score, snake deque with initial position (0, 0), occupied set with initial position, dx and dy dictionary to update coordinate values based on given direction.
2. In the move method, calculate the next possible coordinates new_x and new_y using dx and dy dictionary.
3. Check if the new_x and new_y are out of the boundary, if yes then return -1 as it's a game over.
4. Check if the new position matches with food, if yes then update the score and increment the pos otherwise remove the tail block from the snake and occupied set.
5. If new_head is already in the occupied set, return -1, Because after moving the snake is colliding itself.
6. Otherwise, add the new_head in the snake deque and occupied set then return the current score.


# Russian Doll Envelopes

- slug: russian-doll-envelopes
- difficulty: Hard

You are given a 2D array of integers `envelopes` where `envelopes[i] = [wi, hi]` represents the width and the height of an envelope.

One envelope can fit into another if and only if both the width and height of one envelope are greater than the other envelope's width and height.

Return _the maximum number of envelopes you can Russian doll (i.e., put one inside the other)_.

**Note:** You cannot rotate an envelope.

**Example 1:**

**Input:** envelopes = \[\[5,4\],\[6,4\],\[6,7\],\[2,3\]\]
**Output:** 3
**Explanation:** The maximum number of envelopes you can Russian doll is `3` (\[2,3\] => \[5,4\] => \[6,7\]).

**Example 2:**

**Input:** envelopes = \[\[1,1\],\[1,1\],\[1,1\]\]
**Output:** 1

**Constraints:**

*   `1 <= envelopes.length <= 105`
*   `envelopes[i].length == 2`
*   `1 <= wi, hi <= 105`

## A solution in Java

```java
import java.util.Arrays;
import java.util.Comparator;

public int maxEnvelopes(int[][] envelopes) {
    Arrays.sort(envelopes, new Comparator<int[]>() {
        public int compare(int[] a, int[] b) {
            return a[0] == b[0] ? b[1] - a[1] : a[0] - b[0];
        }
    });

    int[] dp = new int[envelopes.length];
    int len = 0;
    for (int[] envelope : envelopes) {
        int idx = Arrays.binarySearch(dp, 0, len, envelope[1]);
        if (idx < 0) {
            idx = -(idx + 1);
        }
        dp[idx] = envelope[1];
        if (idx == len) {
            len++;
        }
    }

    return len;
}
```
1. Sort the envelopes based on width and in ascending order. If the widths are equal, sort by height in descending order.
2. Create an empty list `dp` to maintain the increasing subsequence.
3. Iterate through the sorted envelopes and for each envelope, find the index of the height in `dp` with binary search. If the index is equal to the length of `dp`, append the height to `dp`. Otherwise, replace the element at the index in `dp` with the current height.
4. The length of `dp` will be the maximum number of envelopes that can be put one inside the other.

## A solution in C++

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

int maxEnvelopes(std::vector<std::vector<int>>& envelopes) {
    std::sort(envelopes.begin(), envelopes.end(), [](const std::vector<int>& a, const std::vector<int>& b) {
        return a[0] == b[0] ? a[1] > b[1] : a[0] < b[0];
    });

    std::vector<int> dp;
    for (const auto& envelope : envelopes) {
        auto it = std::lower_bound(dp.begin(), dp.end(), envelope[1]);
        if (it == dp.end()) {
            dp.push_back(envelope[1]);
        } else {
            *it = envelope[1];
        }
    }

    return dp.size();
}
```
1. Sort the envelopes based on width and in ascending order. If the widths are equal, sort by height in descending order.
2. Create an empty list `dp` to maintain the increasing subsequence.
3. Iterate through the sorted envelopes and for each envelope, find the index of the height in `dp` with binary search. If the index is equal to the length of `dp`, append the height to `dp`. Otherwise, replace the element at the index in `dp` with the current height.
4. The length of `dp` will be the maximum number of envelopes that can be put one inside the other.

## A solution in Python

```python
from bisect import bisect_left

def max_envelopes(envelopes):
    envelopes.sort(key=lambda x: (x[0], -x[1]))
    dp = []

    for _, h in envelopes:
        idx = bisect_left(dp, h)
        if idx == len(dp):
            dp.append(h)
        else:
            dp[idx] = h

    return len(dp)
```
1. Sort the envelopes based on width and in ascending order. If the widths are equal, sort by height in descending order.
2. Create an empty list `dp` to maintain the increasing subsequence.
3. Iterate through the sorted envelopes and for each envelope, find the index of the height in `dp` with binary search. If the index is equal to the length of `dp`, append the height to `dp`. Otherwise, replace the element at the index in `dp` with the current height.
4. The length of `dp` will be the maximum number of envelopes that can be put one inside the other.

## A solution in Javascript

```javascript
function maxEnvelopes(envelopes) {
    envelopes.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]);
    const dp = [];

    for (const envelope of envelopes) {
        const idx = lowerBound(dp, envelope[1]);
        if (idx === dp.length) {
            dp.push(envelope[1]);
        } else {
            dp[idx] = envelope[1];
        }
    }

    return dp.length;

    function lowerBound(arr, target) {
        let low = 0, high = arr.length;
        while (low < high) {
            const mid = Math.floor((low + high) / 2);
            if (arr[mid] < target) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }
}
```
1. Sort the envelopes based on width and in ascending order. If the widths are equal, sort by height in descending order.
2. Create an empty list `dp` to maintain the increasing subsequence.
3. Iterate through the sorted envelopes and for each envelope, find the index of the height in `dp` with binary search. If the index is equal to the length of `dp`, append the height to `dp`. Otherwise, replace the element at the index in `dp` with the current height.
4. The length of `dp` will be the maximum number of envelopes that can be put one inside the other.


# Design Twitter

- slug: design-twitter
- difficulty: Medium

Design a simplified version of Twitter where users can post tweets, follow/unfollow another user, and is able to see the `10` most recent tweets in the user's news feed.

Implement the `Twitter` class:

*   `Twitter()` Initializes your twitter object.
*   `void postTweet(int userId, int tweetId)` Composes a new tweet with ID `tweetId` by the user `userId`. Each call to this function will be made with a unique `tweetId`.
*   `List getNewsFeed(int userId)` Retrieves the `10` most recent tweet IDs in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user themself. Tweets must be **ordered from most recent to least recent**.
*   `void follow(int followerId, int followeeId)` The user with ID `followerId` started following the user with ID `followeeId`.
*   `void unfollow(int followerId, int followeeId)` The user with ID `followerId` started unfollowing the user with ID `followeeId`.

**Example 1:**

**Input**
\[ "Twitter ",  "postTweet ",  "getNewsFeed ",  "follow ",  "postTweet ",  "getNewsFeed ",  "unfollow ",  "getNewsFeed "\]
\[\[\], \[1, 5\], \[1\], \[1, 2\], \[2, 6\], \[1\], \[1, 2\], \[1\]\]
**Output**
\[null, null, \[5\], null, null, \[6, 5\], null, \[5\]\]

**Explanation**
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // User 1 posts a new tweet (id = 5).
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 1 tweet id -> \[5\]. return \[5\]
twitter.follow(1, 2);    // User 1 follows user 2.
twitter.postTweet(2, 6); // User 2 posts a new tweet (id = 6).
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 2 tweet ids -> \[6, 5\]. Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.
twitter.unfollow(1, 2);  // User 1 unfollows user 2.
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 1 tweet id -> \[5\], since user 1 is no longer following user 2.

**Constraints:**

*   `1 <= userId, followerId, followeeId <= 500`
*   `0 <= tweetId <= 104`
*   All the tweets have **unique** IDs.
*   At most `3 * 104` calls will be made to `postTweet`, `getNewsFeed`, `follow`, and `unfollow`.

## A solution in Java

```java
import java.util.*;

class Twitter {
    class Tweet {
        int time;
        int tweetId;

        Tweet(int t, int id) {
            time = t;
            tweetId = id;
        }
    }

    private Map<Integer, List<Tweet>> tweets;
    private Map<Integer, Set<Integer>> following;
    private int timeStamp;

    public Twitter() {
        tweets = new HashMap<>();
        following = new HashMap<>();
        timeStamp = 0;
    }

    public void postTweet(int userId, int tweetId) {
        tweets.putIfAbsent(userId, new ArrayList<>());
        tweets.get(userId).add(new Tweet(timeStamp++, tweetId));
    }

    public List<Integer> getNewsFeed(int userId) {
        List<Tweet> feed = new ArrayList<>();
        if (tweets.containsKey(userId)) {
            feed.addAll(tweets.get(userId));
        }
        if (following.containsKey(userId)) {
            for (int user : following.get(userId)) {
                if (tweets.containsKey(user)) {
                    feed.addAll(tweets.get(user));
                }
            }
        }

        feed.sort((a, b) -> b.time - a.time);

        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < feed.size() && i < 10; ++i) {
            result.add(feed.get(i).tweetId);
        }
        return result;
    }

    public void follow(int followerId, int followeeId) {
        if (followerId != followeeId) {
            following.putIfAbsent(followerId, new HashSet<>());
            following.get(followerId).add(followeeId);
        }
    }

    public void unfollow(int followerId, int followeeId) {
        if (following.containsKey(followerId)) {
            following.get(followerId).remove(followeeId);
        }
    }
}
```
The `Twitter` class has three main data structures: `tweets`, `following`, and a `timeStamp` counter.

- `tweets`: A data structure to store tweet objects for each user.
- `following`: A data structure to store the list of users that the current user follows.
- `timeStamp`: A counter to provide a unique and increasing timestamp for each new tweet.

The main methods are:

1. `postTweet`: This method appends a new tweet with the provided tweetId and a timestamp to the user's tweet list.

2. `getNewsFeed`: This method collects the 10 most recent tweets from the user's own tweets and the tweets of users they follow, sorted by timestamp in decreasing order.

3. `follow`: This method ensures the follower is not following themselves, then adds the followee to the follower's following list.

4. `unfollow`: This method removes the followee from the follower's following list if he/she is present in it.

In each language, the implementation is similar. Data structures and methods are used according to the specific language and built-in capabilities.

## A solution in C++

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

class Twitter {
public:
    class Tweet {
    public:
        int time;
        int tweetId;
        Tweet(int t, int id) : time(t), tweetId(id) {}
    };

    unordered_map<int, vector<Tweet>> tweets;
    unordered_map<int, unordered_set<int>> following;
    int timeStamp;

    Twitter() {
        timeStamp = 0;
    }

    void postTweet(int userId, int tweetId) {
        tweets[userId].emplace_back(timeStamp++, tweetId);
    }

    vector<int> getNewsFeed(int userId) {
        vector<Tweet*> feed;
        for (Tweet& t : tweets[userId]) {
            feed.push_back(&t);
        }
        for (int user : following[userId]) {
            for (Tweet& t : tweets[user]) {
                feed.push_back(&t);
            }
        }

        sort(feed.begin(), feed.end(), [](Tweet* a, Tweet* b) {
            return a->time > b->time;
        });

        vector<int> result;
        for (int i = 0; i < feed.size() && i < 10; ++i) {
            result.push_back(feed[i]->tweetId);
        }
        return result;
    }

    void follow(int followerId, int followeeId) {
        if (followerId != followeeId) {
            following[followerId].insert(followeeId);
        }
    }

    void unfollow(int followerId, int followeeId) {
        following[followerId].erase(followeeId);
    }
};
```
The `Twitter` class has three main data structures: `tweets`, `following`, and a `timeStamp` counter.

- `tweets`: A data structure to store tweet objects for each user.
- `following`: A data structure to store the list of users that the current user follows.
- `timeStamp`: A counter to provide a unique and increasing timestamp for each new tweet.

The main methods are:

1. `postTweet`: This method appends a new tweet with the provided tweetId and a timestamp to the user's tweet list.

2. `getNewsFeed`: This method collects the 10 most recent tweets from the user's own tweets and the tweets of users they follow, sorted by timestamp in decreasing order.

3. `follow`: This method ensures the follower is not following themselves, then adds the followee to the follower's following list.

4. `unfollow`: This method removes the followee from the follower's following list if he/she is present in it.

In each language, the implementation is similar. Data structures and methods are used according to the specific language and built-in capabilities.

## A solution in Python

```python
from collections import defaultdict
from typing import List

class Twitter:

    class Tweet:
        def __init__(self, time, tweetId):
            self.time = time
            self.tweetId = tweetId

    def __init__(self):
        self.tweets = defaultdict(list)
        self.following = defaultdict(set)
        self.timeStamp = 0

    def postTweet(self, userId: int, tweetId: int) -> None:
        self.tweets[userId].append(self.Tweet(self.timeStamp, tweetId))
        self.timeStamp += 1

    def getNewsFeed(self, userId: int) -> List[int]:
        feed = self.tweets[userId][:]
        for user in self.following[userId]:
            feed.extend(self.tweets[user])

        feed.sort(key=lambda x: x.time, reverse=True)
        return [t.tweetId for t in feed[:10]]

    def follow(self, followerId: int, followeeId: int) -> None:
        if followerId != followeeId:
            self.following[followerId].add(followeeId)

    def unfollow(self, followerId: int, followeeId: int) -> None:
        self.following[followerId].discard(followeeId)
```
The `Twitter` class has three main data structures: `tweets`, `following`, and a `timeStamp` counter.

- `tweets`: A data structure to store tweet objects for each user.
- `following`: A data structure to store the list of users that the current user follows.
- `timeStamp`: A counter to provide a unique and increasing timestamp for each new tweet.

The main methods are:

1. `postTweet`: This method appends a new tweet with the provided tweetId and a timestamp to the user's tweet list.

2. `getNewsFeed`: This method collects the 10 most recent tweets from the user's own tweets and the tweets of users they follow, sorted by timestamp in decreasing order.

3. `follow`: This method ensures the follower is not following themselves, then adds the followee to the follower's following list.

4. `unfollow`: This method removes the followee from the follower's following list if he/she is present in it.

In each language, the implementation is similar. Data structures and methods are used according to the specific language and built-in capabilities.

## A solution in Javascript

```javascript
class Twitter {
    constructor() {
        this.tweets = {};
        this.following = {};
        this.timeStamp = 0;
    }

    postTweet(userId, tweetId) {
        if (!this.tweets[userId]) {
            this.tweets[userId] = [];
        }
        this.tweets[userId].push({ time: this.timeStamp++, tweetId });
    }

    getNewsFeed(userId) {
        let feed = this.tweets[userId] ? [...this.tweets[userId]] : [];
        if (this.following[userId]) {
            for (const user of this.following[userId]) {
                if (this.tweets[user]) {
                    feed.push(...this.tweets[user]);
                }
            }
        }

        feed.sort((a, b) => b.time - a.time);

        return feed.slice(0, 10).map(tweet => tweet.tweetId);
    }

    follow(followerId, followeeId) {
        if (followerId !== followeeId) {
            if (!this.following[followerId]) {
                this.following[followerId] = new Set();
            }
            this.following[followerId].add(followeeId);
        }
    }

    unfollow(followerId, followeeId) {
        if (this.following[followerId]) {
            this.following[followerId].delete(followeeId);
        }
    }
}
```
The `Twitter` class has three main data structures: `tweets`, `following`, and a `timeStamp` counter.

- `tweets`: A data structure to store tweet objects for each user.
- `following`: A data structure to store the list of users that the current user follows.
- `timeStamp`: A counter to provide a unique and increasing timestamp for each new tweet.

The main methods are:

1. `postTweet`: This method appends a new tweet with the provided tweetId and a timestamp to the user's tweet list.

2. `getNewsFeed`: This method collects the 10 most recent tweets from the user's own tweets and the tweets of users they follow, sorted by timestamp in decreasing order.

3. `follow`: This method ensures the follower is not following themselves, then adds the followee to the follower's following list.

4. `unfollow`: This method removes the followee from the follower's following list if he/she is present in it.

In each language, the implementation is similar. Data structures and methods are used according to the specific language and built-in capabilities.


# Line Reflection

- slug: line-reflection
- difficulty: Medium

Given `n` points on a 2D plane, find if there is such a line parallel to the y-axis that reflects the given points symmetrically.

In other words, answer whether or not if there exists a line that after reflecting all points over the given line, the original points' set is the same as the reflected ones.

**Note** that there can be repeated points.

**Example 1:**

**Input:** points = \[\[1,1\],\[-1,1\]\]
**Output:** true
**Explanation:** We can choose the line x = 0.

**Example 2:**

**Input:** points = \[\[1,1\],\[-1,-1\]\]
**Output:** false
**Explanation:** We can't choose a line.

**Constraints:**

*   `n == points.length`
*   `1 <= n <= 104`
*   `-108 <= points[i][j] <= 108`

**Follow up:** Could you do better than `O(n2)`?

## A solution in Java

```java
public boolean isReflected(int[][] points) {
    int minX = Integer.MAX_VALUE;
    int maxX = Integer.MIN_VALUE;
    Set<String> pointSet = new HashSet<>();

    for (int[] point : points) {
        minX = Math.min(minX, point[0]);
        maxX = Math.max(maxX, point[0]);
        pointSet.add(point[0] + "," + point[1]);
    }

    int sum = minX + maxX;
    for (int[] point : points) {
        if (!pointSet.contains((sum - point[0]) + "," + point[1])) {
            return false;
        }
    }

    return true;
}
```
1. Iterate through the points and find the minimum and maximum x coordinates. Also, save all points as string (x,y) in a set.
2. Calculate the sum of min_x and max_x (this will give the x-coordinate of the line of reflection).
3. Iterate through the points again and check if the reflection point is in the set of points (using the calculated sum from step 2).
4. If all reflection points exist in the set, return true. Otherwise, return false.

## A solution in C++

```cpp
bool isReflected(vector<vector<int>>& points) {
    int minX = INT_MAX;
    int maxX = INT_MIN;

    unordered_set<string> pointSet;
    for(const auto& point : points) {
        minX = min(minX, point[0]);
        maxX = max(maxX, point[0]);
        pointSet.insert(to_string(point[0]) + "," + to_string(point[1]));
    }

    int sum = minX + maxX;
    for(const auto& point : points) {
        if(!pointSet.count(to_string(sum - point[0]) + "," + to_string(point[1]))) {
            return false;
        }
    }

    return true;
}
```
1. Iterate through the points and find the minimum and maximum x coordinates. Also, save all points as string (x,y) in a set.
2. Calculate the sum of min_x and max_x (this will give the x-coordinate of the line of reflection).
3. Iterate through the points again and check if the reflection point is in the set of points (using the calculated sum from step 2).
4. If all reflection points exist in the set, return true. Otherwise, return false.

## A solution in Python

```python
def isReflected(points):
    min_x = min(point[0] for point in points)
    max_x = max(point[0] for point in points)
    point_set = {(point[0], point[1]) for point in points}

    sum_x = min_x + max_x
    for point in points:
        if (sum_x - point[0], point[1]) not in point_set:
            return False

    return True
```
1. Iterate through the points and find the minimum and maximum x coordinates. Also, save all points as string (x,y) in a set.
2. Calculate the sum of min_x and max_x (this will give the x-coordinate of the line of reflection).
3. Iterate through the points again and check if the reflection point is in the set of points (using the calculated sum from step 2).
4. If all reflection points exist in the set, return true. Otherwise, return false.

## A solution in Javascript

```javascript
function isReflected(points) {
    let minX = Infinity;
    let maxX = -Infinity;
    const pointSet = new Set();

    for (const point of points) {
        minX = Math.min(minX, point[0]);
        maxX = Math.max(maxX, point[0]);
        pointSet.add(point[0] + "," + point[1]);
    }

    const sum = minX + maxX;
    for (const point of points) {
        if (!pointSet.has((sum - point[0]) + "," + point[1])) {
            return false;
        }
    }

    return true;
}
```
1. Iterate through the points and find the minimum and maximum x coordinates. Also, save all points as string (x,y) in a set.
2. Calculate the sum of min_x and max_x (this will give the x-coordinate of the line of reflection).
3. Iterate through the points again and check if the reflection point is in the set of points (using the calculated sum from step 2).
4. If all reflection points exist in the set, return true. Otherwise, return false.


# Count Numbers with Unique Digits

- slug: count-numbers-with-unique-digits
- difficulty: Medium

Given an integer `n`, return the count of all numbers with unique digits, `x`, where `0 <= x < 10n`.

**Example 1:**

**Input:** n = 2
**Output:** 91
**Explanation:** The answer should be the total numbers in the range of 0 <= x < 100, excluding 11,22,33,44,55,66,77,88,99

**Example 2:**

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

**Constraints:**

*   `0 <= n <= 8`

## A solution in Java

```java
public int countNumbersWithUniqueDigits(int n) {
    if (n == 0) return 1;

    int total = 10;
    int uniqueDigits = 9;
    int currentAvailableDigits = 9;

    while (n-- > 1 && currentAvailableDigits > 0) {
        uniqueDigits *= currentAvailableDigits;
        total += uniqueDigits;
        currentAvailableDigits--;
    }

    return total;
}
```
The algorithm starts with a base case when n=0, the result is 1, as there's only one number, 0, that has unique digits.

For other cases, it initializes total count to 10 (0 to 9), the unique digit count to 9, and the available digits count to 9. Then, it iterates until n becomes 1 or the available digits count becomes 0. In each iteration, the unique digit count is multiplied by the available digit count, which is then added to the total count. The available digit count is decremented in each iteration, as there will be one less digit to choose from to keep the numbers unique.

At the end, the total count is returned.

## A solution in C++

```cpp
int countNumbersWithUniqueDigits(int n) {
    if (n == 0) return 1;

    int total = 10;
    int uniqueDigits = 9;
    int currentAvailableDigits = 9;

    while(n-- > 1 && currentAvailableDigits > 0) {
        uniqueDigits *= currentAvailableDigits;
        total += uniqueDigits;
        currentAvailableDigits--;
    }

    return total;
}
```
The algorithm starts with a base case when n=0, the result is 1, as there's only one number, 0, that has unique digits.

For other cases, it initializes total count to 10 (0 to 9), the unique digit count to 9, and the available digits count to 9. Then, it iterates until n becomes 1 or the available digits count becomes 0. In each iteration, the unique digit count is multiplied by the available digit count, which is then added to the total count. The available digit count is decremented in each iteration, as there will be one less digit to choose from to keep the numbers unique.

At the end, the total count is returned.

## A solution in Python

```python
def countNumbersWithUniqueDigits(n):
    if n == 0:
        return 1

    total = 10
    unique_digits = 9
    current_available_digits = 9

    while n > 1 and current_available_digits > 0:
        unique_digits *= current_available_digits
        total += unique_digits
        current_available_digits -= 1
        n -= 1

    return total
```
The algorithm starts with a base case when n=0, the result is 1, as there's only one number, 0, that has unique digits.

For other cases, it initializes total count to 10 (0 to 9), the unique digit count to 9, and the available digits count to 9. Then, it iterates until n becomes 1 or the available digits count becomes 0. In each iteration, the unique digit count is multiplied by the available digit count, which is then added to the total count. The available digit count is decremented in each iteration, as there will be one less digit to choose from to keep the numbers unique.

At the end, the total count is returned.

## A solution in Javascript

```javascript
function countNumbersWithUniqueDigits(n) {
    if (n === 0) return 1;

    let total = 10;
    let uniqueDigits = 9;
    let currentAvailableDigits = 9;

    while (n-- > 1 && currentAvailableDigits > 0) {
        uniqueDigits *= currentAvailableDigits;
        total += uniqueDigits;
        currentAvailableDigits--;
    }

    return total;
}
```
The algorithm starts with a base case when n=0, the result is 1, as there's only one number, 0, that has unique digits.

For other cases, it initializes total count to 10 (0 to 9), the unique digit count to 9, and the available digits count to 9. Then, it iterates until n becomes 1 or the available digits count becomes 0. In each iteration, the unique digit count is multiplied by the available digit count, which is then added to the total count. The available digit count is decremented in each iteration, as there will be one less digit to choose from to keep the numbers unique.

At the end, the total count is returned.


# Rearrange String k Distance Apart

- slug: rearrange-string-k-distance-apart
- difficulty: Hard

Given a string `s` and an integer `k`, rearrange `s` such that the same characters are **at least** distance `k` from each other. If it is not possible to rearrange the string, return an empty string `" "`.

**Example 1:**

**Input:** s =  "aabbcc ", k = 3
**Output:**  "abcabc "
**Explanation:** The same letters are at least a distance of 3 from each other.

**Example 2:**

**Input:** s =  "aaabc ", k = 3
**Output:**  " "
**Explanation:** It is not possible to rearrange the string.

**Example 3:**

**Input:** s =  "aaadbbcc ", k = 2
**Output:**  "abacabcd "
**Explanation:** The same letters are at least a distance of 2 from each other.

**Constraints:**

*   `1 <= s.length <= 3 * 105`
*   `s` consists of only lowercase English letters.
*   `0 <= k <= s.length`

## A solution in Java

```java
import java.util.*;

public class Solution {
    public String rearrangeString(String s, int k) {
        if (k == 0) return s;

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

        PriorityQueue<Map.Entry<Character, Integer>> maxHeap =
                new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
        maxHeap.addAll(freqMap.entrySet());

        StringBuilder result = new StringBuilder();
        while (!maxHeap.isEmpty()) {
            List<Map.Entry<Character, Integer>> temp = new ArrayList<>();

            for (int i = 0; i < k && !maxHeap.isEmpty(); i++) {
                Map.Entry<Character, Integer> curr = maxHeap.poll();

                result.append(curr.getKey());
                if (curr.getValue() - 1 > 0) {
                    curr.setValue(curr.getValue() - 1);
                    temp.add(curr);
                }
            }

            maxHeap.addAll(temp);

            if (maxHeap.isEmpty()) break;
            if (result.length() < s.length()) {
                int spaces = k - temp.size();
                while (spaces-- > 0) result.append(" ");
            }
        }

        if (result.length() < s.length()) return "";
        return result.toString();
    }
}
```
The algorithm involves the following steps:
1. Calculate the frequency of each character in the input string `s`. Store it in a hash table (dictionary/map) `freq`.
2. Build a max heap (priority queue) from the frequency table. The heap will be sorted based on the frequency values.
3. While the max heap is not empty, pop the first `k` elements from the heap, where `k` is the minimum distance required between the same characters, and append the characters to the result string.
4. If the frequency of the popped elements is greater than one, decrement their frequency and store them in a temporary list `temp`.
5. After popping `k` elements, add them back to the max heap.
6. If the max heap is empty, break the loop.
7. If the length of the result string is less than the input string, append `k - temp.length` spaces.
8. If the final result string length is less than the input string, return an empty string. Otherwise, return the result string.

This algorithm ensures that characters with the highest frequency are placed first in the result string followed by other characters, maintaining a distance of at least `k` between the same characters. If it's not possible to place characters at that distance, an empty string will be returned.

## A solution in C++

```cpp
#include <queue>
#include <unordered_map>
#include <string>
using namespace std;

string rearrangeString(string s, int k) {
    if (k == 0) return s;

    unordered_map<char, int> freq;
    for (char c : s) {
        freq[c]++;
    }

    priority_queue<pair<int, char>> max_heap;
    for (const auto& kv : freq) {
        max_heap.emplace(kv.second, kv.first);
    }

    string result;
    while (!max_heap.empty()) {
        vector<pair<int, char>> temp;

        for (int i = 0; i < k && !max_heap.empty(); ++i) {
            auto curr = max_heap.top();
            max_heap.pop();

            result += curr.second;
            if (--curr.first > 0) {
                temp.push_back(curr);
            }
        }

        for (const auto& entry : temp) {
            max_heap.push(entry);
        }

        if (max_heap.empty()) break;
        if (result.length() < s.length()) result.append(k - temp.size(), ' ');
    }

    if (result.length() < s.length()) return "";
    return result;
}
```
The algorithm involves the following steps:
1. Calculate the frequency of each character in the input string `s`. Store it in a hash table (dictionary/map) `freq`.
2. Build a max heap (priority queue) from the frequency table. The heap will be sorted based on the frequency values.
3. While the max heap is not empty, pop the first `k` elements from the heap, where `k` is the minimum distance required between the same characters, and append the characters to the result string.
4. If the frequency of the popped elements is greater than one, decrement their frequency and store them in a temporary list `temp`.
5. After popping `k` elements, add them back to the max heap.
6. If the max heap is empty, break the loop.
7. If the length of the result string is less than the input string, append `k - temp.length` spaces.
8. If the final result string length is less than the input string, return an empty string. Otherwise, return the result string.

This algorithm ensures that characters with the highest frequency are placed first in the result string followed by other characters, maintaining a distance of at least `k` between the same characters. If it's not possible to place characters at that distance, an empty string will be returned.

## A solution in Python

```python
import heapq
from collections import Counter

def rearrange_string(s, k):
    if k == 0:
        return s

    counter = Counter(s)
    max_heap = [(-count, char) for char, count in counter.items()]
    heapq.heapify(max_heap)

    result = []
    while max_heap:
        temp = []

        for _ in range(k):
            if not max_heap:
                break

            count, char = heapq.heappop(max_heap)
            result.append(char)

            if count + 1 < 0:
                temp.append((count + 1, char))

        for item in temp:
            heapq.heappush(max_heap, item)

        if not max_heap:
            break

        if len(result) < len(s):
            result.extend([' '] * (k - len(temp)))

    if len(result) < len(s):
        return ""
    return "".join(result)
```
The algorithm involves the following steps:
1. Calculate the frequency of each character in the input string `s`. Store it in a hash table (dictionary/map) `freq`.
2. Build a max heap (priority queue) from the frequency table. The heap will be sorted based on the frequency values.
3. While the max heap is not empty, pop the first `k` elements from the heap, where `k` is the minimum distance required between the same characters, and append the characters to the result string.
4. If the frequency of the popped elements is greater than one, decrement their frequency and store them in a temporary list `temp`.
5. After popping `k` elements, add them back to the max heap.
6. If the max heap is empty, break the loop.
7. If the length of the result string is less than the input string, append `k - temp.length` spaces.
8. If the final result string length is less than the input string, return an empty string. Otherwise, return the result string.

This algorithm ensures that characters with the highest frequency are placed first in the result string followed by other characters, maintaining a distance of at least `k` between the same characters. If it's not possible to place characters at that distance, an empty string will be returned.

## A solution in Javascript

```javascript
function rearrangeString(s, k) {
  if (k === 0) return s;

  const freqMap = new Map();
  for (const c of s) {
    freqMap.set(c, (freqMap.get(c) || 0) + 1);
  }

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

  let result = '';
  while (maxHeap.length) {
    const temp = [];

    for (let i = 0; i < k && maxHeap.length > 0; i++) {
      const curr = maxHeap.shift();

      result += curr[0];
      if (curr[1] - 1 > 0) {
        temp.push([curr[0], curr[1] - 1]);
      }
    }

    maxHeap.unshift(...temp.sort((a, b) => b[1] - a[1]));

    if (!maxHeap.length) break;
    if (result.length < s.length) {
      result += " ".repeat(k - temp.length);
    }
  }

  if (result.length < s.length) return "";
  return result;
}
```
The algorithm involves the following steps:
1. Calculate the frequency of each character in the input string `s`. Store it in a hash table (dictionary/map) `freq`.
2. Build a max heap (priority queue) from the frequency table. The heap will be sorted based on the frequency values.
3. While the max heap is not empty, pop the first `k` elements from the heap, where `k` is the minimum distance required between the same characters, and append the characters to the result string.
4. If the frequency of the popped elements is greater than one, decrement their frequency and store them in a temporary list `temp`.
5. After popping `k` elements, add them back to the max heap.
6. If the max heap is empty, break the loop.
7. If the length of the result string is less than the input string, append `k - temp.length` spaces.
8. If the final result string length is less than the input string, return an empty string. Otherwise, return the result string.

This algorithm ensures that characters with the highest frequency are placed first in the result string followed by other characters, maintaining a distance of at least `k` between the same characters. If it's not possible to place characters at that distance, an empty string will be returned.