# Design Circular Deque

- slug: design-circular-deque
- difficulty: Medium

Design your implementation of the circular double-ended queue (deque).

Implement the `MyCircularDeque` class:

*   `MyCircularDeque(int k)` Initializes the deque with a maximum size of `k`.
*   `boolean insertFront()` Adds an item at the front of Deque. Returns `true` if the operation is successful, or `false` otherwise.
*   `boolean insertLast()` Adds an item at the rear of Deque. Returns `true` if the operation is successful, or `false` otherwise.
*   `boolean deleteFront()` Deletes an item from the front of Deque. Returns `true` if the operation is successful, or `false` otherwise.
*   `boolean deleteLast()` Deletes an item from the rear of Deque. Returns `true` if the operation is successful, or `false` otherwise.
*   `int getFront()` Returns the front item from the Deque. Returns `-1` if the deque is empty.
*   `int getRear()` Returns the last item from Deque. Returns `-1` if the deque is empty.
*   `boolean isEmpty()` Returns `true` if the deque is empty, or `false` otherwise.
*   `boolean isFull()` Returns `true` if the deque is full, or `false` otherwise.

**Example 1:**

**Input**
\[ "MyCircularDeque ",  "insertLast ",  "insertLast ",  "insertFront ",  "insertFront ",  "getRear ",  "isFull ",  "deleteLast ",  "insertFront ",  "getFront "\]
\[\[3\], \[1\], \[2\], \[3\], \[4\], \[\], \[\], \[\], \[4\], \[\]\]
**Output**
\[null, true, true, true, false, 2, true, true, true, 4\]

**Explanation**
MyCircularDeque myCircularDeque = new MyCircularDeque(3);
myCircularDeque.insertLast(1);  // return True
myCircularDeque.insertLast(2);  // return True
myCircularDeque.insertFront(3); // return True
myCircularDeque.insertFront(4); // return False, the queue is full.
myCircularDeque.getRear();      // return 2
myCircularDeque.isFull();       // return True
myCircularDeque.deleteLast();   // return True
myCircularDeque.insertFront(4); // return True
myCircularDeque.getFront();     // return 4

**Constraints:**

*   `1 <= k <= 1000`
*   `0 <= value <= 1000`
*   At most `2000` calls will be made to `insertFront`, `insertLast`, `deleteFront`, `deleteLast`, `getFront`, `getRear`, `isEmpty`, `isFull`.

## A solution in Java

```java
class MyCircularDeque {
    private int[] buffer;
    private int front, rear, capacity;

    public MyCircularDeque(int k) {
        buffer = new int[k];
        front = -1;
        rear = 0;
        capacity = k;
    }

    public boolean insertFront(int value) {
        if (isFull()) {
            return false;
        }
        if (front == -1) {
            front = 0;
        } else {
            front = (front - 1 + capacity) % capacity;
        }
        buffer[front] = value;
        return true;
    }

    public boolean insertLast(int value) {
        if (isFull()) {
            return false;
        }
        buffer[rear] = value;
        rear = (rear + 1) % capacity;
        if (front == -1) {
            front = 0;
        }
        return true;
    }

    public boolean deleteFront() {
        if (isEmpty()) {
            return false;
        }
        if (front == rear - 1) {
            front = -1;
        } else {
            front = (front + 1) % capacity;
        }
        return true;
    }

    public boolean deleteLast() {
        if (isEmpty()) {
            return false;
        }
        if (front == rear - 1) {
            rear = 0;
            front = -1;
        } else {
            rear = (rear - 1 + capacity) % capacity;
        }
        return true;
    }

    public int getFront() {
        if (isEmpty()) {
            return -1;
        }
        return buffer[front];
    }

    public int getRear() {
        if (isEmpty()) {
            return -1;
        }
        return buffer[(rear - 1 + capacity) % capacity];
    }

    public boolean isEmpty() {
        return front == -1;
    }

    public boolean isFull() {
        return front == rear;
    }
}
```
The algorithm uses a circular buffer which is an array that is treated as a ring of fixed size. The start and the end of the buffer are connected to form a circle. To implement the circular deque, we will have a front and rear pointer, and capacity to store the maximum size. The front and rear pointers are initialized appropriately in the constructor. The insertFront, insertLast, deleteFront, deleteLast, getFront, getRear methods manipulate the pointers while keeping in mind that they need to wrap around the buffer. The isEmpty and isFull methods are used for checking if the deque is empty or full before performing other operations. The front, rear, and capacity indices are used modulo the deque size to wrap around the buffer.

## A solution in C++

```cpp
class MyCircularDeque {
    vector<int> buffer;
    int front, rear, capacity;
public:
    MyCircularDeque(int k) {
        buffer.resize(k);
        front = -1;
        rear = 0;
        capacity = k;
    }

    bool insertFront(int value) {
        if (isFull()) {
            return false;
        }
        if (front == -1) {
            front = 0;
        } else {
            front = (front - 1 + capacity) % capacity;
        }
        buffer[front] = value;
        return true;
    }

    bool insertLast(int value) {
        if (isFull()) {
            return false;
        }
        buffer[rear] = value;
        rear = (rear + 1) % capacity;
        if (front == -1) {
            front = 0;
        }
        return true;
    }

    bool deleteFront() {
        if (isEmpty()) {
            return false;
        }
        if (front == rear - 1) {
            front = -1;
        } else {
            front = (front + 1) % capacity;
        }
        return true;
    }

    bool deleteLast() {
        if (isEmpty()) {
            return false;
        }
        if (front == rear - 1) {
            rear = 0;
            front = -1;
        } else {
            rear = (rear - 1 + capacity) % capacity;
        }
        return true;
    }

    int getFront() {
        if (isEmpty()) {
            return -1;
        }
        return buffer[front];
    }

    int getRear() {
        if (isEmpty()) {
            return -1;
        }
        return buffer[(rear - 1 + capacity) % capacity];
    }

    bool isEmpty() {
        return front == -1;
    }

    bool isFull() {
        return front == rear;
    }
};
```
The algorithm uses a circular buffer which is an array that is treated as a ring of fixed size. The start and the end of the buffer are connected to form a circle. To implement the circular deque, we will have a front and rear pointer, and capacity to store the maximum size. The front and rear pointers are initialized appropriately in the constructor. The insertFront, insertLast, deleteFront, deleteLast, getFront, getRear methods manipulate the pointers while keeping in mind that they need to wrap around the buffer. The isEmpty and isFull methods are used for checking if the deque is empty or full before performing other operations. The front, rear, and capacity indices are used modulo the deque size to wrap around the buffer.

## A solution in Python

```python
class MyCircularDeque:

    def __init__(self, k: int):
        self.buffer = [0] * k
        self.front = -1
        self.rear = 0
        self.capacity = k

    def insertFront(self, value: int) -> bool:
        if self.isFull():
            return False
        if self.front == -1:
            self.front = 0
        else:
            self.front = (self.front - 1 + self.capacity) % self.capacity
        self.buffer[self.front] = value
        return True

    def insertLast(self, value: int) -> bool:
        if self.isFull():
            return False
        self.buffer[self.rear] = value
        self.rear = (self.rear + 1) % self.capacity
        if self.front == -1:
            self.front = 0
        return True

    def deleteFront(self) -> bool:
        if self.isEmpty():
            return False
        if self.front == self.rear - 1:
            self.front = -1
        else:
            self.front = (self.front + 1) % self.capacity
        return True

    def deleteLast(self) -> bool:
        if self.isEmpty():
            return False
        if self.front == self.rear - 1:
            self.rear = 0
            self.front = -1
        else:
            self.rear = (self.rear - 1 + self.capacity) % self.capacity
        return True

    def getFront(self) -> int:
        if self.isEmpty():
            return -1
        return self.buffer[self.front]

    def getRear(self) -> int:
        if self.isEmpty():
            return -1
        return self.buffer[(self.rear - 1 + self.capacity) % self.capacity]

    def isEmpty(self) -> bool:
        return self.front == -1

    def isFull(self) -> bool:
        return self.front == self.rear
```
The algorithm uses a circular buffer which is an array that is treated as a ring of fixed size. The start and the end of the buffer are connected to form a circle. To implement the circular deque, we will have a front and rear pointer, and capacity to store the maximum size. The front and rear pointers are initialized appropriately in the constructor. The insertFront, insertLast, deleteFront, deleteLast, getFront, getRear methods manipulate the pointers while keeping in mind that they need to wrap around the buffer. The isEmpty and isFull methods are used for checking if the deque is empty or full before performing other operations. The front, rear, and capacity indices are used modulo the deque size to wrap around the buffer.

## A solution in Javascript

```javascript
class MyCircularDeque {
    constructor(k) {
        this.buffer = new Array(k);
        this.front = -1;
        this.rear = 0;
        this.capacity = k;
    }

    insertFront(value) {
        if (this.isFull()) {
            return false;
        }
        if (this.front === -1) {
            this.front = 0;
        } else {
            this.front = (this.front - 1 + this.capacity) % this.capacity;
        }
        this.buffer[this.front] = value;
        return true;
    }

    insertLast(value) {
        if (this.isFull()) {
            return false;
        }
        this.buffer[this.rear] = value;
        this.rear = (this.rear + 1) % this.capacity;
        if (this.front === -1) {
            this.front = 0;
        }
        return true;
    }

    deleteFront() {
        if (this.isEmpty()) {
            return false;
        }
        if (this.front === this.rear - 1) {
            this.front = -1;
        } else {
            this.front = (this.front + 1) % this.capacity;
        }
        return true;
    }

    deleteLast() {
        if (this.isEmpty()) {
            return false;
        }
        if (this.front === this.rear - 1) {
            this.rear = 0;
            this.front = -1;
        } else {
            this.rear = (this.rear - 1 + this.capacity) % this.capacity;
        }
        return true;
    }

    getFront() {
        if (this.isEmpty()) {
            return -1;
        }
        return this.buffer[this.front];
    }

    getRear() {
        if (this.isEmpty()) {
            return -1;
        }
        return this.buffer[(this.rear - 1 + this.capacity) % this.capacity];
    }

    isEmpty() {
        return this.front === -1;
    }

    isFull() {
        return this.front === this.rear;
    }
}
```
The algorithm uses a circular buffer which is an array that is treated as a ring of fixed size. The start and the end of the buffer are connected to form a circle. To implement the circular deque, we will have a front and rear pointer, and capacity to store the maximum size. The front and rear pointers are initialized appropriately in the constructor. The insertFront, insertLast, deleteFront, deleteLast, getFront, getRear methods manipulate the pointers while keeping in mind that they need to wrap around the buffer. The isEmpty and isFull methods are used for checking if the deque is empty or full before performing other operations. The front, rear, and capacity indices are used modulo the deque size to wrap around the buffer.


# Design Search Autocomplete System

- slug: design-search-autocomplete-system
- difficulty: Hard

Design a search autocomplete system for a search engine. Users may input a sentence (at least one word and end with a special character `'#'`).

You are given a string array `sentences` and an integer array `times` both of length `n` where `sentences[i]` is a previously typed sentence and `times[i]` is the corresponding number of times the sentence was typed. For each input character except `'#'`, return the top `3` historical hot sentences that have the same prefix as the part of the sentence already typed.

Here are the specific rules:

*   The hot degree for a sentence is defined as the number of times a user typed the exactly same sentence before.
*   The returned top `3` hot sentences should be sorted by hot degree (The first is the hottest one). If several sentences have the same hot degree, use ASCII-code order (smaller one appears first).
*   If less than `3` hot sentences exist, return as many as you can.
*   When the input is a special character, it means the sentence ends, and in this case, you need to return an empty list.

Implement the `AutocompleteSystem` class:

*   `AutocompleteSystem(String[] sentences, int[] times)` Initializes the object with the `sentences` and `times` arrays.
*   `List input(char c)` This indicates that the user typed the character `c`.
    *   Returns an empty array `[]` if `c == '#'` and stores the inputted sentence in the system.
    *   Returns the top `3` historical hot sentences that have the same prefix as the part of the sentence already typed. If there are fewer than `3` matches, return them all.

**Example 1:**

**Input**
\[ "AutocompleteSystem ",  "input ",  "input ",  "input ",  "input "\]
\[\[\[ "i love you ",  "island ",  "iroman ",  "i love leetcode "\], \[5, 3, 2, 2\]\], \[ "i "\], \[ "  "\], \[ "a "\], \[ "# "\]\]
**Output**
\[null, \[ "i love you ",  "island ",  "i love leetcode "\], \[ "i love you ",  "i love leetcode "\], \[\], \[\]\]

**Explanation**
AutocompleteSystem obj = new AutocompleteSystem(\[ "i love you ",  "island ",  "iroman ",  "i love leetcode "\], \[5, 3, 2, 2\]);
obj.input( "i "); // return \[ "i love you ",  "island ",  "i love leetcode "\]. There are four sentences that have prefix  "i ". Among them,  "ironman " and  "i love leetcode " have same hot degree. Since ' ' has ASCII code 32 and 'r' has ASCII code 114,  "i love leetcode " should be in front of  "ironman ". Also we only need to output top 3 hot sentences, so  "ironman " will be ignored.
obj.input( "  "); // return \[ "i love you ",  "i love leetcode "\]. There are only two sentences that have prefix  "i  ".
obj.input( "a "); // return \[\]. There are no sentences that have prefix  "i a ".
obj.input( "# "); // return \[\]. The user finished the input, the sentence  "i a " should be saved as a historical sentence in system. And the following input will be counted as a new search.

**Constraints:**

*   `n == sentences.length`
*   `n == times.length`
*   `1 <= n <= 100`
*   `1 <= sentences[i].length <= 100`
*   `1 <= times[i] <= 50`
*   `c` is a lowercase English letter, a hash `'#'`, or space `' '`.
*   Each tested sentence will be a sequence of characters `c` that end with the character `'#'`.
*   Each tested sentence will have a length in the range `[1, 200]`.
*   The words in each input sentence are separated by single spaces.
*   At most `5000` calls will be made to `input`.

## A solution in Java

```java
import java.util.*;

class AutocompleteSystem {
    class TrieNode {
        HashMap<Character, TrieNode> children = new HashMap<>();
        String sentence;
        int times;

        TrieNode() {
            sentence = null;
            times = 0;
        }
    }

    private void insert(String sentence, int times) {
        TrieNode curr = root;
        for (char c : sentence.toCharArray()) {
            curr.children.putIfAbsent(c, new TrieNode());
            curr = curr.children.get(c);
        }
        curr.sentence = sentence;
        curr.times += times;
    }

    private class NodeComparator implements Comparator<TrieNode> {
        public int compare(TrieNode a, TrieNode b) {
            if (a.times == b.times) {
                return a.sentence.compareTo(b.sentence);
            }
            return b.times - a.times;
        }
    }

    TrieNode root, curr;
    String search;

    public AutocompleteSystem(String[] sentences, int[] times) {
        root = new TrieNode();
        curr = root;
        search = "";
        for (int i = 0; i < sentences.length; ++i) {
            insert(sentences[i], times[i]);
        }
    }

    public List<String> input(char c) {
        List<String> res = new ArrayList<>();
        if (c == '#') {
            insert(search, 1);
            search = "";
            curr = root;
            return res;
        }
        search += c;
        if (!curr.children.containsKey(c)) {
            curr = null;
            return res;
        }
        curr = curr.children.get(c);
        PriorityQueue<TrieNode> pq = new PriorityQueue<>(new NodeComparator());
        for (TrieNode node : curr.children.values()) {
            if (node.times > 0) {
                pq.add(node);
            }
        }
        while (!pq.isEmpty() && res.size() < 3) {
            res.add(pq.poll().sentence);
        }
        return res;
    }
}
```
The algorithm implemented is a trie-based solution. The `AutocompleteSystem` class has a TrieNode structure and methods to insert sentences into the trie, as well as to find and return the top 3 historical hot sentences.

The TrieNode structure has a `children` dictionary that stores the characters and their child TrieNode references, a sentence attribute to store the sentence corresponding to the node (if it is the end of a sentence), and a times attribute to store the hot degree of the sentence.

The `insert` method takes a sentence and times as input and inserts the sentence into the trie structure by following the appropriate path based on each character.

The `input` method processes each character in the user input to search for matching historical hot sentences. If the user input is a special character '#' it stores the inputted sentence in the system and returns an empty list. When the user input is not a special character, the `input` method finds matching historical hot sentences by traversing the trie based on the characters of the user input. A priority queue (or sorting for JavaScript) is used to prioritize and return the top 3 hot historical sentences according to their hot degree and ASCII-code order.

## A solution in C++

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

class AutocompleteSystem {
    struct TrieNode {
        std::unordered_map<char, TrieNode*> children;
        std::string sentence;
        int times;
        TrieNode() : times(0) {}
    };

    void insert(const std::string &sentence, int times) {
        TrieNode *curr = root;
        for (char c : sentence) {
            if (!curr->children[c]) {
                curr->children[c] = new TrieNode();
            }
            curr = curr->children[c];
        }
        curr->times += times;
        curr->sentence = sentence;
    }

    struct cmp {
        bool operator()(const TrieNode* a, const TrieNode* b) const {
            if (a->times == b->times) {
                return a->sentence > b->sentence;
            }
            return a->times < b->times;
        }
    };

    TrieNode *root;
    TrieNode *current;
    std::string search;

public:
    AutocompleteSystem(std::vector<std::string>& sentences, std::vector<int>& times) {
        root = new TrieNode();
        for (int i = 0; i < sentences.size(); ++i) {
            insert(sentences[i], times[i]);
        }
        current = root;
    }

    std::vector<std::string> input(char c) {
        if (c == '#') {
            insert(search, 1);
            search = "";
            current = root;
            return {};
        }
        search += c;
        if (!current) {
            return {};
        }
        current = current->children[c];
        if (!current) {
            return {};
        }
        std::priority_queue<TrieNode*, std::vector<TrieNode*>, cmp> pq;
        for (auto &[char_, node] : current->children) {
            if (node->times) {
                pq.push(node);
            }
        }

        std::vector<std::string> res;
        while (!pq.empty() && res.size() < 3) {
            res.push_back(pq.top()->sentence);
            pq.pop();
        }
        return res;
    }
};
```
The algorithm implemented is a trie-based solution. The `AutocompleteSystem` class has a TrieNode structure and methods to insert sentences into the trie, as well as to find and return the top 3 historical hot sentences.

The TrieNode structure has a `children` dictionary that stores the characters and their child TrieNode references, a sentence attribute to store the sentence corresponding to the node (if it is the end of a sentence), and a times attribute to store the hot degree of the sentence.

The `insert` method takes a sentence and times as input and inserts the sentence into the trie structure by following the appropriate path based on each character.

The `input` method processes each character in the user input to search for matching historical hot sentences. If the user input is a special character '#' it stores the inputted sentence in the system and returns an empty list. When the user input is not a special character, the `input` method finds matching historical hot sentences by traversing the trie based on the characters of the user input. A priority queue (or sorting for JavaScript) is used to prioritize and return the top 3 hot historical sentences according to their hot degree and ASCII-code order.

## A solution in Python

```python
from typing import List
import heapq

class TrieNode:
    def __init__(self):
        self.children = {}
        self.sentence = ""
        self.times = 0

class AutocompleteSystem:

    def __init__(self, sentences: List[str], times: List[int]):
        self.root = TrieNode()
        self.current = self.root
        self.search = ""

        for i in range(len(sentences)):
            self.insert(sentences[i], times[i])

    def insert(self, sentence: str, times: int):
        curr = self.root
        for c in sentence:
            if c not in curr.children:
                curr.children[c] = TrieNode()
            curr = curr.children[c]
        curr.sentence = sentence
        curr.times += times

    def input(self, c: str) -> List[str]:
        if c == '#':
            self.insert(self.search, 1)
            self.search = ""
            self.current = self.root
            return []

        self.search += c
        if not self.current:
            return []

        if c not in self.current.children:
            self.current = None
            return []

        self.current = self.current.children[c]
        heap = []
        for child in self.current.children.values():
            if child.times:
                heapq.heappush(heap, (-child.times, child.sentence))

        res = []
        for _ in range(3):
            if not heap:
                break
            res.append(heapq.heappop(heap)[1])
        return res
```
The algorithm implemented is a trie-based solution. The `AutocompleteSystem` class has a TrieNode structure and methods to insert sentences into the trie, as well as to find and return the top 3 historical hot sentences.

The TrieNode structure has a `children` dictionary that stores the characters and their child TrieNode references, a sentence attribute to store the sentence corresponding to the node (if it is the end of a sentence), and a times attribute to store the hot degree of the sentence.

The `insert` method takes a sentence and times as input and inserts the sentence into the trie structure by following the appropriate path based on each character.

The `input` method processes each character in the user input to search for matching historical hot sentences. If the user input is a special character '#' it stores the inputted sentence in the system and returns an empty list. When the user input is not a special character, the `input` method finds matching historical hot sentences by traversing the trie based on the characters of the user input. A priority queue (or sorting for JavaScript) is used to prioritize and return the top 3 hot historical sentences according to their hot degree and ASCII-code order.

## A solution in Javascript

```javascript
class TrieNode {
    constructor() {
        this.children = {};
        this.sentence = "";
        this.times = 0;
    }
}

class AutocompleteSystem {
    constructor(sentences, times) {
        this.root = new TrieNode();
        this.current = this.root;
        this.search = "";

        for (let i = 0; i < sentences.length; ++i) {
            this.insert(sentences[i], times[i]);
        }
    }

    insert(sentence, times) {
        let curr = this.root;
        for (let c of sentence) {
            if (!curr.children[c]) {
                curr.children[c] = new TrieNode();
            }
            curr = curr.children[c];
        }
        curr.sentence = sentence;
        curr.times += times;
    }

    input(c) {
        if (c === '#') {
            this.insert(this.search, 1);
            this.search = "";
            this.current = this.root;
            return [];
        }

        this.search += c;
        if (!this.current) {
            return [];
        }

        if (!this.current.children[c]) {
            this.current = null;
            return [];
        }

        this.current = this.current.children[c];
        const heap = [];
        for (let node of Object.values(this.current.children)) {
            if (node.times) {
                heap.push([node]);
            }
        }

        heap.sort((a, b) => {
            if (a.times === b.times) {
                return a.sentence.localeCompare(b.sentence);
            }
            return b.times - a.times;
        });

        const res = [];
        for (let i = 0; i < 3 && i < heap.length; ++i) {
            res.push(heap[i].sentence);
        }
        return res;
    }
}
```
The algorithm implemented is a trie-based solution. The `AutocompleteSystem` class has a TrieNode structure and methods to insert sentences into the trie, as well as to find and return the top 3 historical hot sentences.

The TrieNode structure has a `children` dictionary that stores the characters and their child TrieNode references, a sentence attribute to store the sentence corresponding to the node (if it is the end of a sentence), and a times attribute to store the hot degree of the sentence.

The `insert` method takes a sentence and times as input and inserts the sentence into the trie structure by following the appropriate path based on each character.

The `input` method processes each character in the user input to search for matching historical hot sentences. If the user input is a special character '#' it stores the inputted sentence in the system and returns an empty list. When the user input is not a special character, the `input` method finds matching historical hot sentences by traversing the trie based on the characters of the user input. A priority queue (or sorting for JavaScript) is used to prioritize and return the top 3 hot historical sentences according to their hot degree and ASCII-code order.


# Maximum Average Subarray I

- slug: maximum-average-subarray-i
- difficulty: Easy

You are given an integer array `nums` consisting of `n` elements, and an integer `k`.

Find a contiguous subarray whose **length is equal to** `k` that has the maximum average value and return _this value_. Any answer with a calculation error less than `10-5` will be accepted.

**Example 1:**

**Input:** nums = \[1,12,-5,-6,50,3\], k = 4
**Output:** 12.75000
**Explanation:** Maximum average is (12 - 5 - 6 + 50) / 4 = 51 / 4 = 12.75

**Example 2:**

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

**Constraints:**

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

## A solution in Java

```java
public double findMaxAverage(int[] nums, int k) {
    int n = nums.length;
    double sum = 0;
    for (int i = 0; i < k; i++) {
        sum += nums[i];
    }
    double max_avg = sum / k;
    for (int i = k; i < n; i++) {
        sum = sum - nums[i - k] + nums[i];
        max_avg = Math.max(max_avg, sum / k);
    }
    return max_avg;
}
```
1. Initialize the sum with the first `k` elements of the input array.
2. Calculate the average by dividing the sum by `k` and store it in `max_avg`.
3. Loop through the input array from index `k` to the end.
4. For each element, update the sum by subtracting the element at the left side of the sliding window (with `k` length) and adding the current element.
5. Calculate the average again and update the `max_avg` if the current average is higher than the previous `max_avg`.
6. Return `max_avg` after the loop ends.

## A solution in C++

```cpp
double findMaxAverage(vector<int>& nums, int k) {
    int n = nums.size();
    double sum = 0;
    for (int i = 0; i < k; ++i) {
        sum += nums[i];
    }
    double max_avg = sum / k;
    for (int i = k; i < n; ++i) {
        sum = sum - nums[i - k] + nums[i];
        max_avg = max(max_avg, sum / k);
    }
    return max_avg;
}
```
1. Initialize the sum with the first `k` elements of the input array.
2. Calculate the average by dividing the sum by `k` and store it in `max_avg`.
3. Loop through the input array from index `k` to the end.
4. For each element, update the sum by subtracting the element at the left side of the sliding window (with `k` length) and adding the current element.
5. Calculate the average again and update the `max_avg` if the current average is higher than the previous `max_avg`.
6. Return `max_avg` after the loop ends.

## A solution in Python

```python
def findMaxAverage(nums, k):
    n = len(nums)
    sum_ = sum(nums[:k])
    max_avg = sum_ / k
    for i in range(k, n):
        sum_ = sum_ - nums[i - k] + nums[i]
        max_avg = max(max_avg, sum_ / k)
    return max_avg
```
1. Initialize the sum with the first `k` elements of the input array.
2. Calculate the average by dividing the sum by `k` and store it in `max_avg`.
3. Loop through the input array from index `k` to the end.
4. For each element, update the sum by subtracting the element at the left side of the sliding window (with `k` length) and adding the current element.
5. Calculate the average again and update the `max_avg` if the current average is higher than the previous `max_avg`.
6. Return `max_avg` after the loop ends.

## A solution in Javascript

```javascript
function findMaxAverage(nums, k) {
    let n = nums.length;
    let sum = 0;
    for (let i = 0; i < k; i++) {
        sum += nums[i];
    }
    let max_avg = sum / k;
    for (let i = k; i < n; i++) {
        sum = sum - nums[i - k] + nums[i];
        max_avg = Math.max(max_avg, sum / k);
    }
    return max_avg;
}
```
1. Initialize the sum with the first `k` elements of the input array.
2. Calculate the average by dividing the sum by `k` and store it in `max_avg`.
3. Loop through the input array from index `k` to the end.
4. For each element, update the sum by subtracting the element at the left side of the sliding window (with `k` length) and adding the current element.
5. Calculate the average again and update the `max_avg` if the current average is higher than the previous `max_avg`.
6. Return `max_avg` after the loop ends.


# Maximum Average Subarray II

- slug: maximum-average-subarray-ii
- difficulty: Hard

You are given an integer array `nums` consisting of `n` elements, and an integer `k`.

Find a contiguous subarray whose **length is greater than or equal to** `k` that has the maximum average value and return _this value_. Any answer with a calculation error less than `10-5` will be accepted.

**Example 1:**

**Input:** nums = \[1,12,-5,-6,50,3\], k = 4
**Output:** 12.75000
**Explanation:**
\- When the length is 4, averages are \[0.5, 12.75, 10.5\] and the maximum average is 12.75
- When the length is 5, averages are \[10.4, 10.8\] and the maximum average is 10.8
- When the length is 6, averages are \[9.16667\] and the maximum average is 9.16667
The maximum average is when we choose a subarray of length 4 (i.e., the sub array \[12, -5, -6, 50\]) which has the max average 12.75, so we return 12.75
Note that we do not consider the subarrays of length < 4.

**Example 2:**

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

**Constraints:**

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

## A solution in Java

```java
public double findMaxAverage(int[] nums, int k) {
    long sum = 0;
    for(int i = 0; i < k; i++) {
        sum += nums[i];
    }

    double max_avg = (double) sum / k;

    for(int i = k; i < nums.length; i++) {
        sum += nums[i] - nums[i - k];
        max_avg = Math.max(max_avg, (double) sum / k);
    }

    return max_avg;
}
```
The algorithm calculates the initial total of the first `k` elements, and the initial average is the total divided by `k`. Then, it iterates through the rest of the array (from the `k`-th index to the end), updating the total by removing the (i-k)-th element and adding the i-th element. At each step, it compares the new average (total/k) with the previous maximum average and updates accordingly. Finally, it returns the maximum average found.

## A solution in C++

```cpp
double findMaxAverage(vector<int>& nums, int k) {
    long sum = 0;
    int n = nums.size();
    for(int i = 0; i < k; i++) {
        sum += nums[i];
    }

    double max_avg = static_cast<double>(sum) / k;

    for(int i = k; i < n; i++) {
        sum += nums[i] - nums[i - k];
        max_avg = max(max_avg, static_cast<double>(sum) / k);
    }

    return max_avg;
}
```
The algorithm calculates the initial total of the first `k` elements, and the initial average is the total divided by `k`. Then, it iterates through the rest of the array (from the `k`-th index to the end), updating the total by removing the (i-k)-th element and adding the i-th element. At each step, it compares the new average (total/k) with the previous maximum average and updates accordingly. Finally, it returns the maximum average found.

## A solution in Python

```python
def findMaxAverage(nums, k):
    total = sum(nums[:k])
    max_avg = total / k
    for i in range(k, len(nums)):
        total += nums[i] - nums[i - k]
        max_avg = max(max_avg, total / k)
    return max_avg
```
The algorithm calculates the initial total of the first `k` elements, and the initial average is the total divided by `k`. Then, it iterates through the rest of the array (from the `k`-th index to the end), updating the total by removing the (i-k)-th element and adding the i-th element. At each step, it compares the new average (total/k) with the previous maximum average and updates accordingly. Finally, it returns the maximum average found.

## A solution in Javascript

```javascript
function findMaxAverage(nums, k) {
    let sum = 0;
    for(let i = 0; i < k; i++) {
        sum += nums[i];
    }

    let max_avg = sum / k;

    for(let i = k; i < nums.length; i++) {
        sum += nums[i] - nums[i - k];
        max_avg = Math.max(max_avg, sum / k);
    }

    return max_avg;
}
```
The algorithm calculates the initial total of the first `k` elements, and the initial average is the total divided by `k`. Then, it iterates through the rest of the array (from the `k`-th index to the end), updating the total by removing the (i-k)-th element and adding the i-th element. At each step, it compares the new average (total/k) with the previous maximum average and updates accordingly. Finally, it returns the maximum average found.


# Set Mismatch

- slug: set-mismatch
- difficulty: Easy

You have a set of integers `s`, which originally contains all the numbers from `1` to `n`. Unfortunately, due to some error, one of the numbers in `s` got duplicated to another number in the set, which results in **repetition of one** number and **loss of another** number.

You are given an integer array `nums` representing the data status of this set after the error.

Find the number that occurs twice and the number that is missing and return _them in the form of an array_.

**Example 1:**

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

**Example 2:**

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

**Constraints:**

*   `2 <= nums.length <= 104`
*   `1 <= nums[i] <= 104`

## A solution in Java

```java
public int[] findErrorNums(int[] nums) {
    int[] result = new int[2];
    for (int num : nums) {
        int index = Math.abs(num) - 1;
        if (nums[index] > 0) {
            nums[index] = -nums[index];
        } else {
            result[0] = index + 1;
        }
    }
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > 0) {
            result[1] = i + 1;
            break;
        }
    }
    return result;
}
```
1. Iterate through the given array, creating and using the index as the absolute value of the current number minus one. By doing this, we visit the indices in a specific order that allows us to mark numbers we have already visited.
2. If the value at the index is positive, we negate it. If it's negative, it means we found the duplicate number. Store the duplicate number (index + 1) in the result array.
3. Iterate through the array again to find the first positive value. This index plus one will be the missing number, as others should have been negated in the previous steps.
4. Add the missing number to the result array and return it.

## A solution in C++

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

vector<int> findErrorNums(vector<int>& nums) {
    vector<int> result;
    for (int i = 0; i < nums.size(); i++) {
        int index = abs(nums[i]) - 1;
        if (nums[index] > 0) {
            nums[index] = -nums[index];
        } else {
            result.push_back(index + 1);
        }
    }
    for (int i = 0; i < nums.size(); i++) {
        if (nums[i] > 0) {
            result.push_back(i + 1);
            break;
        }
    }
    return result;
}
```
1. Iterate through the given array, creating and using the index as the absolute value of the current number minus one. By doing this, we visit the indices in a specific order that allows us to mark numbers we have already visited.
2. If the value at the index is positive, we negate it. If it's negative, it means we found the duplicate number. Store the duplicate number (index + 1) in the result array.
3. Iterate through the array again to find the first positive value. This index plus one will be the missing number, as others should have been negated in the previous steps.
4. Add the missing number to the result array and return it.

## A solution in Python

```python
def findErrorNums(nums):
    result = []
    for num in nums:
        index = abs(num) - 1
        if nums[index] > 0:
            nums[index] = -nums[index]
        else:
            result.append(index + 1)
    for i, num in enumerate(nums):
        if num > 0:
            result.append(i + 1)
            break
    return result
```
1. Iterate through the given array, creating and using the index as the absolute value of the current number minus one. By doing this, we visit the indices in a specific order that allows us to mark numbers we have already visited.
2. If the value at the index is positive, we negate it. If it's negative, it means we found the duplicate number. Store the duplicate number (index + 1) in the result array.
3. Iterate through the array again to find the first positive value. This index plus one will be the missing number, as others should have been negated in the previous steps.
4. Add the missing number to the result array and return it.

## A solution in Javascript

```javascript
function findErrorNums(nums) {
    let result = [];
    for (let num of nums) {
        let index = Math.abs(num) - 1;
        if (nums[index] > 0) {
            nums[index] = -nums[index];
        } else {
            result.push(index + 1);
        }
    }
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] > 0) {
            result.push(i + 1);
            break;
        }
    }
    return result;
}
```
1. Iterate through the given array, creating and using the index as the absolute value of the current number minus one. By doing this, we visit the indices in a specific order that allows us to mark numbers we have already visited.
2. If the value at the index is positive, we negate it. If it's negative, it means we found the duplicate number. Store the duplicate number (index + 1) in the result array.
3. Iterate through the array again to find the first positive value. This index plus one will be the missing number, as others should have been negated in the previous steps.
4. Add the missing number to the result array and return it.


# Maximum Length of Pair Chain

- slug: maximum-length-of-pair-chain
- difficulty: Medium

You are given an array of `n` pairs `pairs` where `pairs[i] = [lefti, righti]` and `lefti < righti`.

A pair `p2 = [c, d]` **follows** a pair `p1 = [a, b]` if `b < c`. A **chain** of pairs can be formed in this fashion.

Return _the length longest chain which can be formed_.

You do not need to use up all the given intervals. You can select pairs in any order.

**Example 1:**

**Input:** pairs = \[\[1,2\],\[2,3\],\[3,4\]\]
**Output:** 2
**Explanation:** The longest chain is \[1,2\] -> \[3,4\].

**Example 2:**

**Input:** pairs = \[\[1,2\],\[7,8\],\[4,5\]\]
**Output:** 3
**Explanation:** The longest chain is \[1,2\] -> \[4,5\] -> \[7,8\].

**Constraints:**

*   `n == pairs.length`
*   `1 <= n <= 1000`
*   `-1000 <= lefti < righti <= 1000`

## A solution in Java

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

public int findLongestChain(int[][] pairs) {
    Arrays.sort(pairs, Comparator.comparingInt(a -> a[1]));

    int max_chain_length = 0, last_right = Integer.MIN_VALUE;
    for (int[] pair : pairs) {
        if (pair[0] > last_right) {
            last_right = pair[1];
            max_chain_length++;
        }
    }

    return max_chain_length;
}
```
The algorithm first sorts the array of pairs based on their second element. It then iterates through the pairs checking if the first element of the current pair is larger than the second element of the previous pair (i.e., if the current pair can follow the previous pair in the chain). If it can, it updates `last_right` to be the second element of the current pair and increments the max_chain_length. The time complexity of the algorithm is O(n*log(n)) due to sorting. In the worst case, it might create a chain of length n.

## A solution in C++

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

int findLongestChain(std::vector<std::vector<int>>& pairs) {
    std::sort(pairs.begin(), pairs.end(), [](const std::vector<int>& a, const std::vector<int>& b) {
        return a[1] < b[1];
    });

    int max_chain_length = 0, last_right = INT_MIN;
    for (const auto& pair : pairs) {
        if (pair[0] > last_right) {
            last_right = pair[1];
            max_chain_length++;
        }
    }

    return max_chain_length;
}
```
The algorithm first sorts the array of pairs based on their second element. It then iterates through the pairs checking if the first element of the current pair is larger than the second element of the previous pair (i.e., if the current pair can follow the previous pair in the chain). If it can, it updates `last_right` to be the second element of the current pair and increments the max_chain_length. The time complexity of the algorithm is O(n*log(n)) due to sorting. In the worst case, it might create a chain of length n.

## A solution in Python

```python
def findLongestChain(pairs):
    pairs.sort(key=lambda x: x[1])

    max_chain_length = 0
    last_right = float('-inf')
    for pair in pairs:
        if pair[0] > last_right:
            last_right = pair[1]
            max_chain_length += 1

    return max_chain_length
```
The algorithm first sorts the array of pairs based on their second element. It then iterates through the pairs checking if the first element of the current pair is larger than the second element of the previous pair (i.e., if the current pair can follow the previous pair in the chain). If it can, it updates `last_right` to be the second element of the current pair and increments the max_chain_length. The time complexity of the algorithm is O(n*log(n)) due to sorting. In the worst case, it might create a chain of length n.

## A solution in Javascript

```javascript
function findLongestChain(pairs) {
    pairs.sort((a, b) => a[1] - b[1]);

    let max_chain_length = 0, last_right = Number.MIN_SAFE_INTEGER;
    for (const pair of pairs) {
        if (pair[0] > last_right) {
            last_right = pair[1];
            max_chain_length++;
        }
    }

    return max_chain_length;
}
```
The algorithm first sorts the array of pairs based on their second element. It then iterates through the pairs checking if the first element of the current pair is larger than the second element of the previous pair (i.e., if the current pair can follow the previous pair in the chain). If it can, it updates `last_right` to be the second element of the current pair and increments the max_chain_length. The time complexity of the algorithm is O(n*log(n)) due to sorting. In the worst case, it might create a chain of length n.


# Palindromic Substrings

- slug: palindromic-substrings
- difficulty: Medium

Given a string `s`, return _the number of **palindromic substrings** in it_.

A string is a **palindrome** when it reads the same backward as forward.

A **substring** is a contiguous sequence of characters within the string.

**Example 1:**

**Input:** s =  "abc "
**Output:** 3
**Explanation:** Three palindromic strings:  "a ",  "b ",  "c ".

**Example 2:**

**Input:** s =  "aaa "
**Output:** 6
**Explanation:** Six palindromic strings:  "a ",  "a ",  "a ",  "aa ",  "aa ",  "aaa ".

**Constraints:**

*   `1 <= s.length <= 1000`
*   `s` consists of lowercase English letters.

## A solution in Java

```java
public int countSubstrings(String s) {
    int n = s.length(), count = 0;
    for (int center = 0; center < 2 * n - 1; ++center) {
        int left = center / 2;
        int right = left + center % 2;
        while (left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
            ++count;
            --left;
            ++right;
        }
    }
    return count;
}
```
The algorithm is based on the idea of expanding a palindromic substring out from its center. There can be 2 * n - 1 possible centers for a string of length n. For each center, the algorithm initializes two pointers, left and right. Initially, left = center / 2, and right = left + center % 2. This ensures that both odd- and even-length palindromic substrings are covered. Then, for each center, the algorithm checks if characters at left and right are equal. If so, increment the count, move left pointer one position to the left, and right pointer one position to the right. The process continues until conditions are no longer satisfied, ensuring all palindromic substrings are taken into account. Finally, the count is returned as the answer.

## A solution in C++

```cpp
int countSubstrings(std::string s) {
    int n = s.size(), count = 0;
    for (int center = 0; center < 2 * n - 1; ++center) {
        int left = center / 2;
        int right = left + center % 2;
        while (left >= 0 && right < n && s[left] == s[right]) {
            ++count;
            --left;
            ++right;
        }
    }
    return count;
}
```
The algorithm is based on the idea of expanding a palindromic substring out from its center. There can be 2 * n - 1 possible centers for a string of length n. For each center, the algorithm initializes two pointers, left and right. Initially, left = center / 2, and right = left + center % 2. This ensures that both odd- and even-length palindromic substrings are covered. Then, for each center, the algorithm checks if characters at left and right are equal. If so, increment the count, move left pointer one position to the left, and right pointer one position to the right. The process continues until conditions are no longer satisfied, ensuring all palindromic substrings are taken into account. Finally, the count is returned as the answer.

## A solution in Python

```python
def countSubstrings(s: str) -> int:
    n = len(s)
    count = 0
    for center in range(2 * n - 1):
        left = center // 2
        right = left + center % 2
        while left >= 0 and right < n and s[left] == s[right]:
            count += 1
            left -= 1
            right += 1
    return count
```
The algorithm is based on the idea of expanding a palindromic substring out from its center. There can be 2 * n - 1 possible centers for a string of length n. For each center, the algorithm initializes two pointers, left and right. Initially, left = center / 2, and right = left + center % 2. This ensures that both odd- and even-length palindromic substrings are covered. Then, for each center, the algorithm checks if characters at left and right are equal. If so, increment the count, move left pointer one position to the left, and right pointer one position to the right. The process continues until conditions are no longer satisfied, ensuring all palindromic substrings are taken into account. Finally, the count is returned as the answer.

## A solution in Javascript

```javascript
function countSubstrings(s) {
    const n = s.length;
    let count = 0;
    for (let center = 0; center < 2 * n - 1; ++center) {
        let left = Math.floor(center / 2);
        let right = left + center % 2;
        while (left >= 0 && right < n && s[left] === s[right]) {
            ++count;
            --left;
            ++right;
        }
    }
    return count;
}
```
The algorithm is based on the idea of expanding a palindromic substring out from its center. There can be 2 * n - 1 possible centers for a string of length n. For each center, the algorithm initializes two pointers, left and right. Initially, left = center / 2, and right = left + center % 2. This ensures that both odd- and even-length palindromic substrings are covered. Then, for each center, the algorithm checks if characters at left and right are equal. If so, increment the count, move left pointer one position to the left, and right pointer one position to the right. The process continues until conditions are no longer satisfied, ensuring all palindromic substrings are taken into account. Finally, the count is returned as the answer.


# Replace Words

- slug: replace-words
- difficulty: Medium

In English, we have a concept called **root**, which can be followed by some other word to form another longer word - let's call this word **successor**. For example, when the **root** `"an "` is followed by the **successor** word `"other "`, we can form a new word `"another "`.

Given a `dictionary` consisting of many **roots** and a `sentence` consisting of words separated by spaces, replace all the **successors** in the sentence with the **root** forming it. If a **successor** can be replaced by more than one **root**, replace it with the **root** that has **the shortest length**.

Return _the `sentence`_ after the replacement.

**Example 1:**

**Input:** dictionary = \[ "cat ", "bat ", "rat "\], sentence =  "the cattle was rattled by the battery "
**Output:**  "the cat was rat by the bat "

**Example 2:**

**Input:** dictionary = \[ "a ", "b ", "c "\], sentence =  "aadsfasf absbs bbab cadsfafs "
**Output:**  "a a b c "

**Constraints:**

*   `1 <= dictionary.length <= 1000`
*   `1 <= dictionary[i].length <= 100`
*   `dictionary[i]` consists of only lower-case letters.
*   `1 <= sentence.length <= 106`
*   `sentence` consists of only lower-case letters and spaces.
*   The number of words in `sentence` is in the range `[1, 1000]`
*   The length of each word in `sentence` is in the range `[1, 1000]`
*   Every two consecutive words in `sentence` will be separated by exactly one space.
*   `sentence` does not have leading or trailing spaces.

## A solution in Java

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

public String replaceWords(List<String> dict, String sentence) {
    Set<String> roots = new HashSet<>(dict);
    String[] words = sentence.split(" ");
    StringBuilder result = new StringBuilder();

    for (String word : words) {
        String prefix = "";
        for (int i = 1; i <= word.length(); ++i) {
            prefix = word.substring(0, i);
            if (roots.contains(prefix)) {
                break;
            }
        }
        result.append(prefix).append(" ");
    }

    return result.toString().trim();
}
```
1. Create a set of roots from the given dictionary to easily look up if a word fragment is in the roots.
2. Split the sentence into words.
3. Iterate through each word, create a prefix variable that will keep track of the word fragment:
   a. Start with an empty prefix.
   b. Iterate through the characters of the word, adding one character at a time to the prefix.
   c. Check if the prefix is in the roots set.
   d. If a root is found, break the iteration.
4. Add the final prefix to the result list.
5. Join the result list into a string, separating words with spaces.
6. Return the final result string.

## A solution in C++

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

std::string replaceWords(std::vector<std::string>& dict, std::string sentence) {
    std::unordered_set<std::string> roots(dict.begin(), dict.end());
    std::istringstream iss(sentence);
    std::string word, result;

    while (iss >> word) {
        std::string prefix;
        for (int i = 1; i <= word.length(); ++i) {
            prefix = word.substr(0, i);
            if (roots.count(prefix)) {
                break;
            }
        }
        result += prefix + " ";
    }
    result.pop_back();
    return result;
}
```
1. Create a set of roots from the given dictionary to easily look up if a word fragment is in the roots.
2. Split the sentence into words.
3. Iterate through each word, create a prefix variable that will keep track of the word fragment:
   a. Start with an empty prefix.
   b. Iterate through the characters of the word, adding one character at a time to the prefix.
   c. Check if the prefix is in the roots set.
   d. If a root is found, break the iteration.
4. Add the final prefix to the result list.
5. Join the result list into a string, separating words with spaces.
6. Return the final result string.

## A solution in Python

```python
def replaceWords(dict, sentence):
    roots = set(dict)
    words = sentence.split()
    result = []

    for word in words:
        prefix = ''
        for i in range(1, len(word) + 1):
            prefix = word[:i]
            if prefix in roots:
                break
        result.append(prefix)

    return ' '.join(result)
```
1. Create a set of roots from the given dictionary to easily look up if a word fragment is in the roots.
2. Split the sentence into words.
3. Iterate through each word, create a prefix variable that will keep track of the word fragment:
   a. Start with an empty prefix.
   b. Iterate through the characters of the word, adding one character at a time to the prefix.
   c. Check if the prefix is in the roots set.
   d. If a root is found, break the iteration.
4. Add the final prefix to the result list.
5. Join the result list into a string, separating words with spaces.
6. Return the final result string.

## A solution in Javascript

```javascript
function replaceWords(dict, sentence) {
    const roots = new Set(dict);
    const words = sentence.split(' ');
    const result = [];

    for (const word of words) {
        let prefix = '';
        for (let i = 1; i <= word.length; ++i) {
            prefix = word.substring(0, i);
            if (roots.has(prefix)) {
                break;
            }
        }
        result.push(prefix);
    }

    return result.join(' ');
}
```
1. Create a set of roots from the given dictionary to easily look up if a word fragment is in the roots.
2. Split the sentence into words.
3. Iterate through each word, create a prefix variable that will keep track of the word fragment:
   a. Start with an empty prefix.
   b. Iterate through the characters of the word, adding one character at a time to the prefix.
   c. Check if the prefix is in the roots set.
   d. If a root is found, break the iteration.
4. Add the final prefix to the result list.
5. Join the result list into a string, separating words with spaces.
6. Return the final result string.


# Dota2 Senate

- slug: dota2-senate
- difficulty: Medium

In the world of Dota2, there are two parties: the Radiant and the Dire.

The Dota2 senate consists of senators coming from two parties. Now the Senate wants to decide on a change in the Dota2 game. The voting for this change is a round-based procedure. In each round, each senator can exercise **one** of the two rights:

*   **Ban one senator's right:** A senator can make another senator lose all his rights in this and all the following rounds.
*   **Announce the victory:** If this senator found the senators who still have rights to vote are all from the same party, he can announce the victory and decide on the change in the game.

Given a string `senate` representing each senator's party belonging. The character `'R'` and `'D'` represent the Radiant party and the Dire party. Then if there are `n` senators, the size of the given string will be `n`.

The round-based procedure starts from the first senator to the last senator in the given order. This procedure will last until the end of voting. All the senators who have lost their rights will be skipped during the procedure.

Suppose every senator is smart enough and will play the best strategy for his own party. Predict which party will finally announce the victory and change the Dota2 game. The output should be `"Radiant "` or `"Dire "`.

**Example 1:**

**Input:** senate =  "RD "
**Output:**  "Radiant "
**Explanation:**
The first senator comes from Radiant and he can just ban the next senator's right in round 1.
And the second senator can't exercise any rights anymore since his right has been banned.
And in round 2, the first senator can just announce the victory since he is the only guy in the senate who can vote.

**Example 2:**

**Input:** senate =  "RDD "
**Output:**  "Dire "
**Explanation:**
The first senator comes from Radiant and he can just ban the next senator's right in round 1.
And the second senator can't exercise any rights anymore since his right has been banned.
And the third senator comes from Dire and he can ban the first senator's right in round 1.
And in round 2, the third senator can just announce the victory since he is the only guy in the senate who can vote.

**Constraints:**

*   `n == senate.length`
*   `1 <= n <= 104`
*   `senate[i]` is either `'R'` or `'D'`.

## A solution in Java

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

public String predictPartyVictory(String senate) {
    Queue<Integer> radiant = new LinkedList<>();
    Queue<Integer> dire = new LinkedList<>();
    int n = senate.length();

    for (int i = 0; i < n; i++) {
        if (senate.charAt(i) == 'R')
            radiant.add(i);
        else
            dire.add(i);
    }

    while (!radiant.isEmpty() && !dire.isEmpty()) {
        int r = radiant.poll();
        int d = dire.poll();

        if (r < d)
            radiant.add(r + n);
        else
            dire.add(d + n);
    }

    return radiant.isEmpty() ? "Dire" : "Radiant";
}
```
The algorithm uses a power of choices using round-based voting which works as follows:

1. Create two queues: Radiant and Dire, and a variable `n` to store the length of the senate string.
2. Iterate through the `senate` string, and for each character, enqueue the position to the respective queue.
3. While both queues are not empty, dequeue an element from each queue (Radiant and Dire). Compare if the radiant element is smaller; then enqueue radiant element + `n` to the Radiant queue, otherwise, enqueue dire element + `n` to Dire queue.
4. When one of the queues is empty, return the victory of the party that still has elements in the queue. If the Radiant queue is not empty, return "Radiant", otherwise, return "Dire".

This way, the algorithm simulates the round-based voting, considering the best strategy for each party. When one party is no longer able to vote, the other party wins.

## A solution in C++

```cpp
#include <string>
#include <queue>

std::string predictPartyVictory(std::string senate) {
    std::queue<int> radiant, dire;
    int n = senate.size();

    for (int i = 0; i < n; i++) {
        if (senate[i] == 'R')
            radiant.push(i);
        else
            dire.push(i);
    }

    while (!radiant.empty() && !dire.empty()) {
        int r = radiant.front();
        int d = dire.front();
        radiant.pop();
        dire.pop();

        if (r < d)
            radiant.push(r + n);
        else
            dire.push(d + n);
    }

    return radiant.empty() ? "Dire" : "Radiant";
}
```
The algorithm uses a power of choices using round-based voting which works as follows:

1. Create two queues: Radiant and Dire, and a variable `n` to store the length of the senate string.
2. Iterate through the `senate` string, and for each character, enqueue the position to the respective queue.
3. While both queues are not empty, dequeue an element from each queue (Radiant and Dire). Compare if the radiant element is smaller; then enqueue radiant element + `n` to the Radiant queue, otherwise, enqueue dire element + `n` to Dire queue.
4. When one of the queues is empty, return the victory of the party that still has elements in the queue. If the Radiant queue is not empty, return "Radiant", otherwise, return "Dire".

This way, the algorithm simulates the round-based voting, considering the best strategy for each party. When one party is no longer able to vote, the other party wins.

## A solution in Python

```python
from collections import deque

def predict_party_victory(senate: str) -> str:
    radiant = deque()
    dire = deque()
    n = len(senate)

    for i, s in enumerate(senate):
        if s == 'R':
            radiant.append(i)
        else:
            dire.append(i)

    while radiant and dire:
        r = radiant.popleft()
        d = dire.popleft()

        if r < d:
            radiant.append(r + n)
        else:
            dire.append(d + n)

    return "Dire" if not radiant else "Radiant"
```
The algorithm uses a power of choices using round-based voting which works as follows:

1. Create two queues: Radiant and Dire, and a variable `n` to store the length of the senate string.
2. Iterate through the `senate` string, and for each character, enqueue the position to the respective queue.
3. While both queues are not empty, dequeue an element from each queue (Radiant and Dire). Compare if the radiant element is smaller; then enqueue radiant element + `n` to the Radiant queue, otherwise, enqueue dire element + `n` to Dire queue.
4. When one of the queues is empty, return the victory of the party that still has elements in the queue. If the Radiant queue is not empty, return "Radiant", otherwise, return "Dire".

This way, the algorithm simulates the round-based voting, considering the best strategy for each party. When one party is no longer able to vote, the other party wins.

## A solution in Javascript

```javascript
function predictPartyVictory(senate) {
    let radiant = [];
    let dire = [];
    let n = senate.length;

    for (let i = 0; i < n; i++) {
        if (senate[i] === 'R')
            radiant.push(i);
        else
            dire.push(i);
    }

    while (radiant.length > 0 && dire.length > 0) {
        let r = radiant.shift();
        let d = dire.shift();

        if (r < d)
            radiant.push(r + n);
        else
            dire.push(d + n);
    }

    return radiant.length === 0 ? "Dire" : "Radiant";
}
```
The algorithm uses a power of choices using round-based voting which works as follows:

1. Create two queues: Radiant and Dire, and a variable `n` to store the length of the senate string.
2. Iterate through the `senate` string, and for each character, enqueue the position to the respective queue.
3. While both queues are not empty, dequeue an element from each queue (Radiant and Dire). Compare if the radiant element is smaller; then enqueue radiant element + `n` to the Radiant queue, otherwise, enqueue dire element + `n` to Dire queue.
4. When one of the queues is empty, return the victory of the party that still has elements in the queue. If the Radiant queue is not empty, return "Radiant", otherwise, return "Dire".

This way, the algorithm simulates the round-based voting, considering the best strategy for each party. When one party is no longer able to vote, the other party wins.


# 2 Keys Keyboard

- slug: 2-keys-keyboard
- difficulty: Medium

There is only one character `'A'` on the screen of a notepad. You can perform one of two operations on this notepad for each step:

*   Copy All: You can copy all the characters present on the screen (a partial copy is not allowed).
*   Paste: You can paste the characters which are copied last time.

Given an integer `n`, return _the minimum number of operations to get the character_ `'A'` _exactly_ `n` _times on the screen_.

**Example 1:**

**Input:** n = 3
**Output:** 3
**Explanation:** Initially, we have one character 'A'.
In step 1, we use Copy All operation.
In step 2, we use Paste operation to get 'AA'.
In step 3, we use Paste operation to get 'AAA'.

**Example 2:**

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

**Constraints:**

*   `1 <= n <= 1000`

## A solution in Java

```java
public int minSteps(int n) {
    int result = 0;
    for (int i = 2; i <= n; i++) {
        while (n % i == 0) {
            result += i;
            n /= i;
        }
    }
    return result;
}
```
We need to find the minimum number of operations to get the character 'A' exactly n times on the screen. The operations are copying all (useful when having a large number of 'A's) and pasting.

We can think about this problem in terms of prime factorization. We are trying to break down n into the sum of various prime factors. The prime factors represent the number of operations needed at each step.

In our algorithm, we initialize the variable `result` to 0, which will store the minimum number of operations. We then start with i = 2 (smallest prime number) and iterate through all values less than or equal to n. Inside the loop, we check if n is divisible by i (i.e., n % i == 0). If yes, we add i to `result` and divide n by i. We keep doing this while n is divisible by i. Once n is no longer divisible by i, move on to the next value of i.

At the end of the algorithm, the `result` variable will contain the minimum number of operations to get n 'A's on the screen.

## A solution in C++

```cpp
int minSteps(int n) {
    int result = 0;
    for (int i = 2; i <= n; ++i) {
        while (n % i == 0) {
            result += i;
            n /= i;
        }
    }
    return result;
}
```
We need to find the minimum number of operations to get the character 'A' exactly n times on the screen. The operations are copying all (useful when having a large number of 'A's) and pasting.

We can think about this problem in terms of prime factorization. We are trying to break down n into the sum of various prime factors. The prime factors represent the number of operations needed at each step.

In our algorithm, we initialize the variable `result` to 0, which will store the minimum number of operations. We then start with i = 2 (smallest prime number) and iterate through all values less than or equal to n. Inside the loop, we check if n is divisible by i (i.e., n % i == 0). If yes, we add i to `result` and divide n by i. We keep doing this while n is divisible by i. Once n is no longer divisible by i, move on to the next value of i.

At the end of the algorithm, the `result` variable will contain the minimum number of operations to get n 'A's on the screen.

## A solution in Python

```python
def min_steps(n):
    result = 0
    i = 2
    while i <= n:
        while n % i == 0:
            result += i
            n //= i
        i += 1
    return result
```
We need to find the minimum number of operations to get the character 'A' exactly n times on the screen. The operations are copying all (useful when having a large number of 'A's) and pasting.

We can think about this problem in terms of prime factorization. We are trying to break down n into the sum of various prime factors. The prime factors represent the number of operations needed at each step.

In our algorithm, we initialize the variable `result` to 0, which will store the minimum number of operations. We then start with i = 2 (smallest prime number) and iterate through all values less than or equal to n. Inside the loop, we check if n is divisible by i (i.e., n % i == 0). If yes, we add i to `result` and divide n by i. We keep doing this while n is divisible by i. Once n is no longer divisible by i, move on to the next value of i.

At the end of the algorithm, the `result` variable will contain the minimum number of operations to get n 'A's on the screen.

## A solution in Javascript

```javascript
function minSteps(n) {
    let result = 0;
    for (let i = 2; i <= n; i++) {
        while (n % i === 0) {
            result += i;
            n /= i;
        }
    }
    return result;
}
```
We need to find the minimum number of operations to get the character 'A' exactly n times on the screen. The operations are copying all (useful when having a large number of 'A's) and pasting.

We can think about this problem in terms of prime factorization. We are trying to break down n into the sum of various prime factors. The prime factors represent the number of operations needed at each step.

In our algorithm, we initialize the variable `result` to 0, which will store the minimum number of operations. We then start with i = 2 (smallest prime number) and iterate through all values less than or equal to n. Inside the loop, we check if n is divisible by i (i.e., n % i == 0). If yes, we add i to `result` and divide n by i. We keep doing this while n is divisible by i. Once n is no longer divisible by i, move on to the next value of i.

At the end of the algorithm, the `result` variable will contain the minimum number of operations to get n 'A's on the screen.


# 4 Keys Keyboard

- slug: 4-keys-keyboard
- difficulty: Medium

Imagine you have a special keyboard with the following keys:

*   A: Print one `'A'` on the screen.
*   Ctrl-A: Select the whole screen.
*   Ctrl-C: Copy selection to buffer.
*   Ctrl-V: Print buffer on screen appending it after what has already been printed.

Given an integer n, return _the maximum number of_ `'A'` _you can print on the screen with **at most**_ `n` _presses on the keys_.

**Example 1:**

**Input:** n = 3
**Output:** 3
**Explanation:** We can at most get 3 A's on screen by pressing the following key sequence:
A, A, A

**Example 2:**

**Input:** n = 7
**Output:** 9
**Explanation:** We can at most get 9 A's on screen by pressing following key sequence:
A, A, A, Ctrl A, Ctrl C, Ctrl V, Ctrl V

**Constraints:**

*   `1 <= n <= 50`

## A solution in Java

```java
public int maxA(int n) {
    int[] dp = new int[n + 1];
    for(int i = 1; i <= n; ++i) {
        dp[i] = i;
        for(int j = 1; j <= i - 3; ++j)
            dp[i] = Math.max(dp[i], dp[j] * (i - j - 1));
    }
    return dp[n];
}
```
The problem can be solved using dynamic programming. We can create a dp array of size `n + 1` to store the maximum number of 'A's that can be printed with a maximum of `i` presses.

For each position `i` in the dp array, we initialize it with the value of `i`, as the minimum number of 'A's that can be printed is pressing the 'A' key `i` times. Next, we iterate through the previous positions, from `j = 1` to `i - 3`, and calculate the maximum number of 'A's we can obtain by copying the string of 'A's with `(i - j - 1)` Ctrl-V presses right after a Ctrl A and Ctrl C.

To calculate the maximum, we take the maximum between the current value of `dp[i]` and `dp[j] * (i - j - 1)`. Finally, return the value of `dp[n]`, as it represents the maximum number of 'A's that can be printed with a maximum of `n` presses.

## A solution in C++

```cpp
int maxA(int n) {
    vector<int> dp(n + 1);
    for(int i = 1; i <= n; ++i) {
        dp[i] = i;
        for(int j = 1; j <= i - 3; ++j)
            dp[i] = max(dp[i], dp[j] * (i - j - 1));
    }
    return dp[n];
}
```
The problem can be solved using dynamic programming. We can create a dp array of size `n + 1` to store the maximum number of 'A's that can be printed with a maximum of `i` presses.

For each position `i` in the dp array, we initialize it with the value of `i`, as the minimum number of 'A's that can be printed is pressing the 'A' key `i` times. Next, we iterate through the previous positions, from `j = 1` to `i - 3`, and calculate the maximum number of 'A's we can obtain by copying the string of 'A's with `(i - j - 1)` Ctrl-V presses right after a Ctrl A and Ctrl C.

To calculate the maximum, we take the maximum between the current value of `dp[i]` and `dp[j] * (i - j - 1)`. Finally, return the value of `dp[n]`, as it represents the maximum number of 'A's that can be printed with a maximum of `n` presses.

## A solution in Python

```python
def maxA(n: int) -> int:
    dp = [0] * (n + 1)
    for i in range(1, n + 1):
        dp[i] = i
        for j in range(1, i - 2):
            dp[i] = max(dp[i], dp[j] * (i - j - 1))
    return dp[n]
```
The problem can be solved using dynamic programming. We can create a dp array of size `n + 1` to store the maximum number of 'A's that can be printed with a maximum of `i` presses.

For each position `i` in the dp array, we initialize it with the value of `i`, as the minimum number of 'A's that can be printed is pressing the 'A' key `i` times. Next, we iterate through the previous positions, from `j = 1` to `i - 3`, and calculate the maximum number of 'A's we can obtain by copying the string of 'A's with `(i - j - 1)` Ctrl-V presses right after a Ctrl A and Ctrl C.

To calculate the maximum, we take the maximum between the current value of `dp[i]` and `dp[j] * (i - j - 1)`. Finally, return the value of `dp[n]`, as it represents the maximum number of 'A's that can be printed with a maximum of `n` presses.

## A solution in Javascript

```javascript
function maxA(n) {
    let dp = new Array(n + 1);
    for(let i = 1; i <= n; ++i) {
        dp[i] = i;
        for(let j = 1; j <= i - 3; ++j)
            dp[i] = Math.max(dp[i], dp[j] * (i - j - 1));
    }
    return dp[n];
}
```
The problem can be solved using dynamic programming. We can create a dp array of size `n + 1` to store the maximum number of 'A's that can be printed with a maximum of `i` presses.

For each position `i` in the dp array, we initialize it with the value of `i`, as the minimum number of 'A's that can be printed is pressing the 'A' key `i` times. Next, we iterate through the previous positions, from `j = 1` to `i - 3`, and calculate the maximum number of 'A's we can obtain by copying the string of 'A's with `(i - j - 1)` Ctrl-V presses right after a Ctrl A and Ctrl C.

To calculate the maximum, we take the maximum between the current value of `dp[i]` and `dp[j] * (i - j - 1)`. Finally, return the value of `dp[n]`, as it represents the maximum number of 'A's that can be printed with a maximum of `n` presses.


# Find Duplicate Subtrees

- slug: find-duplicate-subtrees
- difficulty: Medium

Given the `root` of a binary tree, return all **duplicate subtrees**.

For each kind of duplicate subtrees, you only need to return the root node of any **one** of them.

Two trees are **duplicate** if they have the **same structure** with the **same node values**.

**Example 1:**

**Input:** root = \[1,2,3,4,null,2,4,null,null,4\]
**Output:** \[\[2,4\],\[4\]\]

**Example 2:**

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

**Example 3:**

**Input:** root = \[2,2,2,3,null,3,null\]
**Output:** \[\[2,3\],\[3\]\]

**Constraints:**

*   The number of the nodes in the tree will be in the range `[1, 5000]`
*   `-200 <= Node.val <= 200`

## A solution in Java

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

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
    Map<String, Integer> treeCount = new HashMap<>();
    List<TreeNode> result = new ArrayList<>();
    findDuplicateSubtreesHelper(root, treeCount, result);
    return result;
}

private String findDuplicateSubtreesHelper(TreeNode root, Map<String, Integer> treeCount, List<TreeNode> result) {
    if (root == null) return "";
    String subtree = root.val + "," + findDuplicateSubtreesHelper(root.left, treeCount, result) + "," + findDuplicateSubtreesHelper(root.right, treeCount, result);
    treeCount.put(subtree, treeCount.getOrDefault(subtree, 0) + 1);
    if (treeCount.get(subtree) == 2) {
        result.add(root);
    }
    return subtree;
}
```
1. We create a helper function that traverses the binary tree in a "postorder" manner.
2. We convert the subtree rooted at each node into a string using in-order traversal.
3. While traversing, we maintain a dictionary (HashMap or Map, depending on the language) to keep track of the frequency of each subtree string.
4. When encountering a subtree string for the second time, we add its root node to the result list.
5. Return the result list.

## A solution in C++

```cpp
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

string findDuplicateSubtreesHelper(TreeNode* root, unordered_map<string, int>& treeCount, vector<TreeNode*>& result) {
    if (!root) return "";
    string subtree = to_string(root->val) + "," + findDuplicateSubtreesHelper(root->left, treeCount, result) + "," + findDuplicateSubtreesHelper(root->right, treeCount, result);
    if (++treeCount[subtree] == 2) {
        result.push_back(root);
    }
    return subtree;
}

vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
    unordered_map<string, int> treeCount;
    vector<TreeNode*> result;
    findDuplicateSubtreesHelper(root, treeCount, result);
    return result;
}
```
1. We create a helper function that traverses the binary tree in a "postorder" manner.
2. We convert the subtree rooted at each node into a string using in-order traversal.
3. While traversing, we maintain a dictionary (HashMap or Map, depending on the language) to keep track of the frequency of each subtree string.
4. When encountering a subtree string for the second time, we add its root node to the result list.
5. Return the result list.

## A solution in Python

```python
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def findDuplicateSubtrees(root):
    tree_count = {}
    result = []
    findDuplicateSubtreesHelper(root, tree_count, result)
    return result

def findDuplicateSubtreesHelper(root, tree_count, result):
    if root is None:
        return ""
    subtree = "{},{},{}".format(root.val, findDuplicateSubtreesHelper(root.left, tree_count, result), findDuplicateSubtreesHelper(root.right, tree_count, result))
    tree_count[subtree] = tree_count.get(subtree, 0) + 1
    if tree_count[subtree] == 2:
        result.append(root)
    return subtree
```
1. We create a helper function that traverses the binary tree in a "postorder" manner.
2. We convert the subtree rooted at each node into a string using in-order traversal.
3. While traversing, we maintain a dictionary (HashMap or Map, depending on the language) to keep track of the frequency of each subtree string.
4. When encountering a subtree string for the second time, we add its root node to the result list.
5. Return the result list.

## A solution in Javascript

```javascript
class TreeNode {
    constructor(val, left = null, right = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function findDuplicateSubtrees(root) {
    const treeCount = new Map();
    const result = [];
    findDuplicateSubtreesHelper(root, treeCount, result);
    return result;
}

function findDuplicateSubtreesHelper(root, treeCount, result) {
    if (root === null) return "";
    const subtree = `${root.val},${findDuplicateSubtreesHelper(root.left, treeCount, result)},${findDuplicateSubtreesHelper(root.right, treeCount, result)}`;
    treeCount.set(subtree, (treeCount.get(subtree) || 0) + 1);
    if (treeCount.get(subtree) === 2) {
        result.push(root);
    }
    return subtree;
}
```
1. We create a helper function that traverses the binary tree in a "postorder" manner.
2. We convert the subtree rooted at each node into a string using in-order traversal.
3. While traversing, we maintain a dictionary (HashMap or Map, depending on the language) to keep track of the frequency of each subtree string.
4. When encountering a subtree string for the second time, we add its root node to the result list.
5. Return the result list.


# Two Sum IV - Input is a BST

- slug: two-sum-iv-input-is-a-bst
- difficulty: Easy

Given the `root` of a binary search tree and an integer `k`, return `true` _if there exist two elements in the BST such that their sum is equal to_ `k`, _or_ `false` _otherwise_.

**Example 1:**

**Input:** root = \[5,3,6,2,4,null,7\], k = 9
**Output:** true

**Example 2:**

**Input:** root = \[5,3,6,2,4,null,7\], k = 28
**Output:** false

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 104]`.
*   `-104 <= Node.val <= 104`
*   `root` is guaranteed to be a **valid** binary search tree.
*   `-105 <= k <= 105`

## A solution in Java

```java
public boolean findTarget(TreeNode root, int k) {
    Set<Integer> nodes = new HashSet<>();
    return findNode(root, k, nodes);
}

public boolean findNode(TreeNode root, int k, Set<Integer> nodes) {
    if (root == null) return false;
    if (nodes.contains(k - root.val)) return true;
    nodes.add(root.val);
    return findNode(root.left, k, nodes) || findNode(root.right, k, nodes);
}
```
The function takes the root of a binary search tree and a target number `k`. The purpose is to see if there are two elements in the tree that sum up to `k`. We start by initializing a set called `nodes` to keep track of visited values. Then, we create a recursive helper function called `findNode`.

In the `findNode` function, the base case is when the current root is null, meaning we've reached the end of a branch, and we return false as no such pair of elements found yet. If `k - root.val` is found in our set, that means we've found a pair of elements that sum up to `k`, and we can return true. Otherwise, we proceed with the left and right children of the current root, passing the `nodes` set along to keep track of visited values. This is done using a depth-first search strategy.

The result is a boolean indicating whether or not two elements in the tree sum up to `k`.

## A solution in C++

```cpp
bool findTarget(TreeNode* root, int k) {
    unordered_set<int> nodes;
    return findNode(root, k, nodes);
}

bool findNode(TreeNode* root, int k, unordered_set<int>& nodes) {
    if (!root) return false;
    if (nodes.count(k - root->val)) return true;
    nodes.insert(root->val);
    return findNode(root->left, k, nodes) || findNode(root->right, k, nodes);
}
```
The function takes the root of a binary search tree and a target number `k`. The purpose is to see if there are two elements in the tree that sum up to `k`. We start by initializing a set called `nodes` to keep track of visited values. Then, we create a recursive helper function called `findNode`.

In the `findNode` function, the base case is when the current root is null, meaning we've reached the end of a branch, and we return false as no such pair of elements found yet. If `k - root.val` is found in our set, that means we've found a pair of elements that sum up to `k`, and we can return true. Otherwise, we proceed with the left and right children of the current root, passing the `nodes` set along to keep track of visited values. This is done using a depth-first search strategy.

The result is a boolean indicating whether or not two elements in the tree sum up to `k`.

## A solution in Python

```python
def findTarget(root, k):
    nodes = set()
    return findNode(root, k, nodes)

def findNode(root, k, nodes):
    if not root:
        return False
    if k - root.val in nodes:
        return True
    nodes.add(root.val)
    return findNode(root.left, k, nodes) or findNode(root.right, k, nodes)
```
The function takes the root of a binary search tree and a target number `k`. The purpose is to see if there are two elements in the tree that sum up to `k`. We start by initializing a set called `nodes` to keep track of visited values. Then, we create a recursive helper function called `findNode`.

In the `findNode` function, the base case is when the current root is null, meaning we've reached the end of a branch, and we return false as no such pair of elements found yet. If `k - root.val` is found in our set, that means we've found a pair of elements that sum up to `k`, and we can return true. Otherwise, we proceed with the left and right children of the current root, passing the `nodes` set along to keep track of visited values. This is done using a depth-first search strategy.

The result is a boolean indicating whether or not two elements in the tree sum up to `k`.

## A solution in Javascript

```javascript
function findTarget(root, k) {
    const nodes = new Set();
    return findNode(root, k, nodes);
}

function findNode(root, k, nodes) {
    if (!root) return false;
    if (nodes.has(k - root.val)) return true;
    nodes.add(root.val);
    return findNode(root.left, k, nodes) || findNode(root.right, k, nodes);
}
```
The function takes the root of a binary search tree and a target number `k`. The purpose is to see if there are two elements in the tree that sum up to `k`. We start by initializing a set called `nodes` to keep track of visited values. Then, we create a recursive helper function called `findNode`.

In the `findNode` function, the base case is when the current root is null, meaning we've reached the end of a branch, and we return false as no such pair of elements found yet. If `k - root.val` is found in our set, that means we've found a pair of elements that sum up to `k`, and we can return true. Otherwise, we proceed with the left and right children of the current root, passing the `nodes` set along to keep track of visited values. This is done using a depth-first search strategy.

The result is a boolean indicating whether or not two elements in the tree sum up to `k`.


# Maximum Binary Tree

- slug: maximum-binary-tree
- difficulty: Medium

You are given an integer array `nums` with no duplicates. A **maximum binary tree** can be built recursively from `nums` using the following algorithm:

1.  Create a root node whose value is the maximum value in `nums`.
2.  Recursively build the left subtree on the **subarray prefix** to the **left** of the maximum value.
3.  Recursively build the right subtree on the **subarray suffix** to the **right** of the maximum value.

Return _the **maximum binary tree** built from_ `nums`.

**Example 1:**

**Input:** nums = \[3,2,1,6,0,5\]
**Output:** \[6,3,5,null,2,0,null,null,1\]
**Explanation:** The recursive calls are as follow:
- The largest value in \[3,2,1,6,0,5\] is 6. Left prefix is \[3,2,1\] and right suffix is \[0,5\].
    - The largest value in \[3,2,1\] is 3. Left prefix is \[\] and right suffix is \[2,1\].
        - Empty array, so no child.
        - The largest value in \[2,1\] is 2. Left prefix is \[\] and right suffix is \[1\].
            - Empty array, so no child.
            - Only one element, so child is a node with value 1.
    - The largest value in \[0,5\] is 5. Left prefix is \[0\] and right suffix is \[\].
        - Only one element, so child is a node with value 0.
        - Empty array, so no child.

**Example 2:**

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

**Constraints:**

*   `1 <= nums.length <= 1000`
*   `0 <= nums[i] <= 1000`
*   All integers in `nums` are **unique**.

## A solution in Java

```java
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public TreeNode constructMaximumBinaryTree(int[] nums) {
    return helper(nums, 0, nums.length - 1);
}

private TreeNode helper(int[] nums, int left, int right) {
    if (left > right) {
        return null;
    }

    int maxIdx = left;
    for (int i = left + 1; i <= right; i++) {
        if (nums[i] > nums[maxIdx]) {
            maxIdx = i;
        }
    }

    TreeNode root = new TreeNode(nums[maxIdx]);
    root.left = helper(nums, left, maxIdx - 1);
    root.right = helper(nums, maxIdx + 1, right);
    return root;
}
```
The algorithm starts by finding the index of the maximum value in nums. This maximum value becomes the root of the maximum binary tree. Then it invokes the helper function recursively to create the left subtree and right subtree by dividing the nums array into two subarrays: one subarray on the left side of the maximum value index and another subarray on the right side of the maximum value index. The base case for recursion is when left is greater than right, which means the subtree is empty (i.e., no elements are available to build a tree), it returns null.

This process continues recursively for each subarray until all elements in nums have been assigned to the maximum binary tree.

## A solution in C++

```cpp
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
    return helper(nums, 0, nums.size() - 1);
}

TreeNode* helper(vector<int>& nums, int left, int right) {
    if (left > right) {
        return nullptr;
    }

    int maxIdx = left;
    for (int i = left + 1; i <= right; i++) {
        if (nums[i] > nums[maxIdx]) {
            maxIdx = i;
        }
    }

    TreeNode* root = new TreeNode(nums[maxIdx]);
    root->left = helper(nums, left, maxIdx - 1);
    root->right = helper(nums, maxIdx + 1, right);
    return root;
}
```
The algorithm starts by finding the index of the maximum value in nums. This maximum value becomes the root of the maximum binary tree. Then it invokes the helper function recursively to create the left subtree and right subtree by dividing the nums array into two subarrays: one subarray on the left side of the maximum value index and another subarray on the right side of the maximum value index. The base case for recursion is when left is greater than right, which means the subtree is empty (i.e., no elements are available to build a tree), it returns null.

This process continues recursively for each subarray until all elements in nums have been assigned to the maximum binary tree.

## A solution in Python

```python
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def constructMaximumBinaryTree(nums):
    def helper(nums, left, right):
        if left > right:
            return None

        maxIdx = left
        for i in range(left + 1, right + 1):
            if nums[i] > nums[maxIdx]:
                maxIdx = i

        root = TreeNode(nums[maxIdx])
        root.left = helper(nums, left, maxIdx - 1)
        root.right = helper(nums, maxIdx + 1, right)
        return root

    return helper(nums, 0, len(nums) - 1)
```
The algorithm starts by finding the index of the maximum value in nums. This maximum value becomes the root of the maximum binary tree. Then it invokes the helper function recursively to create the left subtree and right subtree by dividing the nums array into two subarrays: one subarray on the left side of the maximum value index and another subarray on the right side of the maximum value index. The base case for recursion is when left is greater than right, which means the subtree is empty (i.e., no elements are available to build a tree), it returns null.

This process continues recursively for each subarray until all elements in nums have been assigned to the maximum binary tree.

## A solution in Javascript

```javascript
class TreeNode {
    constructor(val, left = null, right = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function constructMaximumBinaryTree(nums) {
    function helper(nums, left, right) {
        if (left > right) {
            return null;
        }

        let maxIdx = left;
        for (let i = left + 1; i <= right; i++) {
            if (nums[i] > nums[maxIdx]) {
                maxIdx = i;
            }
        }

        const root = new TreeNode(nums[maxIdx]);
        root.left = helper(nums, left, maxIdx - 1);
        root.right = helper(nums, maxIdx + 1, right);
        return root;
    }

    return helper(nums, 0, nums.length - 1);
}
```
The algorithm starts by finding the index of the maximum value in nums. This maximum value becomes the root of the maximum binary tree. Then it invokes the helper function recursively to create the left subtree and right subtree by dividing the nums array into two subarrays: one subarray on the left side of the maximum value index and another subarray on the right side of the maximum value index. The base case for recursion is when left is greater than right, which means the subtree is empty (i.e., no elements are available to build a tree), it returns null.

This process continues recursively for each subarray until all elements in nums have been assigned to the maximum binary tree.