# Implement Trie (Prefix Tree)

- slug: implement-trie-prefix-tree
- difficulty: Medium

A [**trie**](https://en.wikipedia.org/wiki/Trie) (pronounced as "try ") or **prefix tree** is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.

Implement the Trie class:

*   `Trie()` Initializes the trie object.
*   `void insert(String word)` Inserts the string `word` into the trie.
*   `boolean search(String word)` Returns `true` if the string `word` is in the trie (i.e., was inserted before), and `false` otherwise.
*   `boolean startsWith(String prefix)` Returns `true` if there is a previously inserted string `word` that has the prefix `prefix`, and `false` otherwise.

**Example 1:**

**Input**
\[ "Trie ",  "insert ",  "search ",  "search ",  "startsWith ",  "insert ",  "search "\]
\[\[\], \[ "apple "\], \[ "apple "\], \[ "app "\], \[ "app "\], \[ "app "\], \[ "app "\]\]
**Output**
\[null, null, true, false, true, null, true\]

**Explanation**
Trie trie = new Trie();
trie.insert( "apple ");
trie.search( "apple ");   // return True
trie.search( "app ");     // return False
trie.startsWith( "app "); // return True
trie.insert( "app ");
trie.search( "app ");     // return True

**Constraints:**

*   `1 <= word.length, prefix.length <= 2000`
*   `word` and `prefix` consist only of lowercase English letters.
*   At most `3 * 104` calls **in total** will be made to `insert`, `search`, and `startsWith`.

## A solution in Java

```java
class Trie {
    private class TrieNode {
        Map<Character, TrieNode> children;
        boolean isEndOfWord;

        public TrieNode() {
            children = new HashMap<>();
            isEndOfWord = false;
        }
    }

    private final TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    public void insert(String word) {
        TrieNode current = root;
        for (char c : word.toCharArray()) {
            current.children.putIfAbsent(c, new TrieNode());
            current = current.children.get(c);
        }
        current.isEndOfWord = true;
    }

    public boolean search(String word) {
        TrieNode current = root;
        for (char c : word.toCharArray()) {
            TrieNode node = current.children.get(c);
            if (node == null) {
                return false;
            }
            current = node;
        }
        return current.isEndOfWord;
    }

    public boolean startsWith(String prefix) {
        TrieNode current = root;
        for (char c : prefix.toCharArray()) {
            TrieNode node = current.children.get(c);
            if (node == null) {
                return false;
            }
            current = node;
        }
        return true;
    }
}
```
The Trie data structure is implemented as a tree, where each node has a mapping of characters to their corresponding child nodes. Every node also has an `isEndOfWord` flag to indicate if any word ends at this node.

The `insert` function iterates through each character in a given word, adding new nodes to the tree if they don't already exist, and finally setting the `isEndOfWord` flag to true at the final node.

The `search` function follows the characters from the root of the Trie to the final node, returning false if any character does not map to a child node, otherwise returning the value of the `isEndOfWord` flag at the final node.

The `startsWith` function is similar to `search`, but returns true if a sequence of characters exists in the Trie, regardless of whether a word terminates at the final node.

## A solution in C++

```cpp
class Trie {
    struct TrieNode {
        unordered_map<char, TrieNode*> children;
        bool isEndOfWord;
    };

    TrieNode *root;

public:
    Trie() {
        root = new TrieNode();
        root->isEndOfWord = false;
    }

    void insert(string word) {
        TrieNode *curr = root;
        for (char c : word) {
            if (curr->children.find(c) == curr->children.end()) {
                curr->children[c] = new TrieNode();
            }
            curr = curr->children[c];
        }
        curr->isEndOfWord = true;
    }

    bool search(string word) {
        TrieNode *curr = root;
        for (char c : word) {
            if (curr->children.find(c) == curr->children.end()) {
                return false;
            }
            curr = curr->children[c];
        }
        return curr->isEndOfWord;
    }

    bool startsWith(string prefix) {
        TrieNode *curr = root;
        for (char c : prefix) {
            if (curr->children.find(c) == curr->children.end()) {
                return false;
            }
            curr = curr->children[c];
        }
        return true;
    }
};
```
The Trie data structure is implemented as a tree, where each node has a mapping of characters to their corresponding child nodes. Every node also has an `isEndOfWord` flag to indicate if any word ends at this node.

The `insert` function iterates through each character in a given word, adding new nodes to the tree if they don't already exist, and finally setting the `isEndOfWord` flag to true at the final node.

The `search` function follows the characters from the root of the Trie to the final node, returning false if any character does not map to a child node, otherwise returning the value of the `isEndOfWord` flag at the final node.

The `startsWith` function is similar to `search`, but returns true if a sequence of characters exists in the Trie, regardless of whether a word terminates at the final node.

## A solution in Python

```python
class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end_of_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word: str) -> None:
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_end_of_word = True

    def search(self, word: str) -> bool:
        node = self.root
        for c in word:
            if c not in node.children:
                return False
            node = node.children[c]
        return node.is_end_of_word

    def startsWith(self, prefix: str) -> bool:
        node = self.root
        for c in prefix:
            if c not in node.children:
                return False
            node = node.children[c]
        return True
```
The Trie data structure is implemented as a tree, where each node has a mapping of characters to their corresponding child nodes. Every node also has an `isEndOfWord` flag to indicate if any word ends at this node.

The `insert` function iterates through each character in a given word, adding new nodes to the tree if they don't already exist, and finally setting the `isEndOfWord` flag to true at the final node.

The `search` function follows the characters from the root of the Trie to the final node, returning false if any character does not map to a child node, otherwise returning the value of the `isEndOfWord` flag at the final node.

The `startsWith` function is similar to `search`, but returns true if a sequence of characters exists in the Trie, regardless of whether a word terminates at the final node.

## A solution in Javascript

```javascript
class TrieNode {
    constructor() {
        this.children = {};
        this.isEndOfWord = false;
    }
}

class Trie {
    constructor() {
        this.root = new TrieNode();
    }

    insert(word) {
        let node = this.root;
        for (let char of word) {
            if (!node.children[char]) {
                node.children[char] = new TrieNode();
            }
            node = node.children[char];
        }
        node.isEndOfWord = true;
    }

    search(word) {
        let node = this.root;
        for (let char of word) {
            node = node.children[char];
            if (!node) {
                return false;
            }
        }
        return node.isEndOfWord;
    }

    startsWith(prefix) {
        let node = this.root;
        for (let char of prefix) {
            node = node.children[char];
            if (!node) {
                return false;
            }
        }
        return true;
    }
}
```
The Trie data structure is implemented as a tree, where each node has a mapping of characters to their corresponding child nodes. Every node also has an `isEndOfWord` flag to indicate if any word ends at this node.

The `insert` function iterates through each character in a given word, adding new nodes to the tree if they don't already exist, and finally setting the `isEndOfWord` flag to true at the final node.

The `search` function follows the characters from the root of the Trie to the final node, returning false if any character does not map to a child node, otherwise returning the value of the `isEndOfWord` flag at the final node.

The `startsWith` function is similar to `search`, but returns true if a sequence of characters exists in the Trie, regardless of whether a word terminates at the final node.


# Minimum Size Subarray Sum

- slug: minimum-size-subarray-sum
- difficulty: Medium

Given an array of positive integers `nums` and a positive integer `target`, return _the **minimal length** of a_ _subarray_ _whose sum is greater than or equal to_ `target`. If there is no such subarray, return `0` instead.

**Example 1:**

**Input:** target = 7, nums = \[2,3,1,2,4,3\]
**Output:** 2
**Explanation:** The subarray \[4,3\] has the minimal length under the problem constraint.

**Example 2:**

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

**Example 3:**

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

**Constraints:**

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

**Follow up:** If you have figured out the `O(n)` solution, try coding another solution of which the time complexity is `O(n log(n))`.

## A solution in Java

```java
public int minSubArrayLen(int target, int[] nums) {
    int left = 0, cur_sum = 0, min_len = Integer.MAX_VALUE;
    for (int right = 0; right < nums.length; right++) {
        cur_sum += nums[right];
        while (cur_sum >= target) {
            min_len = Math.min(min_len, right - left + 1);
            cur_sum -= nums[left++];
        }
    }
    return min_len == Integer.MAX_VALUE ? 0 : min_len;
}
```
The algorithm initializes pointers left and right, sum cur_sum, and minimum length min_len. The right pointer traverses nums. During traversal, update cur_sum by adding nums[right]. Then check if cur_sum is greater than or equal to target. If so, update min_len by comparing min_len and the length of the current subarray (right - left + 1). Then update cur_sum by subtracting nums[left] and increment the left pointer. Continue this process until the end of nums is reached. If min_len is still at its max value at the end, return 0. Otherwise, return min_len.

This algorithm uses a sliding window technique to iterate through the array while maintaining subarray sums greater than or equal to the target.

## A solution in C++

```cpp
#include <climits>
int minSubArrayLen(int target, vector<int>& nums) {
    int left = 0, cur_sum = 0, min_len = INT_MAX;
    for (int right = 0; right < nums.size(); right++) {
        cur_sum += nums[right];
        while (cur_sum >= target) {
            min_len = min(min_len, right - left + 1);
            cur_sum -= nums[left++];
        }
    }
    return min_len == INT_MAX ? 0 : min_len;
}
```
The algorithm initializes pointers left and right, sum cur_sum, and minimum length min_len. The right pointer traverses nums. During traversal, update cur_sum by adding nums[right]. Then check if cur_sum is greater than or equal to target. If so, update min_len by comparing min_len and the length of the current subarray (right - left + 1). Then update cur_sum by subtracting nums[left] and increment the left pointer. Continue this process until the end of nums is reached. If min_len is still at its max value at the end, return 0. Otherwise, return min_len.

This algorithm uses a sliding window technique to iterate through the array while maintaining subarray sums greater than or equal to the target.

## A solution in Python

```python
def minSubArrayLen(target: int, nums: List[int]) -> int:
    left, cur_sum, min_len = 0, 0, float('inf')
    for right in range(len(nums)):
        cur_sum += nums[right]
        while cur_sum >= target:
            min_len = min(min_len, right - left + 1)
            cur_sum -= nums[left]
            left += 1
    return min_len if min_len != float('inf') else 0
```
The algorithm initializes pointers left and right, sum cur_sum, and minimum length min_len. The right pointer traverses nums. During traversal, update cur_sum by adding nums[right]. Then check if cur_sum is greater than or equal to target. If so, update min_len by comparing min_len and the length of the current subarray (right - left + 1). Then update cur_sum by subtracting nums[left] and increment the left pointer. Continue this process until the end of nums is reached. If min_len is still at its max value at the end, return 0. Otherwise, return min_len.

This algorithm uses a sliding window technique to iterate through the array while maintaining subarray sums greater than or equal to the target.

## A solution in Javascript

```javascript
function minSubArrayLen(target, nums) {
    let left = 0, cur_sum = 0, min_len = Number.MAX_VALUE;
    for (let right = 0; right < nums.length; right++) {
        cur_sum += nums[right];
        while (cur_sum >= target) {
            min_len = Math.min(min_len, right - left + 1);
            cur_sum -= nums[left++];
        }
    }
    return min_len === Number.MAX_VALUE ? 0 : min_len;
}
```
The algorithm initializes pointers left and right, sum cur_sum, and minimum length min_len. The right pointer traverses nums. During traversal, update cur_sum by adding nums[right]. Then check if cur_sum is greater than or equal to target. If so, update min_len by comparing min_len and the length of the current subarray (right - left + 1). Then update cur_sum by subtracting nums[left] and increment the left pointer. Continue this process until the end of nums is reached. If min_len is still at its max value at the end, return 0. Otherwise, return min_len.

This algorithm uses a sliding window technique to iterate through the array while maintaining subarray sums greater than or equal to the target.


# Course Schedule II

- slug: course-schedule-ii
- difficulty: Medium

There are a total of `numCourses` courses you have to take, labeled from `0` to `numCourses - 1`. You are given an array `prerequisites` where `prerequisites[i] = [ai, bi]` indicates that you **must** take course `bi` first if you want to take course `ai`.

*   For example, the pair `[0, 1]`, indicates that to take course `0` you have to first take course `1`.

Return _the ordering of courses you should take to finish all courses_. If there are many valid answers, return **any** of them. If it is impossible to finish all courses, return **an empty array**.

**Example 1:**

**Input:** numCourses = 2, prerequisites = \[\[1,0\]\]
**Output:** \[0,1\]
**Explanation:** There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is \[0,1\].

**Example 2:**

**Input:** numCourses = 4, prerequisites = \[\[1,0\],\[2,0\],\[3,1\],\[3,2\]\]
**Output:** \[0,2,1,3\]
**Explanation:** There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
So one correct course order is \[0,1,2,3\]. Another correct ordering is \[0,2,1,3\].

**Example 3:**

**Input:** numCourses = 1, prerequisites = \[\]
**Output:** \[0\]

**Constraints:**

*   `1 <= numCourses <= 2000`
*   `0 <= prerequisites.length <= numCourses * (numCourses - 1)`
*   `prerequisites[i].length == 2`
*   `0 <= ai, bi < numCourses`
*   `ai != bi`
*   All the pairs `[ai, bi]` are **distinct**.

## A solution in Java

```java
import java.util.*;

public int[] findOrder(int numCourses, int[][] prerequisites) {
    int[] inDegree = new int[numCourses];
    List<List<Integer>> adjList = new ArrayList<>();

    for (int i = 0; i < numCourses; i++) {
        adjList.add(new ArrayList<>());
    }

    for (int[] p : prerequisites) {
        adjList.get(p[1]).add(p[0]);
        inDegree[p[0]]++;
    }

    Queue<Integer> q = new LinkedList<>();
    for (int i = 0; i < numCourses; i++) {
        if (inDegree[i] == 0) {
            q.offer(i);
        }
    }

    int[] order = new int[numCourses];
    int index = 0;

    while (!q.isEmpty()) {
        int curr = q.poll();
        order[index++] = curr;
        for (int next : adjList.get(curr)) {
            if (--inDegree[next] == 0) {
                q.offer(next);
            }
        }
    }

    return (index == numCourses) ? order : new int[0];
}
```
This problem can be solved using the Topological Sort algorithm, which works in the following way:
1. Calculate the in-degree (number of incoming edges) of each node/course (use an array called `inDegree`).
2. Initialize an adjacency list, `adjList`, to store the outgoing courses from a prerequisite course.
3. Fill `adjList` while iterating through the prerequisites array.
4. Create a queue, `q`, and enqueue all the nodes whose in-degree is 0; these nodes represent the starting points in this topological sort.
5. Initialize an array or list called `order` to store the final ordering.
6. While `q` is not empty, perform the following steps:
    - Dequeue the front node `curr`.
    - Append `curr` to the `order`.
    - Iterate through all the outgoing courses (neighbors) of `curr`. For each neighboring node `next`, decrease the in-degree of `next` by 1. If the in-degree of `next` becomes 0, enqueue `next` to `q`.
7. Finally, if the length of the `order` is equal to the total number of courses, return the `order`. Otherwise, return an empty array/list, indicating that it is impossible to finish all the courses.

## A solution in C++

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

vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
    vector<int> inDegree(numCourses, 0);
    vector<vector<int>> adjList(numCourses);

    for (auto& p : prerequisites) {
        adjList[p[1]].push_back(p[0]);
        inDegree[p[0]]++;
    }

    queue<int> q;
    for (int i = 0; i < numCourses; i++) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }

    vector<int> order;

    while (!q.empty()) {
        int curr = q.front();
        q.pop();
        order.push_back(curr);
        for (auto next : adjList[curr]) {
            if (--inDegree[next] == 0) {
                q.push(next);
            }
        }
    }

    return (order.size() == numCourses) ? order : vector<int>();
}
```
This problem can be solved using the Topological Sort algorithm, which works in the following way:
1. Calculate the in-degree (number of incoming edges) of each node/course (use an array called `inDegree`).
2. Initialize an adjacency list, `adjList`, to store the outgoing courses from a prerequisite course.
3. Fill `adjList` while iterating through the prerequisites array.
4. Create a queue, `q`, and enqueue all the nodes whose in-degree is 0; these nodes represent the starting points in this topological sort.
5. Initialize an array or list called `order` to store the final ordering.
6. While `q` is not empty, perform the following steps:
    - Dequeue the front node `curr`.
    - Append `curr` to the `order`.
    - Iterate through all the outgoing courses (neighbors) of `curr`. For each neighboring node `next`, decrease the in-degree of `next` by 1. If the in-degree of `next` becomes 0, enqueue `next` to `q`.
7. Finally, if the length of the `order` is equal to the total number of courses, return the `order`. Otherwise, return an empty array/list, indicating that it is impossible to finish all the courses.

## A solution in Python

```python
from collections import deque

def findOrder(numCourses, prerequisites):
    in_degree = [0] * numCourses
    adj_list = [[] for _ in range(numCourses)]

    for p in prerequisites:
        adj_list[p[1]].append(p[0])
        in_degree[p[0]] += 1

    q = deque([i for i in range(numCourses) if in_degree[i] == 0])
    order = []

    while q:
        curr = q.popleft()
        order.append(curr)
        for next in adj_list[curr]:
            in_degree[next] -= 1
            if in_degree[next] == 0:
                q.append(next)

    return order if len(order) == numCourses else []
```
This problem can be solved using the Topological Sort algorithm, which works in the following way:
1. Calculate the in-degree (number of incoming edges) of each node/course (use an array called `inDegree`).
2. Initialize an adjacency list, `adjList`, to store the outgoing courses from a prerequisite course.
3. Fill `adjList` while iterating through the prerequisites array.
4. Create a queue, `q`, and enqueue all the nodes whose in-degree is 0; these nodes represent the starting points in this topological sort.
5. Initialize an array or list called `order` to store the final ordering.
6. While `q` is not empty, perform the following steps:
    - Dequeue the front node `curr`.
    - Append `curr` to the `order`.
    - Iterate through all the outgoing courses (neighbors) of `curr`. For each neighboring node `next`, decrease the in-degree of `next` by 1. If the in-degree of `next` becomes 0, enqueue `next` to `q`.
7. Finally, if the length of the `order` is equal to the total number of courses, return the `order`. Otherwise, return an empty array/list, indicating that it is impossible to finish all the courses.

## A solution in Javascript

```javascript
function findOrder(numCourses, prerequisites) {
    const inDegree = new Array(numCourses).fill(0);
    const adjList = Array.from({ length: numCourses }, () => []);

    for (const p of prerequisites) {
        adjList[p[1]].push(p[0]);
        inDegree[p[0]]++;
    }

    const q = [];
    for (let i = 0; i < numCourses; i++) {
        if (inDegree[i] === 0) {
            q.push(i);
        }
    }

    const order = [];

    while (q.length) {
        const curr = q.shift();
        order.push(curr);
        for (const next of adjList[curr]) {
            if (--inDegree[next] === 0) {
                q.push(next);
            }
        }
    }

    return (order.length === numCourses) ? order : [];
}
```
This problem can be solved using the Topological Sort algorithm, which works in the following way:
1. Calculate the in-degree (number of incoming edges) of each node/course (use an array called `inDegree`).
2. Initialize an adjacency list, `adjList`, to store the outgoing courses from a prerequisite course.
3. Fill `adjList` while iterating through the prerequisites array.
4. Create a queue, `q`, and enqueue all the nodes whose in-degree is 0; these nodes represent the starting points in this topological sort.
5. Initialize an array or list called `order` to store the final ordering.
6. While `q` is not empty, perform the following steps:
    - Dequeue the front node `curr`.
    - Append `curr` to the `order`.
    - Iterate through all the outgoing courses (neighbors) of `curr`. For each neighboring node `next`, decrease the in-degree of `next` by 1. If the in-degree of `next` becomes 0, enqueue `next` to `q`.
7. Finally, if the length of the `order` is equal to the total number of courses, return the `order`. Otherwise, return an empty array/list, indicating that it is impossible to finish all the courses.


# Design Add and Search Words Data Structure

- slug: design-add-and-search-words-data-structure
- difficulty: Medium

Design a data structure that supports adding new words and finding if a string matches any previously added string.

Implement the `WordDictionary` class:

*   `WordDictionary()` Initializes the object.
*   `void addWord(word)` Adds `word` to the data structure, it can be matched later.
*   `bool search(word)` Returns `true` if there is any string in the data structure that matches `word` or `false` otherwise. `word` may contain dots `'.'` where dots can be matched with any letter.

**Example:**

**Input**
\[ "WordDictionary ", "addWord ", "addWord ", "addWord ", "search ", "search ", "search ", "search "\]
\[\[\],\[ "bad "\],\[ "dad "\],\[ "mad "\],\[ "pad "\],\[ "bad "\],\[ ".ad "\],\[ "b.. "\]\]
**Output**
\[null,null,null,null,false,true,true,true\]

**Explanation**
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord( "bad ");
wordDictionary.addWord( "dad ");
wordDictionary.addWord( "mad ");
wordDictionary.search( "pad "); // return False
wordDictionary.search( "bad "); // return True
wordDictionary.search( ".ad "); // return True
wordDictionary.search( "b.. "); // return True

**Constraints:**

*   `1 <= word.length <= 25`
*   `word` in `addWord` consists of lowercase English letters.
*   `word` in `search` consist of `'.'` or lowercase English letters.
*   There will be at most `2` dots in `word` for `search` queries.
*   At most `104` calls will be made to `addWord` and `search`.

## A solution in Java

```java
class WordDictionary {
    private static class TrieNode {
        TrieNode[] children = new TrieNode[26];
        boolean is_word;
    }

    private TrieNode root;

    public WordDictionary() {
        root = new TrieNode();
    }

    public void addWord(String word) {
        TrieNode current = root;
        for (char c : word.toCharArray()) {
            if (current.children[c - 'a'] == null) {
                current.children[c - 'a'] = new TrieNode();
            }
            current = current.children[c - 'a'];
        }
        current.is_word = true;
    }

    public boolean search(String word) {
        return searchHelper(root, word, 0);
    }

    private boolean searchHelper(TrieNode node, String word, int index) {
        if (index == word.length()) {
            return node.is_word;
        }

        if (word.charAt(index) == '.') {
            for (int i = 0; i < 26; i++) {
                if (node.children[i] != null && searchHelper(node.children[i], word, index + 1)) {
                    return true;
                }
            }
            return false;
        } else {
            if (node.children[word.charAt(index) - 'a'] == null) {
                return false;
            }
            return searchHelper(node.children[word.charAt(index) - 'a'], word, index + 1);
        }
    }
}
```
We use a Trie data structure to store the words. Each Trie node has an array of child pointers for all lowercase English letters (size 26) and a boolean flag `is_word` indicating if the word ends at this node. Initially, all child pointers are set to null, and `is_word` is set to false.

When we add a word, we walk through the Trie, creating new child nodes if necessary, and set `is_word` to true for the last Trie node representing the word's last character.

When we search for a word, we use a helper function that takes the current Trie node, the word, and the current position in the word. If the current character in the word is a dot (`.`), we search for any matching character by iterating through all its children, recursively calling the helper function with the next position in the word. If the current character in the word is a lowercase letter, we proceed to the corresponding child node and continue the search.

At any point, if we reach the word's end, we check if the `is_word` of the current Trie node is true. If it is, we found a match. Otherwise, the search continues.

## A solution in C++

```cpp
class WordDictionary {
public:
    struct TrieNode {
        TrieNode* children[26];
        bool is_word;
    };

    TrieNode* root;

    WordDictionary() {
        root = new TrieNode();
    }

    void addWord(string word) {
        TrieNode* current = root;
        for (char c : word) {
            if (current->children[c - 'a'] == nullptr) {
                current->children[c - 'a'] = new TrieNode();
            }
            current = current->children[c - 'a'];
        }
        current->is_word = true;
    }

    bool search(string word) {
        return searchHelper(root, word, 0);
    }

    bool searchHelper(TrieNode* node, string& word, int index) {
        if (index == word.length()) {
            return node->is_word;
        }

        if (word[index] == '.') {
            for (int i = 0; i < 26; i++) {
                if (node->children[i] != nullptr && searchHelper(node->children[i], word, index + 1)) {
                    return true;
                }
            }
            return false;
        } else {
            if (node->children[word[index] - 'a'] == nullptr) {
                return false;
            }
            return searchHelper(node->children[word[index] - 'a'], word, index + 1);
        }
    }
};
```
We use a Trie data structure to store the words. Each Trie node has an array of child pointers for all lowercase English letters (size 26) and a boolean flag `is_word` indicating if the word ends at this node. Initially, all child pointers are set to null, and `is_word` is set to false.

When we add a word, we walk through the Trie, creating new child nodes if necessary, and set `is_word` to true for the last Trie node representing the word's last character.

When we search for a word, we use a helper function that takes the current Trie node, the word, and the current position in the word. If the current character in the word is a dot (`.`), we search for any matching character by iterating through all its children, recursively calling the helper function with the next position in the word. If the current character in the word is a lowercase letter, we proceed to the corresponding child node and continue the search.

At any point, if we reach the word's end, we check if the `is_word` of the current Trie node is true. If it is, we found a match. Otherwise, the search continues.

## A solution in Python

```python
class TrieNode:
    def __init__(self):
        self.children = [None] * 26
        self.is_word = False

class WordDictionary:
    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word: str) -> None:
        current = self.root
        for c in word:
            index = ord(c) - ord('a')
            if current.children[index] is None:
                current.children[index] = TrieNode()
            current = current.children[index]
        current.is_word = True

    def search(self, word: str) -> bool:
        return self._search_helper(self.root, word, 0)

    def _search_helper(self, node: TrieNode, word: str, index: int) -> bool:
        if index == len(word):
            return node.is_word

        if word[index] == '.':
            for child_node in node.children:
                if child_node is not None and self._search_helper(child_node, word, index + 1):
                    return True
            return False
        else:
            child_node = node.children[ord(word[index]) - ord('a')]
            if child_node is None:
                return False
            return self._search_helper(child_node, word, index + 1)
```
We use a Trie data structure to store the words. Each Trie node has an array of child pointers for all lowercase English letters (size 26) and a boolean flag `is_word` indicating if the word ends at this node. Initially, all child pointers are set to null, and `is_word` is set to false.

When we add a word, we walk through the Trie, creating new child nodes if necessary, and set `is_word` to true for the last Trie node representing the word's last character.

When we search for a word, we use a helper function that takes the current Trie node, the word, and the current position in the word. If the current character in the word is a dot (`.`), we search for any matching character by iterating through all its children, recursively calling the helper function with the next position in the word. If the current character in the word is a lowercase letter, we proceed to the corresponding child node and continue the search.

At any point, if we reach the word's end, we check if the `is_word` of the current Trie node is true. If it is, we found a match. Otherwise, the search continues.

## A solution in Javascript

```javascript
class TrieNode {
    constructor() {
        this.children = new Array(26).fill(null);
        this.is_word = false;
    }
}

class WordDictionary {
    constructor() {
        this.root = new TrieNode();
    }

    addWord(word) {
        let current = this.root;
        for (const c of word) {
            const index = c.charCodeAt(0) - 'a'.charCodeAt(0);
            if (!current.children[index]) {
                current.children[index] = new TrieNode();
            }
            current = current.children[index];
        }
        current.is_word = true;
    }

    search(word) {
        return this._searchHelper(this.root, word, 0);
    }

    _searchHelper(node, word, index) {
        if (index === word.length) {
            return node.is_word;
        }

        if (word[index] === '.') {
            for (let i = 0; i < 26; i++) {
                if (node.children[i] && this._searchHelper(node.children[i], word, index + 1)) {
                    return true;
                }
            }
            return false;
        } else {
            const childIndex = word.charCodeAt(index) - 'a'.charCodeAt(0);
            if (!node.children[childIndex]) {
                return false;
            }
            return this._searchHelper(node.children[childIndex], word, index + 1);
        }
    }
}
```
We use a Trie data structure to store the words. Each Trie node has an array of child pointers for all lowercase English letters (size 26) and a boolean flag `is_word` indicating if the word ends at this node. Initially, all child pointers are set to null, and `is_word` is set to false.

When we add a word, we walk through the Trie, creating new child nodes if necessary, and set `is_word` to true for the last Trie node representing the word's last character.

When we search for a word, we use a helper function that takes the current Trie node, the word, and the current position in the word. If the current character in the word is a dot (`.`), we search for any matching character by iterating through all its children, recursively calling the helper function with the next position in the word. If the current character in the word is a lowercase letter, we proceed to the corresponding child node and continue the search.

At any point, if we reach the word's end, we check if the `is_word` of the current Trie node is true. If it is, we found a match. Otherwise, the search continues.


# Word Search II

- slug: word-search-ii
- difficulty: Hard

Given an `m x n` `board` of characters and a list of strings `words`, return _all words on the board_.

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

**Example 1:**

**Input:** board = \[\[ "o ", "a ", "a ", "n "\],\[ "e ", "t ", "a ", "e "\],\[ "i ", "h ", "k ", "r "\],\[ "i ", "f ", "l ", "v "\]\], words = \[ "oath ", "pea ", "eat ", "rain "\]
**Output:** \[ "eat ", "oath "\]

**Example 2:**

**Input:** board = \[\[ "a ", "b "\],\[ "c ", "d "\]\], words = \[ "abcb "\]
**Output:** \[\]

**Constraints:**

*   `m == board.length`
*   `n == board[i].length`
*   `1 <= m, n <= 12`
*   `board[i][j]` is a lowercase English letter.
*   `1 <= words.length <= 3 * 104`
*   `1 <= words[i].length <= 10`
*   `words[i]` consists of lowercase English letters.
*   All the strings of `words` are unique.

## A solution in Java

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

public List<String> findWords(char[][] board, String[] words) {
    List<String> result = new ArrayList<>();
    for (String word : words) {
        if (exist(board, word)) {
            result.add(word);
        }
    }
    return result;
}

private boolean exist(char[][] board, String word) {
    int m = board.length;
    int n = board[0].length;
    boolean[][] visited = new boolean[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (dfs(board, word, 0, i, j, visited)) {
                return true;
            }
        }
    }
    return false;
}

private boolean dfs(char[][] board, String word, int index, int i, int j, boolean[][] visited) {
    if (index == word.length()) {
        return true;
    }
    if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j] || board[i][j] != word.charAt(index)) {
        return false;
    }
    visited[i][j] = true;
    boolean found =
            dfs(board, word, index + 1, i - 1, j, visited) ||
            dfs(board, word, index + 1, i + 1, j, visited) ||
            dfs(board, word, index + 1, i, j - 1, visited) ||
            dfs(board, word, index + 1, i, j + 1, visited);
    visited[i][j] = false;
    return found;
}
```
The algorithm uses Depth First Search (DFS) to search for each word in the board. For each word, we iterate through all the cells in the board and start the DFS search if the current cell matches the word's first letter. During the DFS search, we mark the cell as visited and only continue the search if the next cell we are going to move to is not yet visited, in the allowed board bounds, and it matches the next character of the word. If we reached the end of the word, then we know that this word is found in the board.

For each programming language, we implemented the `findWords` function that takes the `board` and the `words` as an input and returns a list of found words. The core algorithm is the same, but the language-specific syntax and constructs are used accordingly.

## A solution in C++

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

void dfs(const std::vector<std::vector<char>>& board, const std::string& word, int index, int i, int j, std::vector<std::vector<bool>>& visited, bool& found){
    if (index == word.length()) {
        found = true;
        return;
    }
    if (i < 0 || j < 0 || i >= board.size() || j >= board[0].size() || visited[i][j] || board[i][j] != word[index]){
        return;
    }
    visited[i][j] = true;
    dfs(board, word, index + 1, i - 1, j, visited, found);
    dfs(board, word, index + 1, i + 1, j, visited, found);
    dfs(board, word, index + 1, i, j - 1, visited, found);
    dfs(board, word, index + 1, i, j + 1, visited, found);
    visited[i][j] = false;
}

std::vector<std::string> findWords(std::vector<std::vector<char>>& board, std::vector<std::string>& words) {
    std::vector<std::string> result;
    for (const auto& word : words) {
        bool found = false;
        std::vector<std::vector<bool>> visited(board.size(), std::vector<bool>(board[0].size(), false));
        for (int i = 0; i < board.size() && !found; ++i) {
            for (int j = 0; j < board[0].size() && !found; ++j) {
                dfs(board, word, 0, i, j, visited, found);
            }
        }
        if (found) {
            result.push_back(word);
        }
    }
    return result;
}
```
The algorithm uses Depth First Search (DFS) to search for each word in the board. For each word, we iterate through all the cells in the board and start the DFS search if the current cell matches the word's first letter. During the DFS search, we mark the cell as visited and only continue the search if the next cell we are going to move to is not yet visited, in the allowed board bounds, and it matches the next character of the word. If we reached the end of the word, then we know that this word is found in the board.

For each programming language, we implemented the `findWords` function that takes the `board` and the `words` as an input and returns a list of found words. The core algorithm is the same, but the language-specific syntax and constructs are used accordingly.

## A solution in Python

```python
def findWords(board, words):
    def dfs(board, word, index, i, j, visited):
        if index == len(word):
            return True
        if i < 0 or j < 0 or i >= len(board) or j >= len(board[0]) or visited[i][j] or board[i][j] != word[index]:
            return False
        visited[i][j] = True
        found = dfs(board, word, index + 1, i - 1, j, visited) or \
                dfs(board, word, index + 1, i + 1, j, visited) or \
                dfs(board, word, index + 1, i, j - 1, visited) or \
                dfs(board, word, index + 1, i, j + 1, visited)
        visited[i][j] = False
        return found

    res = []
    for word in words:
        if any(dfs(board, word, 0, i, j, [[False] * len(board[0]) for _ in range(len(board))])
               for i in range(len(board)) for j in range(len(board[0]))):
            res.append(word)
    return res
```
The algorithm uses Depth First Search (DFS) to search for each word in the board. For each word, we iterate through all the cells in the board and start the DFS search if the current cell matches the word's first letter. During the DFS search, we mark the cell as visited and only continue the search if the next cell we are going to move to is not yet visited, in the allowed board bounds, and it matches the next character of the word. If we reached the end of the word, then we know that this word is found in the board.

For each programming language, we implemented the `findWords` function that takes the `board` and the `words` as an input and returns a list of found words. The core algorithm is the same, but the language-specific syntax and constructs are used accordingly.

## A solution in Javascript

```javascript
function findWords(board, words) {
    function dfs(board, word, index, i, j, visited) {
        if (index === word.length) {
            return true;
        }
        if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j] || board[i][j] !== word.charAt(index)) {
            return false;
        }
        visited[i][j] = true;
        const found = dfs(board, word, index + 1, i - 1, j, visited) ||
                      dfs(board, word, index + 1, i + 1, j, visited) ||
                      dfs(board, word, index + 1, i, j - 1, visited) ||
                      dfs(board, word, index + 1, i, j + 1, visited);
        visited[i][j] = false;
        return found;
    }

    const res = [];
    for (const word of words) {
        let found = false;
        for (let i = 0; i < board.length && !found; i++) {
            for (let j = 0; j < board[0].length && !found; j++) {
                if (dfs(board, word, 0, i, j, Array.from({ length: board.length }, () => Array(board[0].length).fill(false)))) {
                    found = true;
                }
            }
        }
        if (found) {
            res.push(word);
        }
    }
    return res;
}
```
The algorithm uses Depth First Search (DFS) to search for each word in the board. For each word, we iterate through all the cells in the board and start the DFS search if the current cell matches the word's first letter. During the DFS search, we mark the cell as visited and only continue the search if the next cell we are going to move to is not yet visited, in the allowed board bounds, and it matches the next character of the word. If we reached the end of the word, then we know that this word is found in the board.

For each programming language, we implemented the `findWords` function that takes the `board` and the `words` as an input and returns a list of found words. The core algorithm is the same, but the language-specific syntax and constructs are used accordingly.


# House Robber II

- slug: house-robber-ii
- difficulty: Medium

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are **arranged in a circle.** That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and **it will automatically contact the police if two adjacent houses were broken into on the same night**.

Given an integer array `nums` representing the amount of money of each house, return _the maximum amount of money you can rob tonight **without alerting the police**_.

**Example 1:**

**Input:** nums = \[2,3,2\]
**Output:** 3
**Explanation:** You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.

**Example 2:**

**Input:** nums = \[1,2,3,1\]
**Output:** 4
**Explanation:** Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

**Example 3:**

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

**Constraints:**

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

## A solution in Java

```java
public int rob(int[] nums) {
    if (nums.length == 1) return nums[0];
    int prev = 0, curr = 0;
    for (int i = 0; i < nums.length - 1; i++) {
        int temp = Math.max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    int res = curr;
    prev = 0;
    curr = 0;
    for (int i = 1; i < nums.length; i++) {
        int temp = Math.max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    return Math.max(res, curr);
}
```
The main idea here is to divide the problem into two subproblems: rob houses from the first to the second last, and rob houses from the second to the last. First, initialize two variables prev and curr to store the maximum amount obtained till the current house. Then, loop through the houses from the first to the second last, and at each step, update the maximum amount till the current house by choosing between two options: rob the current house (prev + nums[i]) or skip it (curr). Repeat the process for houses from the second to the last. Finally, return the maximum amount among both subproblems.

## A solution in C++

```cpp
int rob(vector<int>& nums) {
    if (nums.size() == 1) return nums[0];
    int prev = 0, curr = 0;
    for (int i = 0; i < nums.size() - 1; i++) {
        int temp = max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    int res = curr;
    prev = 0;
    curr = 0;
    for (int i = 1; i < nums.size(); i++) {
        int temp = max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    return max(res, curr);
}
```
The main idea here is to divide the problem into two subproblems: rob houses from the first to the second last, and rob houses from the second to the last. First, initialize two variables prev and curr to store the maximum amount obtained till the current house. Then, loop through the houses from the first to the second last, and at each step, update the maximum amount till the current house by choosing between two options: rob the current house (prev + nums[i]) or skip it (curr). Repeat the process for houses from the second to the last. Finally, return the maximum amount among both subproblems.

## A solution in Python

```python
def rob(nums):
    if len(nums) == 1:
        return nums[0]
    prev, curr = 0, 0
    for i in range(len(nums) - 1):
        temp = max(curr, prev + nums[i])
        prev, curr = curr, temp
    res = curr
    prev, curr = 0, 0
    for i in range(1, len(nums)):
        temp = max(curr, prev + nums[i])
        prev, curr = curr, temp
    return max(res, curr)
```
The main idea here is to divide the problem into two subproblems: rob houses from the first to the second last, and rob houses from the second to the last. First, initialize two variables prev and curr to store the maximum amount obtained till the current house. Then, loop through the houses from the first to the second last, and at each step, update the maximum amount till the current house by choosing between two options: rob the current house (prev + nums[i]) or skip it (curr). Repeat the process for houses from the second to the last. Finally, return the maximum amount among both subproblems.

## A solution in Javascript

```javascript
function rob(nums) {
    if (nums.length === 1) return nums[0];
    let prev = 0, curr = 0;
    for (let i = 0; i < nums.length - 1; i++) {
        let temp = Math.max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    let res = curr;
    prev = 0;
    curr = 0;
    for (let i = 1; i < nums.length; i++) {
        let temp = Math.max(curr, prev + nums[i]);
        prev = curr;
        curr = temp;
    }
    return Math.max(res, curr);
}
```
The main idea here is to divide the problem into two subproblems: rob houses from the first to the second last, and rob houses from the second to the last. First, initialize two variables prev and curr to store the maximum amount obtained till the current house. Then, loop through the houses from the first to the second last, and at each step, update the maximum amount till the current house by choosing between two options: rob the current house (prev + nums[i]) or skip it (curr). Repeat the process for houses from the second to the last. Finally, return the maximum amount among both subproblems.


# Shortest Palindrome

- slug: shortest-palindrome
- difficulty: Hard

You are given a string `s`. You can convert `s` to a palindrome by adding characters in front of it.

Return _the shortest palindrome you can find by performing this transformation_.

**Example 1:**

**Input:** s = "aacecaaa"
**Output:** "aaacecaaa"

**Example 2:**

**Input:** s = "abcd"
**Output:** "dcbabcd"

**Constraints:**

*   `0 <= s.length <= 5 * 104`
*   `s` consists of lowercase English letters only.

## A solution in Java

```java
public String shortestPalindrome(String s) {
    int n = s.length();
    String rev_s = new StringBuilder(s).reverse().toString();

    for (int i = 0; i < n; ++i) {
        if(s.substring(0, n - i).equals(rev_s.substring(i)))
            return rev_s.substring(0, i) + s;
    }
    return "";
}
```
1. Take input string `s`.
2. Get string `rev_s` by reversing the input string.
3. Iterate through the characters in both strings.
4. For each index `i`, compare the substring `[0, n - i)` of `s` and substring `[i, n)` of `rev_s`.
5. If the substrings match, concatenate the non-matching substring of `rev_s` and the original input string `s`. This will result in the shortest palindromic string we can build.
6. If not, continue with the next iteration.
7. The function returns an empty string if an exception occurs.

## A solution in C++

```cpp
#include <string>

std::string shortestPalindrome(std::string s) {
    int n = s.size();
    std::string rev_s = s;
    std::reverse(rev_s.begin(), rev_s.end());

    for (int i = 0; i < n; ++i) {
        if(s.substr(0, n - i) == rev_s.substr(i))
            return rev_s.substr(0, i) + s;
    }
    return "";
}
```
1. Take input string `s`.
2. Get string `rev_s` by reversing the input string.
3. Iterate through the characters in both strings.
4. For each index `i`, compare the substring `[0, n - i)` of `s` and substring `[i, n)` of `rev_s`.
5. If the substrings match, concatenate the non-matching substring of `rev_s` and the original input string `s`. This will result in the shortest palindromic string we can build.
6. If not, continue with the next iteration.
7. The function returns an empty string if an exception occurs.

## A solution in Python

```python
def shortest_palindrome(s: str) -> str:
    n = len(s)
    rev_s = s[::-1]

    for i in range(n):
        if s[:n - i] == rev_s[i:]:
            return rev_s[:i] + s
    return ""
```
1. Take input string `s`.
2. Get string `rev_s` by reversing the input string.
3. Iterate through the characters in both strings.
4. For each index `i`, compare the substring `[0, n - i)` of `s` and substring `[i, n)` of `rev_s`.
5. If the substrings match, concatenate the non-matching substring of `rev_s` and the original input string `s`. This will result in the shortest palindromic string we can build.
6. If not, continue with the next iteration.
7. The function returns an empty string if an exception occurs.

## A solution in Javascript

```javascript
function shortestPalindrome(s) {
    let n = s.length;
    let rev_s = s.split('').reverse().join('');

    for (let i = 0; i < n; ++i) {
        if (s.slice(0, n - i) === rev_s.slice(i))
            return rev_s.slice(0, i) + s;
    }
    return "";
}
```
1. Take input string `s`.
2. Get string `rev_s` by reversing the input string.
3. Iterate through the characters in both strings.
4. For each index `i`, compare the substring `[0, n - i)` of `s` and substring `[i, n)` of `rev_s`.
5. If the substrings match, concatenate the non-matching substring of `rev_s` and the original input string `s`. This will result in the shortest palindromic string we can build.
6. If not, continue with the next iteration.
7. The function returns an empty string if an exception occurs.


# Kth Largest Element in an Array

- slug: kth-largest-element-in-an-array
- difficulty: Medium

Given an integer array `nums` and an integer `k`, return _the_ `kth` _largest element in the array_.

Note that it is the `kth` largest element in the sorted order, not the `kth` distinct element.

You must solve it in `O(n)` time complexity.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

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

## A solution in Java

```java
import java.util.PriorityQueue;

public int findKthLargest(int[] nums, int k) {
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    for (int num : nums) {
        minHeap.add(num);
        if (minHeap.size() > k) {
            minHeap.poll();
        }
    }
    return minHeap.poll();
}
```
The algorithm sorts the input array in descending order (non-increasing order). Then it returns the element at the index `k-1`. In the case of the C++ and Python implementations, the built-in `sort()` method was used to sort the array in descending order, while in the Java implementation, a min-heap was used for efficiency. In the Javascript implementation, the custom comparator `(a, b) => b - a` was used to sort the input array in descending order.

Sorting the array in descending order ensures that the kth largest element will be located at the index `k-1` (since indexing starts at 0).

## A solution in C++

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

int findKthLargest(std::vector<int>& nums, int k) {
    std::sort(nums.begin(), nums.end(), std::greater<int>());
    return nums[k-1];
}
```
The algorithm sorts the input array in descending order (non-increasing order). Then it returns the element at the index `k-1`. In the case of the C++ and Python implementations, the built-in `sort()` method was used to sort the array in descending order, while in the Java implementation, a min-heap was used for efficiency. In the Javascript implementation, the custom comparator `(a, b) => b - a` was used to sort the input array in descending order.

Sorting the array in descending order ensures that the kth largest element will be located at the index `k-1` (since indexing starts at 0).

## A solution in Python

```python
def findKthLargest(nums: List[int], k: int) -> int:
    nums.sort(reverse=True)
    return nums[k-1]
```
The algorithm sorts the input array in descending order (non-increasing order). Then it returns the element at the index `k-1`. In the case of the C++ and Python implementations, the built-in `sort()` method was used to sort the array in descending order, while in the Java implementation, a min-heap was used for efficiency. In the Javascript implementation, the custom comparator `(a, b) => b - a` was used to sort the input array in descending order.

Sorting the array in descending order ensures that the kth largest element will be located at the index `k-1` (since indexing starts at 0).

## A solution in Javascript

```javascript
function findKthLargest(nums, k) {
    nums.sort((a, b) => b - a);
    return nums[k - 1];
}
```
The algorithm sorts the input array in descending order (non-increasing order). Then it returns the element at the index `k-1`. In the case of the C++ and Python implementations, the built-in `sort()` method was used to sort the array in descending order, while in the Java implementation, a min-heap was used for efficiency. In the Javascript implementation, the custom comparator `(a, b) => b - a` was used to sort the input array in descending order.

Sorting the array in descending order ensures that the kth largest element will be located at the index `k-1` (since indexing starts at 0).


# Combination Sum III

- slug: combination-sum-iii
- difficulty: Medium

Find all valid combinations of `k` numbers that sum up to `n` such that the following conditions are true:

*   Only numbers `1` through `9` are used.
*   Each number is used **at most once**.

Return _a list of all possible valid combinations_. The list must not contain the same combination twice, and the combinations may be returned in any order.

**Example 1:**

**Input:** k = 3, n = 7
**Output:** \[\[1,2,4\]\]
**Explanation:**
1 + 2 + 4 = 7
There are no other valid combinations.

**Example 2:**

**Input:** k = 3, n = 9
**Output:** \[\[1,2,6\],\[1,3,5\],\[2,3,4\]\]
**Explanation:**
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
There are no other valid combinations.

**Example 3:**

**Input:** k = 4, n = 1
**Output:** \[\]
**Explanation:** There are no valid combinations.
Using 4 different numbers in the range \[1,9\], the smallest sum we can get is 1+2+3+4 = 10 and since 10 > 1, there are no valid combination.

**Constraints:**

*   `2 <= k <= 9`
*   `1 <= n <= 60`

## A solution in Java

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

public List<List<Integer>> combinationSum3(int k, int n) {
    List<List<Integer>> result = new ArrayList<>();
    helper(k, n, 0, new ArrayList<>(), result);
    return result;
}

private void helper(int k, int n, int current, List<Integer> currentComb, List<List<Integer>> result) {
    if (k == 0 && n == 0) {
        result.add(new ArrayList<>(currentComb));
    } else if (k > 0 && n > 0) {
        for (int i = current + 1; i <= 9; i++) {
            currentComb.add(i);
            helper(k - 1, n - i, i, currentComb, result);
            currentComb.remove(currentComb.size() - 1);
        }
    }
}
```
The algorithm is based on a backtracking approach. We use a helper function which takes some parameters: `k` and `n` to limit the combinations, `current` which is the last considered element, `current_comb` which is the current combination being formed, and `result` which is the list of all valid combinations found so far.

We keep updating the current combination and decreasing `k` and `n` accordingly as we call the helper function recursively. When we have `k = 0` and `n = 0`, we know we have reached a valid combination and add it to our result list. To prevent revisiting the same combinations, we make sure that the numbers are considered in increasing order (thus, the current value being picked always starts at `current + 1`).

When backtracking, we remove the last considered element from the current combination so that we can try another combination. Following this approach ensures that we visit every potential combination only once and store it if it is valid.

## A solution in C++

```cpp
#include <vector>

void helper(int k, int n, int current, std::vector<int>& current_comb, std::vector<std::vector<int>>& result) {
    if (k == 0 && n == 0) {
        result.push_back(current_comb);
    } else if (k > 0 && n > 0) {
        for (int i = current + 1; i <= 9; ++i) {
            current_comb.push_back(i);
            helper(k - 1, n - i, i, current_comb, result);
            current_comb.pop_back();
        }
    }
}

std::vector<std::vector<int>> combinationSum3(int k, int n) {
    std::vector<std::vector<int>> result;
    std::vector<int> current_comb;
    helper(k, n, 0, current_comb, result);
    return result;
}
```
The algorithm is based on a backtracking approach. We use a helper function which takes some parameters: `k` and `n` to limit the combinations, `current` which is the last considered element, `current_comb` which is the current combination being formed, and `result` which is the list of all valid combinations found so far.

We keep updating the current combination and decreasing `k` and `n` accordingly as we call the helper function recursively. When we have `k = 0` and `n = 0`, we know we have reached a valid combination and add it to our result list. To prevent revisiting the same combinations, we make sure that the numbers are considered in increasing order (thus, the current value being picked always starts at `current + 1`).

When backtracking, we remove the last considered element from the current combination so that we can try another combination. Following this approach ensures that we visit every potential combination only once and store it if it is valid.

## A solution in Python

```python
def combinationSum3(k, n):
    def helper(k, n, current, current_comb, result):
        if k == 0 and n == 0:
            result.append(list(current_comb))
        elif k > 0 and n > 0:
            for i in range(current + 1, 10):
                current_comb.append(i)
                helper(k - 1, n - i, i, current_comb, result)
                current_comb.pop()

    result = []
    helper(k, n, 0, [], result)
    return result
```
The algorithm is based on a backtracking approach. We use a helper function which takes some parameters: `k` and `n` to limit the combinations, `current` which is the last considered element, `current_comb` which is the current combination being formed, and `result` which is the list of all valid combinations found so far.

We keep updating the current combination and decreasing `k` and `n` accordingly as we call the helper function recursively. When we have `k = 0` and `n = 0`, we know we have reached a valid combination and add it to our result list. To prevent revisiting the same combinations, we make sure that the numbers are considered in increasing order (thus, the current value being picked always starts at `current + 1`).

When backtracking, we remove the last considered element from the current combination so that we can try another combination. Following this approach ensures that we visit every potential combination only once and store it if it is valid.

## A solution in Javascript

```javascript
function combinationSum3(k, n) {
  function helper(k, n, current, currentComb, result) {
    if (k === 0 && n === 0) {
      result.push([...currentComb]);
    } else if (k > 0 && n > 0) {
      for (let i = current + 1; i <= 9; i++) {
        currentComb.push(i);
        helper(k - 1, n - i, i, currentComb, result);
        currentComb.pop();
      }
    }
  }

  const result = [];
  helper(k, n, 0, [], result);
  return result;
}
```
The algorithm is based on a backtracking approach. We use a helper function which takes some parameters: `k` and `n` to limit the combinations, `current` which is the last considered element, `current_comb` which is the current combination being formed, and `result` which is the list of all valid combinations found so far.

We keep updating the current combination and decreasing `k` and `n` accordingly as we call the helper function recursively. When we have `k = 0` and `n = 0`, we know we have reached a valid combination and add it to our result list. To prevent revisiting the same combinations, we make sure that the numbers are considered in increasing order (thus, the current value being picked always starts at `current + 1`).

When backtracking, we remove the last considered element from the current combination so that we can try another combination. Following this approach ensures that we visit every potential combination only once and store it if it is valid.


# Contains Duplicate

- slug: contains-duplicate
- difficulty: Easy

Given an integer array `nums`, return `true` if any value appears **at least twice** in the array, and return `false` if every element is distinct.

**Example 1:**

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

**Example 2:**

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

**Example 3:**

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

**Constraints:**

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

## A solution in Java

```java
public boolean containsDuplicate(int[] nums) {
    Set<Integer> set = new HashSet<Integer>();
    for (int num : nums) {
        if (!set.add(num)) {
            return true;
        }
    }
    return false;
}
```
The algorithm starts by creating an empty set. Then it iterates through the input array. For each number in the array, it checks if the number is already in the set. If the number is in the set, it means there's a duplicate, so it returns true. If the number is not in the set, it adds the number to the set. If the function has not returned true after iterating through the entire array, it means that there are no duplicates, so it returns false.

In Python, we use the fact that sets don't allow duplicates, so we can directly compare the length of the original list with the length of the set created from the list. If they are not equal, it means there are duplicates in the list, and the function returns true. Otherwise, it returns false.

## A solution in C++

```cpp
bool containsDuplicate(vector<int>& nums) {
    unordered_set<int> s;
    for (int num : nums) {
        if (s.find(num) != s.end()) {
            return true;
        }
        s.insert(num);
    }
    return false;
}
```
The algorithm starts by creating an empty set. Then it iterates through the input array. For each number in the array, it checks if the number is already in the set. If the number is in the set, it means there's a duplicate, so it returns true. If the number is not in the set, it adds the number to the set. If the function has not returned true after iterating through the entire array, it means that there are no duplicates, so it returns false.

In Python, we use the fact that sets don't allow duplicates, so we can directly compare the length of the original list with the length of the set created from the list. If they are not equal, it means there are duplicates in the list, and the function returns true. Otherwise, it returns false.

## A solution in Python

```python
def containsDuplicate(nums):
    return len(nums) != len(set(nums))
```
The algorithm starts by creating an empty set. Then it iterates through the input array. For each number in the array, it checks if the number is already in the set. If the number is in the set, it means there's a duplicate, so it returns true. If the number is not in the set, it adds the number to the set. If the function has not returned true after iterating through the entire array, it means that there are no duplicates, so it returns false.

In Python, we use the fact that sets don't allow duplicates, so we can directly compare the length of the original list with the length of the set created from the list. If they are not equal, it means there are duplicates in the list, and the function returns true. Otherwise, it returns false.

## A solution in Javascript

```javascript
function containsDuplicate(nums) {
    const set = new Set();
    for (const num of nums) {
        if (set.has(num)) {
            return true;
        }
        set.add(num);
    }
    return false;
}
```
The algorithm starts by creating an empty set. Then it iterates through the input array. For each number in the array, it checks if the number is already in the set. If the number is in the set, it means there's a duplicate, so it returns true. If the number is not in the set, it adds the number to the set. If the function has not returned true after iterating through the entire array, it means that there are no duplicates, so it returns false.

In Python, we use the fact that sets don't allow duplicates, so we can directly compare the length of the original list with the length of the set created from the list. If they are not equal, it means there are duplicates in the list, and the function returns true. Otherwise, it returns false.


# The Skyline Problem

- slug: the-skyline-problem
- difficulty: Hard

A city's **skyline** is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Given the locations and heights of all the buildings, return _the **skyline** formed by these buildings collectively_.

The geometric information of each building is given in the array `buildings` where `buildings[i] = [lefti, righti, heighti]`:

*   `lefti` is the x coordinate of the left edge of the `ith` building.
*   `righti` is the x coordinate of the right edge of the `ith` building.
*   `heighti` is the height of the `ith` building.

You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height `0`.

The **skyline** should be represented as a list of "key points " **sorted by their x-coordinate** in the form `[[x1,y1],[x2,y2],...]`. Each key point is the left endpoint of some horizontal segment in the skyline except the last point in the list, which always has a y-coordinate `0` and is used to mark the skyline's termination where the rightmost building ends. Any ground between the leftmost and rightmost buildings should be part of the skyline's contour.

**Note:** There must be no consecutive horizontal lines of equal height in the output skyline. For instance, `[...,[2 3],[4 5],[7 5],[11 5],[12 7],...]` is not acceptable; the three lines of height 5 should be merged into one in the final output as such: `[...,[2 3],[4 5],[12 7],...]`

**Example 1:**

**Input:** buildings = \[\[2,9,10\],\[3,7,15\],\[5,12,12\],\[15,20,10\],\[19,24,8\]\]
**Output:** \[\[2,10\],\[3,15\],\[7,12\],\[12,0\],\[15,10\],\[20,8\],\[24,0\]\]
**Explanation:**
Figure A shows the buildings of the input.
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.

**Example 2:**

**Input:** buildings = \[\[0,2,3\],\[2,5,3\]\]
**Output:** \[\[0,3\],\[5,0\]\]

**Constraints:**

*   `1 <= buildings.length <= 104`
*   `0 <= lefti < righti <= 231 - 1`
*   `1 <= heighti <= 231 - 1`
*   `buildings` is sorted by `lefti` in non-decreasing order.

## A solution in Java

```java
import java.util.*;

class Solution {
    public List<List<Integer>> getSkyline(int[][] buildings) {
        List<int[]> points = new ArrayList<>();
        for (int[] b : buildings) {
            points.add(new int[]{b[0], -b[2]});
            points.add(new int[]{b[1], b[2]});
        }
        Collections.sort(points, (a, b) -> a[0] - b[0]);
        TreeSet<Integer> heights = new TreeSet<>(Collections.reverseOrder());
        heights.add(0);
        int prev = 0;
        List<List<Integer>> skyline = new ArrayList<>();
        for (int[] point : points) {
            int x = point[0], h = point[1];
            if (h < 0)
                heights.add(-h);
            else
                heights.remove(h);
            int cur = heights.first();
            if (cur != prev) {
                skyline.add(Arrays.asList(x, cur));
                prev = cur;
            }
        }
        return skyline;
    }
}
```
The algorithm starts by iterating through all the given buildings and creating a list of x-coordinates paired with the height of the buildings, where the left points are negated. We then sort the list of points by x-coordinate. Additionally, we also create a sorted multiset (C++)/TreeSet (Java)/SortedList (Python)/SortedSet (JavaScript) of building heights, initialized with a single 0 height.

Next, we iterate through the sorted points. If the height is negative, meaning it's a left point of a building, we add the absolute value of the height to the heights set. If the height is positive, meaning it's a right point of a building, we remove the height from the heights set.

At each iteration, we compare the current maximum height to the previous maximum height. If the current maximum height is different from the previous maximum height, it means we've reached a key point in the skyline, so we add this x-coordinate and the current maximum height to the skyline result list.

This algorithm ensures we receive a sorted list of key points in the skyline, without consecutive horizontal lines of equal height.

## A solution in C++

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

vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
    vector<pair<int, int>> points;
    for (const auto &b : buildings) {
        points.emplace_back(b[0], -b[2]);
        points.emplace_back(b[1], b[2]);
    }
    sort(points.begin(), points.end());
    multiset<int> heights = {0};
    int prev = 0;
    vector<vector<int>> skyline;
    for (const auto &[x, h] : points) {
        if (h < 0)
            heights.insert(-h);
        else
            heights.erase(heights.find(h));
        int cur = *heights.rbegin();
        if (cur != prev) {
            skyline.push_back({x, cur});
            prev = cur;
        }
    }
    return skyline;
}
```
The algorithm starts by iterating through all the given buildings and creating a list of x-coordinates paired with the height of the buildings, where the left points are negated. We then sort the list of points by x-coordinate. Additionally, we also create a sorted multiset (C++)/TreeSet (Java)/SortedList (Python)/SortedSet (JavaScript) of building heights, initialized with a single 0 height.

Next, we iterate through the sorted points. If the height is negative, meaning it's a left point of a building, we add the absolute value of the height to the heights set. If the height is positive, meaning it's a right point of a building, we remove the height from the heights set.

At each iteration, we compare the current maximum height to the previous maximum height. If the current maximum height is different from the previous maximum height, it means we've reached a key point in the skyline, so we add this x-coordinate and the current maximum height to the skyline result list.

This algorithm ensures we receive a sorted list of key points in the skyline, without consecutive horizontal lines of equal height.

## A solution in Python

```python
from sortedcontainers import SortedList

def getSkyline(buildings):
    points = []
    for l, r, h in buildings:
        points.append((l, -h))
        points.append((r, h))
    points.sort()
    heights = SortedList([0])
    prev = 0
    skyline = []
    for x, h in points:
        if h < 0:
            heights.add(-h)
        else:
            heights.remove(h)
        cur = heights[-1]
        if cur != prev:
            skyline.append([x, cur])
            prev = cur
    return skyline
```
The algorithm starts by iterating through all the given buildings and creating a list of x-coordinates paired with the height of the buildings, where the left points are negated. We then sort the list of points by x-coordinate. Additionally, we also create a sorted multiset (C++)/TreeSet (Java)/SortedList (Python)/SortedSet (JavaScript) of building heights, initialized with a single 0 height.

Next, we iterate through the sorted points. If the height is negative, meaning it's a left point of a building, we add the absolute value of the height to the heights set. If the height is positive, meaning it's a right point of a building, we remove the height from the heights set.

At each iteration, we compare the current maximum height to the previous maximum height. If the current maximum height is different from the previous maximum height, it means we've reached a key point in the skyline, so we add this x-coordinate and the current maximum height to the skyline result list.

This algorithm ensures we receive a sorted list of key points in the skyline, without consecutive horizontal lines of equal height.

## A solution in Javascript

```javascript
function getSkyline(buildings) {
    const points = [];
    for (const [l, r, h] of buildings) {
        points.push([l, -h]);
        points.push([r, h]);
    }
    points.sort((a, b) => a[0] - b[0]);
    const heights = new SortedSet([0]);
    let prev = 0;
    const skyline = [];
    for (const [x, h] of points) {
        if (h < 0) {
            heights.add(-h);
        } else {
            heights.delete(h);
        }
        const cur = heights.last();
        if (cur !== prev) {
            skyline.push([x, cur]);
            prev = cur;
        }
    }
    return skyline;
}
```
The algorithm starts by iterating through all the given buildings and creating a list of x-coordinates paired with the height of the buildings, where the left points are negated. We then sort the list of points by x-coordinate. Additionally, we also create a sorted multiset (C++)/TreeSet (Java)/SortedList (Python)/SortedSet (JavaScript) of building heights, initialized with a single 0 height.

Next, we iterate through the sorted points. If the height is negative, meaning it's a left point of a building, we add the absolute value of the height to the heights set. If the height is positive, meaning it's a right point of a building, we remove the height from the heights set.

At each iteration, we compare the current maximum height to the previous maximum height. If the current maximum height is different from the previous maximum height, it means we've reached a key point in the skyline, so we add this x-coordinate and the current maximum height to the skyline result list.

This algorithm ensures we receive a sorted list of key points in the skyline, without consecutive horizontal lines of equal height.


# Contains Duplicate II

- slug: contains-duplicate-ii
- difficulty: Easy

Given an integer array `nums` and an integer `k`, return `true` _if there are two **distinct indices**_ `i` _and_ `j` _in the array such that_ `nums[i] == nums[j]` _and_ `abs(i - j) <= k`.

**Example 1:**

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

**Example 2:**

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

**Example 3:**

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

**Constraints:**

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

## A solution in Java

```java
public boolean containsNearbyDuplicate(int[] nums, int k) {
    HashMap<Integer, Integer> valueIndexMap = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        if (valueIndexMap.containsKey(nums[i]) && i - valueIndexMap.get(nums[i]) <= k) {
            return true;
        }
        valueIndexMap.put(nums[i], i);
    }
    return false;
}
```
The algorithm utilizes a Hashtable, in which we store the integer value present in the array as the key and its latest index position as the value. For each element in the array, we first check if the current number is already in the Hashtable. If it is, we also check if the difference between the current index and the latest index stored in the Hashtable is less than or equal to k. If both conditions are met, we return `true` because there are two repeating integers having an index difference less than or equal to k. Otherwise, we add the number along with its latest index to the Hashtable and continue with the next element. If the loop finishes without finding such a pair, we return `false`.

Note: The algorithm's time complexity is O(n), where n is the length of the input array, and the space complexity is O(min(n, k)).

## A solution in C++

```cpp
bool containsNearbyDuplicate(vector<int>& nums, int k) {
    unordered_map<int, int> valueIndexMap;
    for (int i = 0; i < nums.size(); i++) {
        if (valueIndexMap.find(nums[i]) != valueIndexMap.end() && i - valueIndexMap[nums[i]] <= k) {
            return true;
        }
        valueIndexMap[nums[i]] = i;
    }
    return false;
}
```
The algorithm utilizes a Hashtable, in which we store the integer value present in the array as the key and its latest index position as the value. For each element in the array, we first check if the current number is already in the Hashtable. If it is, we also check if the difference between the current index and the latest index stored in the Hashtable is less than or equal to k. If both conditions are met, we return `true` because there are two repeating integers having an index difference less than or equal to k. Otherwise, we add the number along with its latest index to the Hashtable and continue with the next element. If the loop finishes without finding such a pair, we return `false`.

Note: The algorithm's time complexity is O(n), where n is the length of the input array, and the space complexity is O(min(n, k)).

## A solution in Python

```python
def containsNearbyDuplicate(nums, k):
    value_index_map = {}
    for i, num in enumerate(nums):
        if num in value_index_map and i - value_index_map[num] <= k:
            return True
        value_index_map[num] = i
    return False
```
The algorithm utilizes a Hashtable, in which we store the integer value present in the array as the key and its latest index position as the value. For each element in the array, we first check if the current number is already in the Hashtable. If it is, we also check if the difference between the current index and the latest index stored in the Hashtable is less than or equal to k. If both conditions are met, we return `true` because there are two repeating integers having an index difference less than or equal to k. Otherwise, we add the number along with its latest index to the Hashtable and continue with the next element. If the loop finishes without finding such a pair, we return `false`.

Note: The algorithm's time complexity is O(n), where n is the length of the input array, and the space complexity is O(min(n, k)).

## A solution in Javascript

```javascript
function containsNearbyDuplicate(nums, k) {
    const valueIndexMap = new Map();
    for (let i = 0; i < nums.length; i++) {
        if (valueIndexMap.has(nums[i]) && i - valueIndexMap.get(nums[i]) <= k) {
            return true;
        }
        valueIndexMap.set(nums[i], i);
    }
    return false;
}
```
The algorithm utilizes a Hashtable, in which we store the integer value present in the array as the key and its latest index position as the value. For each element in the array, we first check if the current number is already in the Hashtable. If it is, we also check if the difference between the current index and the latest index stored in the Hashtable is less than or equal to k. If both conditions are met, we return `true` because there are two repeating integers having an index difference less than or equal to k. Otherwise, we add the number along with its latest index to the Hashtable and continue with the next element. If the loop finishes without finding such a pair, we return `false`.

Note: The algorithm's time complexity is O(n), where n is the length of the input array, and the space complexity is O(min(n, k)).


# Contains Duplicate III

- slug: contains-duplicate-iii
- difficulty: Hard

You are given an integer array `nums` and two integers `indexDiff` and `valueDiff`.

Find a pair of indices `(i, j)` such that:

*   `i != j`,
*   `abs(i - j) <= indexDiff`.
*   `abs(nums[i] - nums[j]) <= valueDiff`, and

Return `true` _if such pair exists or_ `false` _otherwise_.

**Example 1:**

**Input:** nums = \[1,2,3,1\], indexDiff = 3, valueDiff = 0
**Output:** true
**Explanation:** We can choose (i, j) = (0, 3).
We satisfy the three conditions:
i != j --> 0 != 3
abs(i - j) <= indexDiff --> abs(0 - 3) <= 3
abs(nums\[i\] - nums\[j\]) <= valueDiff --> abs(1 - 1) <= 0

**Example 2:**

**Input:** nums = \[1,5,9,1,5,9\], indexDiff = 2, valueDiff = 3
**Output:** false
**Explanation:** After trying all the possible pairs (i, j), we cannot satisfy the three conditions, so we return false.

**Constraints:**

*   `2 <= nums.length <= 105`
*   `-109 <= nums[i] <= 109`
*   `1 <= indexDiff <= nums.length`
*   `0 <= valueDiff <= 109`

## A solution in Java

```java
import java.util.TreeSet;

public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
    TreeSet<Long> window = new TreeSet<>();
    for(int i = 0; i < nums.length; i++) {
        if(i > k) {
            window.remove((long)nums[i - k - 1]);
        }
        Long ceil = window.ceiling((long)nums[i] - t);
        if(ceil != null && ceil - nums[i] <= t) {
            return true;
        }
        window.add((long)nums[i]);
    }
    return false;
}
```
In this algorithm, we maintain a sliding window of size k + 1, and use a search tree (set or TreeSet depending on the language) to store the elements within the window. We use the search tree to efficiently search for elements in the window that meet the requirement of `abs(nums[i] - nums[j]) <= t`.

For each element in nums, we try to find a lower bound in the search tree that is close enough to the current element (within t). If there already exists an element that meets the condition, we return true.

We remove elements from the search tree that fall outside the window and add the current element to the search tree, maintaining the window size.

If we iterate through the whole array without finding a pair that meets the condition, we return false.

Note that in the Python implementation, "SortedList" from the "sortedcontainers" package is being used as it provides the needed functionality similar to C++ and Java. You might need to install the package via pip if not available.

## A solution in C++

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

bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    set<long> window;
    for (int i = 0; i < nums.size(); i++) {
        if (i > k) {
            window.erase(nums[i - k - 1]);
        }
        auto pos = window.lower_bound((long)nums[i] - t);
        if (pos != window.end() && *pos - nums[i] <= t) {
            return true;
        }
        window.insert(nums[i]);
    }
    return false;
}
```
In this algorithm, we maintain a sliding window of size k + 1, and use a search tree (set or TreeSet depending on the language) to store the elements within the window. We use the search tree to efficiently search for elements in the window that meet the requirement of `abs(nums[i] - nums[j]) <= t`.

For each element in nums, we try to find a lower bound in the search tree that is close enough to the current element (within t). If there already exists an element that meets the condition, we return true.

We remove elements from the search tree that fall outside the window and add the current element to the search tree, maintaining the window size.

If we iterate through the whole array without finding a pair that meets the condition, we return false.

Note that in the Python implementation, "SortedList" from the "sortedcontainers" package is being used as it provides the needed functionality similar to C++ and Java. You might need to install the package via pip if not available.

## A solution in Python

```python
from sortedcontainers import SortedList

def containsNearbyAlmostDuplicate(nums, k, t):
    window = SortedList()
    for i in range(len(nums)):
        if i > k:
            window.remove(nums[i - k - 1])
        pos = window.bisect_left(nums[i] - t)
        if pos != len(window) and window[pos] - nums[i] <= t:
            return True
        window.add(nums[i])
    return False
```
In this algorithm, we maintain a sliding window of size k + 1, and use a search tree (set or TreeSet depending on the language) to store the elements within the window. We use the search tree to efficiently search for elements in the window that meet the requirement of `abs(nums[i] - nums[j]) <= t`.

For each element in nums, we try to find a lower bound in the search tree that is close enough to the current element (within t). If there already exists an element that meets the condition, we return true.

We remove elements from the search tree that fall outside the window and add the current element to the search tree, maintaining the window size.

If we iterate through the whole array without finding a pair that meets the condition, we return false.

Note that in the Python implementation, "SortedList" from the "sortedcontainers" package is being used as it provides the needed functionality similar to C++ and Java. You might need to install the package via pip if not available.

## A solution in Javascript

```javascript
function containsNearbyAlmostDuplicate(nums, k, t) {
    let window = new Set();
    for (let i = 0; i < nums.length; i++) {
        if (i > k) {
            window.delete(nums[i - k - 1]);
        }
        for (const num of window) {
            if (Math.abs(num - nums[i]) <= t) {
                return true;
            }
        }
        window.add(nums[i]);
    }
    return false;
}
```
In this algorithm, we maintain a sliding window of size k + 1, and use a search tree (set or TreeSet depending on the language) to store the elements within the window. We use the search tree to efficiently search for elements in the window that meet the requirement of `abs(nums[i] - nums[j]) <= t`.

For each element in nums, we try to find a lower bound in the search tree that is close enough to the current element (within t). If there already exists an element that meets the condition, we return true.

We remove elements from the search tree that fall outside the window and add the current element to the search tree, maintaining the window size.

If we iterate through the whole array without finding a pair that meets the condition, we return false.

Note that in the Python implementation, "SortedList" from the "sortedcontainers" package is being used as it provides the needed functionality similar to C++ and Java. You might need to install the package via pip if not available.


# Maximal Square

- slug: maximal-square
- difficulty: Medium

Given an `m x n` binary `matrix` filled with `0`'s and `1`'s, _find the largest square containing only_ `1`'s _and return its area_.

**Example 1:**

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

**Example 2:**

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

**Example 3:**

**Input:** matrix = \[\[ "0 "\]\]
**Output:** 0

**Constraints:**

*   `m == matrix.length`
*   `n == matrix[i].length`
*   `1 <= m, n <= 300`
*   `matrix[i][j]` is `'0'` or `'1'`.

## A solution in Java

```java
public int maximalSquare(char[][] matrix) {
    int m = matrix.length;
    int n = matrix[0].length;
    int[][] dp = new int[m + 1][n + 1];
    int maxSize = 0;

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (matrix[i - 1][j - 1] == '1') {
                dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                maxSize = Math.max(maxSize, dp[i][j]);
            }
        }
    }

    return maxSize * maxSize;
}
```
The algorithm uses dynamic programming to find the largest square containing only 1's. It starts by creating a 2D table, `dp`, where `dp[i][j]` represents the size of the largest square ending at position (i, j) in the input matrix. The dimensions of `dp` are m+1 and n+1 to accommodate zero-indexing, and all elements are initialized to zero.

The algorithm iterates through each element in the input matrix. If the current element is 1, it sets the corresponding entry in `dp` to the minimum of the neighboring `dp` values (i.e., the values at top, left, and top-left) plus 1, which represents the size of the current square. The maxSize variable keeps track of the current largest square size, and at the end, the area of the largest square is returned by squaring maxSize.

## A solution in C++

```cpp
int maximalSquare(vector<vector<char>>& matrix) {
    int m = matrix.size();
    int n = matrix[0].size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    int maxSize = 0;

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (matrix[i - 1][j - 1] == '1') {
                dp[i][j] = min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;
                maxSize = max(maxSize, dp[i][j]);
            }
        }
    }

    return maxSize * maxSize;
}
```
The algorithm uses dynamic programming to find the largest square containing only 1's. It starts by creating a 2D table, `dp`, where `dp[i][j]` represents the size of the largest square ending at position (i, j) in the input matrix. The dimensions of `dp` are m+1 and n+1 to accommodate zero-indexing, and all elements are initialized to zero.

The algorithm iterates through each element in the input matrix. If the current element is 1, it sets the corresponding entry in `dp` to the minimum of the neighboring `dp` values (i.e., the values at top, left, and top-left) plus 1, which represents the size of the current square. The maxSize variable keeps track of the current largest square size, and at the end, the area of the largest square is returned by squaring maxSize.

## A solution in Python

```python
def maximalSquare(matrix):
    m, n = len(matrix), len(matrix[0])
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    maxSize = 0

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if matrix[i - 1][j - 1] == '1':
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1
                maxSize = max(maxSize, dp[i][j])

    return maxSize * maxSize
```
The algorithm uses dynamic programming to find the largest square containing only 1's. It starts by creating a 2D table, `dp`, where `dp[i][j]` represents the size of the largest square ending at position (i, j) in the input matrix. The dimensions of `dp` are m+1 and n+1 to accommodate zero-indexing, and all elements are initialized to zero.

The algorithm iterates through each element in the input matrix. If the current element is 1, it sets the corresponding entry in `dp` to the minimum of the neighboring `dp` values (i.e., the values at top, left, and top-left) plus 1, which represents the size of the current square. The maxSize variable keeps track of the current largest square size, and at the end, the area of the largest square is returned by squaring maxSize.

## A solution in Javascript

```javascript
function maximalSquare(matrix) {
    const m = matrix.length;
    const n = matrix[0].length;
    const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
    let maxSize = 0;

    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (matrix[i - 1][j - 1] === '1') {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
                maxSize = Math.max(maxSize, dp[i][j]);
            }
        }
    }

    return maxSize * maxSize;
}
```
The algorithm uses dynamic programming to find the largest square containing only 1's. It starts by creating a 2D table, `dp`, where `dp[i][j]` represents the size of the largest square ending at position (i, j) in the input matrix. The dimensions of `dp` are m+1 and n+1 to accommodate zero-indexing, and all elements are initialized to zero.

The algorithm iterates through each element in the input matrix. If the current element is 1, it sets the corresponding entry in `dp` to the minimum of the neighboring `dp` values (i.e., the values at top, left, and top-left) plus 1, which represents the size of the current square. The maxSize variable keeps track of the current largest square size, and at the end, the area of the largest square is returned by squaring maxSize.