There are `n` cities. Some of them are connected, while some are not. If city
`a` is connected directly with city `b`, and city `b` is connected directly
with city `c`, then city `a` is connected indirectly with city `c`.

A province is a group of directly or indirectly connected cities and no other
cities outside of the group.

You are given an `n x n` matrix `isConnected` where `isConnected[i][j] = 1` if
the `ith` city and the `jth` city are directly connected, and
`isConnected[i][j] = 0` otherwise.

Return the total number of provinces.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class UnionFind:
  def __init__(self, n: int):
    self.count = n
    self.id = list(range(n))
    self.rank = [0] * n

  def unionByRank(self, u: int, v: int) -> None:
    i = self._find(u)
    j = self._find(v)
    if i == j:
      return
    if self.rank[i] < self.rank[j]:
      self.id[i] = j
    elif self.rank[i] > self.rank[j]:
      self.id[j] = i
    else:
      self.id[i] = j
      self.rank[j] += 1
    self.count -= 1

  def _find(self, u: int) -> int:
    if self.id[u] != u:
      self.id[u] = self._find(self.id[u])
    return self.id[u]

class Solution:
  def findCircleNum(self, isConnected: List[List[int]]) -> int:
    n = len(isConnected)
    uf = UnionFind(n)

    for i in range(n):
      for j in range(i, n):
        if isConnected[i][j] == 1:
          uf.unionByRank(i, j)

    return uf.count

class UnionFind {
  public UnionFind(int n) {
    count = n;
    id = new int[n];
    rank = new int[n];
    for (int i = 0; i < n; ++i)
      id[i] = i;
  }

  public void unionByRank(int u, int v) {
    final int i = find(u);
    final int j = find(v);
    if (i == j)
      return;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    --count;
  }

  public int getCount() {
    return count;
  }

  private int count;
  private int[] id;
  private int[] rank;

  private int find(int u) {
    return id[u] == u ? u : (id[u] = find(id[u]));
  }
}

class Solution {
  public int findCircleNum(int[][] isConnected) {
    final int n = isConnected.length;
    UnionFind uf = new UnionFind(n);

    for (int i = 0; i < n; ++i)
      for (int j = i; j < n; ++j)
        if (isConnected[i][j] == 1)
          uf.unionByRank(i, j);

    return uf.getCount();
  }
}

class UnionFind {
 public:
  UnionFind(int n) : count(n), id(n), rank(n) {
    iota(id.begin(), id.end(), 0);
  }

  void unionByRank(int u, int v) {
    const int i = find(u);
    const int j = find(v);
    if (i == j)
      return;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    --count;
  }

  int getCount() const {
    return count;
  }

 private:
  int count;
  vector<int> id;
  vector<int> rank;

  int find(int u) {
    return id[u] == u ? u : id[u] = find(id[u]);
  }
};

class Solution {
 public:
  int findCircleNum(vector<vector<int>>& isConnected) {
    const int n = isConnected.size();
    UnionFind uf(n);

    for (int i = 0; i < n; ++i)
      for (int j = i; j < n; ++j)
        if (isConnected[i][j] == 1)
          uf.unionByRank(i, j);

    return uf.getCount();
  }
};


Given an integer array `nums`, you need to find one continuous subarray such
that if you only sort this subarray in non-decreasing order, then the whole
array will be sorted in non-decreasing order.

Return the shortest such subarray and output its length.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def findUnsortedSubarray(self, nums: List[int]) -> int:
    mini = math.inf
    maxi = -math.inf
    flag = False

    for i in range(1, len(nums)):
      if nums[i] < nums[i - 1]:
        flag = True
      if flag:
        mini = min(mini, nums[i])

    flag = False

    for i in reversed(range(len(nums) - 1)):
      if nums[i] > nums[i + 1]:
        flag = True
      if flag:
        maxi = max(maxi, nums[i])

    for l in range(len(nums)):
      if nums[l] > mini:
        break

    for r, num in reversed(list(enumerate(nums))):
      if num < maxi:
        break

    return 0 if l >= r else r - l + 1

class Solution {
  public int findUnsortedSubarray(int[] nums) {
    final int n = nums.length;
    int mn = Integer.MAX_VALUE;
    int mx = Integer.MIN_VALUE;
    boolean meetDecrease = false;
    boolean meetIncrease = false;

    for (int i = 1; i < n; ++i) {
      if (nums[i] < nums[i - 1])
        meetDecrease = true;
      if (meetDecrease)
        mn = Math.min(mn, nums[i]);
    }

    for (int i = n - 2; i >= 0; --i) {
      if (nums[i] > nums[i + 1])
        meetIncrease = true;
      if (meetIncrease)
        mx = Math.max(mx, nums[i]);
    }

    int l = 0;
    for (l = 0; l < n; ++l)
      if (nums[l] > mn)
        break;

    int r = 0;
    for (r = n - 1; r >= 0; --r)
      if (nums[r] < mx)
        break;

    return l > r ? 0 : r - l + 1;
  }
}

class Solution {
 public:
  int findUnsortedSubarray(vector<int>& nums) {
    const int n = nums.size();
    int mn = INT_MAX;
    int mx = INT_MIN;
    bool meetDecrease = false;
    bool meetIncrease = false;

    for (int i = 1; i < n; ++i) {
      if (nums[i] < nums[i - 1])
        meetDecrease = true;
      if (meetDecrease)
        mn = min(mn, nums[i]);
    }

    for (int i = n - 2; i >= 0; --i) {
      if (nums[i] > nums[i + 1])
        meetIncrease = true;
      if (meetIncrease)
        mx = max(mx, nums[i]);
    }

    int l;
    for (l = 0; l < n; ++l)
      if (nums[l] > mn)
        break;

    int r;
    for (r = n - 1; r >= 0; --r)
      if (nums[r] < mx)
        break;

    return l < r ? r - l + 1 : 0;
  }
};


Given a string representing a code snippet, implement a tag validator to parse
the code and return whether it is valid.

A code snippet is valid if all the following rules hold:

1. The code must be wrapped in a valid closed tag. Otherwise, the code is invalid.
2. A closed tag (not necessarily valid) has exactly the following format : `<TAG_NAME>TAG_CONTENT</TAG_NAME>`. Among them, `<TAG_NAME>` is the start tag, and `</TAG_NAME>` is the end tag. The TAG_NAME in start and end tags should be the same. A closed tag is valid if and only if the TAG_NAME and TAG_CONTENT are valid.
3. A valid `TAG_NAME` only contain upper-case letters, and has length in range [1,9]. Otherwise, the `TAG_NAME` is invalid.
4. A valid `TAG_CONTENT` may contain other valid closed tags, cdata and any characters (see note1) EXCEPT unmatched `<`, unmatched start and end tag, and unmatched or closed tags with invalid TAG_NAME. Otherwise, the `TAG_CONTENT` is invalid.
5. A start tag is unmatched if no end tag exists with the same TAG_NAME, and vice versa. However, you also need to consider the issue of unbalanced when tags are nested.
6. A `<` is unmatched if you cannot find a subsequent `>`. And when you find a `<` or `</`, all the subsequent characters until the next `>` should be parsed as TAG_NAME (not necessarily valid).
7. The cdata has the following format : `<![CDATA[CDATA_CONTENT]]>`. The range of `CDATA_CONTENT` is defined as the characters between `<![CDATA[` and the first subsequent `]]>`.
8. `CDATA_CONTENT` may contain any characters. The function of cdata is to forbid the validator to parse `CDATA_CONTENT`, so even it has some characters that can be parsed as tag (no matter valid or invalid), you should treat it as regular characters.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def isValid(self, code: str) -> bool:
    if code[0] != '<' or code[-1] != '>':
      return False

    containsTag = False
    stack = []

    def isValidCdata(s: str) -> bool:
      return s.find('[CDATA[') == 0

    def isValidTagName(tagName: str, isEndTag: bool) -> bool:
      nonlocal containsTag
      if not tagName or len(tagName) > 9:
        return False
      if any(not c.isupper() for c in tagName):
        return False

      if isEndTag:
        return stack and stack.pop() == tagName

      containsTag = True
      stack.append(tagName)
      return True

    i = 0
    while i < len(code):
      if not stack and containsTag:
        return False
      if code[i] == '<':
        if stack and code[i + 1] == '!':
          closeIndex = code.find(']]>', i + 2)
          if closeIndex == -1 or not isValidCdata(code[i + 2:closeIndex]):
            return False
        elif code[i + 1] == '/':
          closeIndex = code.find('>', i + 2)
          if closeIndex == -1 or not isValidTagName(code[i + 2:closeIndex], True):
            return False
        else:
          closeIndex = code.find('>', i + 1)
          if closeIndex == -1 or not isValidTagName(code[i + 1:closeIndex], False):
            return False
        i = closeIndex
      i += 1

    return not stack and containsTag

class Solution {
  public boolean isValid(String code) {
    if (code.charAt(0) != '<' || code.charAt(code.length() - 1) != '>')
      return false;

    Deque<String> stack = new ArrayDeque<>();

    for (int i = 0; i < code.length(); ++i) {
      int closeIndex = 0;
      if (stack.isEmpty() && containsTag)
        return false;
      if (code.charAt(i) == '<') {
        // It's inside a tag, so check if it's a cdata.
        if (!stack.isEmpty() && code.charAt(i + 1) == '!') {
          closeIndex = code.indexOf("]]>", i + 2);
          if (closeIndex < 0 || !isValidCdata(code.substring(i + 2, closeIndex)))
            return false;
        } else if (code.charAt(i + 1) == '/') { // the end tag
          closeIndex = code.indexOf('>', i + 2);
          if (closeIndex < 0 || !isValidTagName(stack, code.substring(i + 2, closeIndex), true))
            return false;
        } else { // the start tag
          closeIndex = code.indexOf('>', i + 1);
          if (closeIndex < 0 || !isValidTagName(stack, code.substring(i + 1, closeIndex), false))
            return false;
        }
        i = closeIndex;
      }
    }

    return stack.isEmpty() && containsTag;
  }

  private boolean containsTag = false;

  private boolean isValidCdata(final String s) {
    return s.indexOf("[CDATA[") == 0;
  }

  private boolean isValidTagName(Deque<String> stack, String tagName, boolean isEndTag) {
    if (tagName.isEmpty() || tagName.length() > 9)
      return false;

    for (final char c : tagName.toCharArray())
      if (!Character.isUpperCase(c))
        return false;

    if (isEndTag)
      return !stack.isEmpty() && stack.pop().equals(tagName);

    containsTag = true;
    stack.push(tagName);
    return true;
  }
}

class Solution {
 public:
  bool isValid(string code) {
    if (code[0] != '<' || code.back() != '>')
      return false;

    stack<string> stack;

    for (int i = 0; i < code.length(); ++i) {
      int closeIndex = 0;
      if (stack.empty() && containsTag)
        return false;
      if (code[i] == '<') {
        // It's inside a tag, so check if it's a cdata.
        if (!stack.empty() && code[i + 1] == '!') {
          closeIndex = code.find("]]>", i + 2);
          if (closeIndex == string::npos ||
              !isValidCdata(code.substr(i + 2, closeIndex - i - 2)))
            return false;
        } else if (code[i + 1] == '/') {  // the end tag
          closeIndex = code.find('>', i + 2);
          if (closeIndex == string::npos ||
              !isValidTagName(stack, code.substr(i + 2, closeIndex - i - 2),
                              true))
            return false;
        } else {  // the start tag
          closeIndex = code.find('>', i + 1);
          if (closeIndex == string::npos ||
              !isValidTagName(stack, code.substr(i + 1, closeIndex - i - 1),
                              false))
            return false;
        }
        i = closeIndex;
      }
    }

    return stack.empty() && containsTag;
  }

 private:
  bool containsTag = false;

  bool isValidCdata(const string& s) {
    return s.find("[CDATA[") == 0;
  }

  bool isValidTagName(stack<string>& stack, const string& tagName,
                      bool isEndTag) {
    if (tagName.empty() || tagName.length() > 9)
      return false;

    for (const char c : tagName)
      if (!isupper(c))
        return false;

    if (isEndTag) {
      if (stack.empty())
        return false;
      if (stack.top() != tagName)
        return false;
      stack.pop();
      return true;
    }

    containsTag = true;
    stack.push(tagName);
    return true;
  }
};


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 `"help"` is followed by the successor word `"ful"`, we
can form a new word `"helpful"`.

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.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def __init__(self):
    self.root = {}

  def insert(self, word: str) -> None:
    node = self.root
    for c in word:
      if c not in node:
        node[c] = {}
      node = node[c]
    node['word'] = word

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

  def replaceWords(self, dictionary: List[str], sentence: str) -> str:
    for word in dictionary:
      self.insert(word)

    words = sentence.split(' ')
    return ' '.join([self.search(word) for word in words])

class TrieNode {
  TrieNode[] children = new TrieNode[26];
  String word;
}

class Solution {
  public String replaceWords(List<String> dictionary, String sentence) {
    StringBuilder sb = new StringBuilder();

    for (final String word : dictionary)
      insert(word);

    final String[] words = sentence.split(" ");
    for (final String word : words)
      sb.append(' ').append(search(word));

    return sb.substring(1).toString();
  }

  private TrieNode root = new TrieNode();

  private void insert(final String word) {
    TrieNode node = root;
    for (char c : word.toCharArray()) {
      final int i = c - 'a';
      if (node.children[i] == null)
        node.children[i] = new TrieNode();
      node = node.children[i];
    }
    node.word = word;
  }

  private String search(final String word) {
    TrieNode node = root;
    for (char c : word.toCharArray()) {
      if (node.word != null)
        return node.word;
      final int i = c - 'a';
      if (node.children[i] == null)
        return word;
      node = node.children[i];
    }
    return word;
  }
}

struct TrieNode {
  vector<shared_ptr<TrieNode>> children;
  const string* word = nullptr;
  TrieNode() : children(26) {}
};

class Solution {
 public:
  string replaceWords(vector<string>& dictionary, string sentence) {
    for (const string& word : dictionary)
      insert(word);

    string ans;
    istringstream iss(sentence);

    for (string s; iss >> s;)
      ans += search(s) + ' ';
    ans.pop_back();

    return ans;
  }

 private:
  shared_ptr<TrieNode> root = make_shared<TrieNode>();

  void insert(const string& word) {
    shared_ptr<TrieNode> node = root;
    for (const char c : word) {
      const int i = c - 'a';
      if (node->children[i] == nullptr)
        node->children[i] = make_shared<TrieNode>();
      node = node->children[i];
    }
    node->word = &word;
  }

  string search(const string& word) {
    shared_ptr<TrieNode> node = root;
    for (const char c : word) {
      if (node->word)
        return *node->word;
      const int i = c - 'a';
      if (node->children[i] == nullptr)
        return word;
      node = node->children[i];
    }
    return word;
  }
};


Number of Longest Increasing Subsequence

Given an integer array `nums`, return the number of longest increasing
subsequences.

Notice that the sequence has to be strictly increasing.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def findNumberOfLIS(self, nums: List[int]) -> int:
    ans = 0
    maxLength = 0
    length = [1] * len(nums)
    count = [1] * len(nums)

    for i, num in enumerate(nums):
      for j in range(i):
        if nums[j] < num:
          if length[i] < length[j] + 1:
            length[i] = length[j] + 1
            count[i] = count[j]
          elif length[i] == length[j] + 1:
            count[i] += count[j]

    for i, l in enumerate(length):
      if l > maxLength:
        maxLength = l
        ans = count[i]
      elif l == maxLength:
        ans += count[i]

    return ans

class Solution {
  public int findNumberOfLIS(int[] nums) {
    final int n = nums.length;
    int ans = 0;
    int maxLength = 0;
    // length[i] := the length of the LIS ending in nums[i]
    int[] length = new int[n];
    // count[i] := the number of LIS's ending in nums[i]
    int[] count = new int[n];

    Arrays.fill(length, 1);
    Arrays.fill(count, 1);

    // Calculate the `length` and `count` arrays.
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < i; ++j)
        if (nums[j] < nums[i])
          if (length[i] < length[j] + 1) {
            length[i] = length[j] + 1;
            count[i] = count[j];
          } else if (length[i] == length[j] + 1) {
            count[i] += count[j];
          }

    // Get the number of LIS.
    for (int i = 0; i < n; ++i)
      if (length[i] > maxLength) {
        maxLength = length[i];
        ans = count[i];
      } else if (length[i] == maxLength) {
        ans += count[i];
      }

    return ans;
  }
}

class Solution {
 public:
  int findNumberOfLIS(vector<int>& nums) {
    const int n = nums.size();
    int ans = 0;
    int maxLength = 0;
    // length[i] := the length of LIS's ending in nums[i]
    vector<int> length(n, 1);
    // count[i] := the number of LIS's ending in nums[i]
    vector<int> count(n, 1);

    // Calculate `length` and `count` arrays.
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < i; ++j)
        if (nums[j] < nums[i])
          if (length[i] < length[j] + 1) {
            length[i] = length[j] + 1;
            count[i] = count[j];
          } else if (length[i] == length[j] + 1) {
            count[i] += count[j];
          }

    // Get the number of LIS.
    for (int i = 0; i < n; ++i)
      if (length[i] > maxLength) {
        maxLength = length[i];
        ans = count[i];
      } else if (length[i] == maxLength) {
        ans += count[i];
      }

    return ans;
  }
};


In this problem, a tree is an undirected graph that is connected and has no
cycles.

You are given a graph that started as a tree with `n` nodes labeled from `1`
to `n`, with one additional edge added. The added edge has two different
vertices chosen from `1` to `n`, and was not an edge that already existed. The
graph is represented as an array `edges` of length `n` where `edges[i] = [ai,
bi]` indicates that there is an edge between nodes `ai` and `bi` in the graph.

Return an edge that can be removed so that the resulting graph is a tree of
`n` nodes. If there are multiple answers, return the answer that occurs last
in the input.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class UnionFind:
  def __init__(self, n: int):
    self.id = list(range(n))
    self.rank = [0] * n

  def unionByRank(self, u: int, v: int) -> bool:
    i = self._find(u)
    j = self._find(v)
    if i == j:
      return False
    if self.rank[i] < self.rank[j]:
      self.id[i] = j
    elif self.rank[i] > self.rank[j]:
      self.id[j] = i
    else:
      self.id[i] = j
      self.rank[j] += 1
    return True

  def _find(self, u: int) -> int:
    if self.id[u] != u:
      self.id[u] = self._find(self.id[u])
    return self.id[u]

class Solution:
  def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
    uf = UnionFind(len(edges) + 1)

    for edge in edges:
      u, v = edge
      if not uf.unionByRank(u, v):
        return edge

class UnionFind {
  public UnionFind(int n) {
    id = new int[n];
    rank = new int[n];
    for (int i = 0; i < n; ++i)
      id[i] = i;
  }

  public boolean unionByRank(int u, int v) {
    final int i = find(u);
    final int j = find(v);
    if (i == j)
      return false;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    return true;
  }

  private int[] id;
  private int[] rank;

  private int find(int u) {
    return id[u] == u ? u : (id[u] = find(id[u]));
  }
}

class Solution {
  public int[] findRedundantConnection(int[][] edges) {
    UnionFind uf = new UnionFind(edges.length + 1);

    for (int[] edge : edges) {
      final int u = edge[0];
      final int v = edge[1];
      if (!uf.unionByRank(u, v))
        return edge;
    }

    throw new IllegalArgumentException();
  }
}

class UnionFind {
 public:
  UnionFind(int n) : id(n), rank(n) {
    iota(id.begin(), id.end(), 0);
  }

  bool unionByRank(int u, int v) {
    const int i = find(u);
    const int j = find(v);
    if (i == j)
      return false;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    return true;
  }

 private:
  vector<int> id;
  vector<int> rank;

  int find(int u) {
    return id[u] == u ? u : id[u] = find(id[u]);
  }
};

class Solution {
 public:
  vector<int> findRedundantConnection(vector<vector<int>>& edges) {
    UnionFind uf(edges.size() + 1);

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      if (!uf.unionByRank(u, v))
        return edge;
    }

    throw;
  }
};


In this problem, a rooted tree is a directed graph such that, there is exactly
one node (the root) for which all other nodes are descendants of this node,
plus every node has exactly one parent, except for the root node which has no
parents.

The given input is a directed graph that started as a rooted tree with `n`
nodes (with distinct values from `1` to `n`), with one additional directed
edge added. The added edge has two different vertices chosen from `1` to `n`,
and was not an edge that already existed.

The resulting graph is given as a 2D-array of `edges`. Each element of `edges`
is a pair `[ui, vi]` that represents a directed edge connecting nodes `ui` and
`vi`, where `ui` is a parent of child `vi`.

Return an edge that can be removed so that the resulting graph is a rooted
tree of `n` nodes. If there are multiple answers, return the answer that
occurs last in the given 2D-array.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class UnionFind:
  def __init__(self, n: int):
    self.id = list(range(n))
    self.rank = [0] * n

  def unionByRank(self, u: int, v: int) -> bool:
    i = self._find(u)
    j = self._find(v)
    if i == j:
      return False
    if self.rank[i] < self.rank[j]:
      self.id[i] = j
    elif self.rank[i] > self.rank[j]:
      self.id[j] = i
    else:
      self.id[i] = j
      self.rank[j] += 1
    return True

  def _find(self, u: int) -> int:
    if self.id[u] != u:
      self.id[u] = self._find(self.id[u])
    return self.id[u]

class Solution:
  def findRedundantDirectedConnection(self, edges: List[List[int]]) -> List[int]:
    ids = [0] * (len(edges) + 1)
    nodeWithTwoParents = 0

    for _, v in edges:
      ids[v] += 1
      if ids[v] == 2:
        nodeWithTwoParents = v

    def findRedundantDirectedConnection(skippedEdgeIndex: int) -> List[int]:
      uf = UnionFind(len(edges) + 1)

      for i, edge in enumerate(edges):
        if i == skippedEdgeIndex:
          continue
        if not uf.unionByRank(edge[0], edge[1]):
          return edge

      return []

    if nodeWithTwoParents == 0:
      return findRedundantDirectedConnection(-1)

    for i in reversed(range(len(edges))):
      _, v = edges[i]
      if v == nodeWithTwoParents:
        if not findRedundantDirectedConnection(i):
          return edges[i]

class UnionFind {
  public UnionFind(int n) {
    id = new int[n];
    rank = new int[n];
    for (int i = 0; i < n; ++i)
      id[i] = i;
  }

  public boolean unionByRank(int u, int v) {
    final int i = find(u);
    final int j = find(v);
    if (i == j)
      return false;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    return true;
  }

  private int[] id;
  private int[] rank;

  private int find(int u) {
    return id[u] == u ? u : (id[u] = find(id[u]));
  }
}

class Solution {
  public int[] findRedundantDirectedConnection(int[][] edges) {
    int[] ids = new int[edges.length + 1];
    int nodeWithTwoParents = 0;

    for (int[] edge : edges) {
      final int v = edge[1];
      if (++ids[v] == 2) {
        nodeWithTwoParents = v;
        break;
      }
    }

    // If there is no edge with two ids, don't skip any edge.
    if (nodeWithTwoParents == 0)
      return findRedundantDirectedConnection(edges, -1);

    for (int i = edges.length - 1; i >= 0; --i)
      if (edges[i][1] == nodeWithTwoParents)
        // Try to delete the edges[i].
        if (findRedundantDirectedConnection(edges, i).length == 0)
          return edges[i];

    throw new IllegalArgumentException();
  }

  private int[] findRedundantDirectedConnection(int[][] edges, int skippedEdgeIndex) {
    UnionFind uf = new UnionFind(edges.length + 1);

    for (int i = 0; i < edges.length; ++i) {
      if (i == skippedEdgeIndex)
        continue;
      if (!uf.unionByRank(edges[i][0], edges[i][1]))
        return edges[i];
    }

    return new int[] {};
  }
}

class UnionFind {
 public:
  UnionFind(int n) : id(n), rank(n) {
    iota(id.begin(), id.end(), 0);
  }

  bool unionByRank(int u, int v) {
    const int i = find(u);
    const int j = find(v);
    if (i == j)
      return false;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
    return true;
  }

 private:
  vector<int> id;
  vector<int> rank;
  int find(int u) {
    return id[u] == u ? u : id[u] = find(id[u]);
  }
};

class Solution {
 public:
  vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
    vector<int> ids(edges.size() + 1);
    int nodeWithTwoParents = 0;

    for (const vector<int>& edge : edges) {
      const int v = edge[1];
      if (++ids[v] == 2) {
        nodeWithTwoParents = v;
        break;
      }
    }

    // If there is no edge with two ids, don't skip any edge.
    if (nodeWithTwoParents == 0)
      return findRedundantDirectedConnection(edges, -1);

    for (int i = edges.size() - 1; i >= 0; --i)
      if (edges[i][1] == nodeWithTwoParents)
        // Try to delete the edges[i].
        if (findRedundantDirectedConnection(edges, i).empty())
          return edges[i];

    throw;
  }

  vector<int> findRedundantDirectedConnection(const vector<vector<int>>& edges,
                                              int skippedEdgeIndex) {
    UnionFind uf(edges.size() + 1);

    for (int i = 0; i < edges.size(); ++i) {
      if (i == skippedEdgeIndex)
        continue;
      if (!uf.unionByRank(edges[i][0], edges[i][1]))
        return edges[i];
    }

    return {};
  }
};


On an `n x n` chessboard, a knight starts at the cell `(row, column)` and
attempts to make exactly `k` moves. The rows and columns are 0-indexed, so the
top-left cell is `(0, 0)`, and the bottom-right cell is `(n - 1, n - 1)`.

A chess knight has eight possible moves it can make, as illustrated below.
Each move is two cells in a cardinal direction, then one cell in an orthogonal
direction.

Each time the knight is to move, it chooses one of eight possible moves
uniformly at random (even if the piece would go off the chessboard) and moves
there.

The knight continues moving until it has made exactly `k` moves or has moved
off the chessboard.

Return the probability that the knight remains on the board after it has
stopped moving.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
    dirs = ((1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2))
    dp = [[0] * n for _ in range(n)]
    dp[row][column] = 1.0

    for _ in range(k):
      newDp = [[0] * n for _ in range(n)]
      for i in range(n):
        for j in range(n):
          for dx, dy in dirs:
            x = i + dx
            y = j + dy
            if 0 <= x < n and 0 <= y < n:
              newDp[i][j] += dp[x][y]
      dp = newDp

    return sum(map(sum, dp)) / 8**k

class Solution {
  public double knightProbability(int n, int k, int row, int column) {
    final int[][] DIRS = {{1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}};
    final double PROB = 0.125;
    // dp[i][j] := the probability to stand on (i, j)
    double[][] dp = new double[n][n];
    dp[row][column] = 1.0;

    for (int move = 0; move < k; ++move) {
      double[][] newDp = new double[n][n];
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
          if (dp[i][j] > 0.0) {
            for (int[] dir : DIRS) {
              final int x = i + dir[0];
              final int y = j + dir[1];
              if (x < 0 || x >= n || y < 0 || y >= n)
                continue;
              newDp[x][y] += dp[i][j] * PROB;
            }
          }
      dp = newDp;
    }

    return Arrays.stream(dp).flatMapToDouble(Arrays::stream).sum();
  }
}

class Solution {
 public:
  double knightProbability(int n, int k, int row, int column) {
    constexpr int kDirs[8][2] = {{1, 2},   {2, 1},   {2, -1}, {1, -2},
                                 {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}};
    constexpr double kProb = 0.125;
    // dp[i][j] := the probability to stand on (i, j)
    vector<vector<double>> dp(n, vector<double>(n));
    dp[row][column] = 1.0;

    for (int move = 0; move < k; ++move) {
      vector<vector<double>> newDp(n, vector<double>(n));
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
          if (dp[i][j] > 0.0) {
            for (const auto& [dx, dy] : kDirs) {
              const int x = i + dx;
              const int y = j + dy;
              if (x < 0 || x >= n || y < 0 || y >= n)
                continue;
              newDp[x][y] += dp[i][j] * kProb;
            }
          }
      dp = std::move(newDp);
    }

    return accumulate(dp.begin(), dp.end(), 0.0,
                      [](double acc, const vector<double>& row) {
      return acc + accumulate(row.begin(), row.end(), 0.0);
    });
  }
};


Maximum Sum of 3 Non-Overlapping Subarrays

Given an integer array `nums` and an integer `k`, find three non-overlapping
subarrays of length `k` with maximum sum and return them.

Return the result as a list of indices representing the starting position of
each interval (0-indexed). If there are multiple answers, return the
lexicographically smallest one.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def maxSumOfThreeSubarrays(self, nums: List[int], k: int) -> List[int]:
    n = len(nums) - k + 1
    sums = [0] * n
    l = [0] * n
    r = [0] * n

    summ = 0
    for i, num in enumerate(nums):
      summ += num
      if i >= k:
        summ -= nums[i - k]
      if i >= k - 1:
        sums[i - k + 1] = summ

    maxIndex = 0
    for i in range(n):
      if sums[i] > sums[maxIndex]:
        maxIndex = i
      l[i] = maxIndex

    maxIndex = n - 1
    for i in range(n - 1, -1, -1):
      if sums[i] >= sums[maxIndex]:
        maxIndex = i
      r[i] = maxIndex

    ans = [-1, -1, -1]

    for i in range(k, n - k):
      if ans[0] == -1 or sums[ans[0]] + sums[ans[1]] + sums[ans[2]] < sums[l[i - k]] + sums[i] + sums[r[i + k]]:
        ans[0] = l[i - k]
        ans[1] = i
        ans[2] = r[i + k]

    return ans

class Solution {
  public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
    final int n = nums.length - k + 1;
    // sums[i] := sum(nums[i..i + k))
    int[] sums = new int[n];
    // l[i] := the index in [0..i] that has the maximum sums[i]
    int[] l = new int[n];
    // r[i] := the index in [i..n) that has the maximum sums[i]
    int[] r = new int[n];

    int sum = 0;
    for (int i = 0; i < nums.length; ++i) {
      sum += nums[i];
      if (i >= k)
        sum -= nums[i - k];
      if (i >= k - 1)
        sums[i - k + 1] = sum;
    }

    int maxIndex = 0;
    for (int i = 0; i < n; ++i) {
      if (sums[i] > sums[maxIndex])
        maxIndex = i;
      l[i] = maxIndex;
    }

    maxIndex = n - 1;
    for (int i = n - 1; i >= 0; --i) {
      if (sums[i] >= sums[maxIndex])
        maxIndex = i;
      r[i] = maxIndex;
    }

    int[] ans = {-1, -1, -1};

    for (int i = k; i + k < n; ++i)
      if (ans[0] == -1 ||
          sums[ans[0]] + sums[ans[1]] + sums[ans[2]] < sums[l[i - k]] + sums[i] + sums[r[i + k]]) {
        ans[0] = l[i - k];
        ans[1] = i;
        ans[2] = r[i + k];
      }

    return ans;
  }
}

class Solution {
 public:
  vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
    const int n = nums.size() - k + 1;
    // sums[i] := sum(nums[i..i + k))
    vector<int> sums(n);
    // l[i] := the index in [0..i] that has the maximum sums[i]
    vector<int> l(n);
    // r[i] := the index in [i..n) that has the maximum sums[i]
    vector<int> r(n);

    int sum = 0;
    for (int i = 0; i < nums.size(); ++i) {
      sum += nums[i];
      if (i >= k)
        sum -= nums[i - k];
      if (i >= k - 1)
        sums[i - k + 1] = sum;
    }

    int maxIndex = 0;
    for (int i = 0; i < n; ++i) {
      if (sums[i] > sums[maxIndex])
        maxIndex = i;
      l[i] = maxIndex;
    }

    maxIndex = n - 1;
    for (int i = n - 1; i >= 0; --i) {
      if (sums[i] >= sums[maxIndex])
        maxIndex = i;
      r[i] = maxIndex;
    }

    vector<int> ans{-1, -1, -1};

    for (int i = k; i < n - k; ++i)
      if (ans[0] == -1 || sums[ans[0]] + sums[ans[1]] + sums[ans[2]] <
                              sums[l[i - k]] + sums[i] + sums[r[i + k]]) {
        ans[0] = l[i - k];
        ans[1] = i;
        ans[2] = r[i + k];
      }

    return ans;
  }
};


We are given `n` different types of `stickers`. Each sticker has a lowercase
English word on it.

You would like to spell out the given string `target` by cutting individual
letters from your collection of stickers and rearranging them. You can use
each sticker more than once if you want, and you have infinite quantities of
each sticker.

Return the minimum number of stickers that you need to spell out `target`. If
the task is impossible, return `-1`.

Note: In all test cases, all words were chosen randomly from the `1000` most
common US English words, and `target` was chosen as a concatenation of two
random words.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minStickers(self, stickers: List[str], target: str) -> int:
    maxMask = 1 << len(target)
    dp = [math.inf] * maxMask
    dp[0] = 0

    for mask in range(maxMask):
      if dp[mask] == math.inf:
        continue
      for sticker in stickers:
        superMask = mask
        for c in sticker:
          for i, t in enumerate(target):
            if c == t and not (superMask >> i & 1):
              superMask |= 1 << i
              break
        dp[superMask] = min(dp[superMask], dp[mask] + 1)

    return -1 if dp[-1] == math.inf else dp[-1]

class Solution {
  public int minStickers(String[] stickers, String target) {
    final int n = target.length();
    final int maxMask = 1 << n;
    // dp[i] := the minimum number of stickers to spell out i, where i is the
    // bit mask of target
    int[] dp = new int[maxMask];
    Arrays.fill(dp, Integer.MAX_VALUE);
    dp[0] = 0;

    for (int mask = 0; mask < maxMask; ++mask) {
      if (dp[mask] == Integer.MAX_VALUE)
        continue;
      // Try to expand from `mask` by using each sticker.
      for (final String sticker : stickers) {
        int superMask = mask;
        for (final char c : sticker.toCharArray())
          for (int i = 0; i < n; ++i)
            // Try to apply it on a missing letter.
            if (c == target.charAt(i) && (superMask >> i & 1) == 0) {
              superMask |= 1 << i;
              break;
            }
        dp[superMask] = Math.min(dp[superMask], dp[mask] + 1);
      }
    }

    return dp[maxMask - 1] == Integer.MAX_VALUE ? -1 : dp[maxMask - 1];
  }
}

class Solution {
 public:
  int minStickers(vector<string>& stickers, string target) {
    const int n = target.size();
    const int maxMask = 1 << n;
    // dp[i] := the minimum number of stickers to spell out i, where i is the
    // bit mask of target
    vector<int> dp(maxMask, INT_MAX);
    dp[0] = 0;

    for (int mask = 0; mask < maxMask; ++mask) {
      if (dp[mask] == INT_MAX)
        continue;
      // Try to expand from `mask` by using each sticker.
      for (const string& sticker : stickers) {
        int superMask = mask;
        for (const char c : sticker)
          for (int i = 0; i < n; ++i)
            // Try to apply it on a missing letter.
            if (c == target[i] && (superMask >> i & 1) == 0) {
              superMask |= 1 << i;
              break;
            }
        dp[superMask] = min(dp[superMask], dp[mask] + 1);
      }
    }

    return dp.back() == INT_MAX ? -1 : dp.back();
  }
};


Given a C++ program, remove comments from it. The program source is an array
of strings `source` where `source[i]` is the `ith` line of the source code.
This represents the result of splitting the original source code string by the
newline character `'\n'`.

In C++, there are two types of comments, line comments, and block comments.

* The string `"//"` denotes a line comment, which represents that it and the rest of the characters to the right of it in the same line should be ignored.
* The string `"/*"` denotes a block comment, which represents that all characters until the next (non-overlapping) occurrence of `"*/"` should be ignored. (Here, occurrences happen in reading order: line by line from left to right.) To be clear, the string `"/*/"` does not yet end the block comment, as the ending would be overlapping the beginning.

The first effective comment takes precedence over others.

* For example, if the string `"//"` occurs in a block comment, it is ignored.
* Similarly, if the string `"/*"` occurs in a line or block comment, it is also ignored.

If a certain line of code is empty after removing comments, you must not
output that line: each string in the answer list will be non-empty.

There will be no control characters, single quote, or double quote characters.

* For example, `source = "string s = "/* Not a comment. */";"` will not be a test case.

Also, nothing else such as defines or macros will interfere with the comments.

It is guaranteed that every open block comment will eventually be closed, so
`"/*"` outside of a line or block comment always starts a new comment.

Finally, implicit newline characters can be deleted by block comments. Please
see the examples below for details.

After removing the comments from the source code, return the source code in
the same format.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def removeComments(self, source: List[str]) -> List[str]:
    ans = []
    commenting = False
    modified = ''

    for line in source:
      i = 0
      while i < len(line):
        if i + 1 == len(line):
          if not commenting:
            modified += line[i]
          i += 1
          break
        twoChars = line[i:i + 2]
        if twoChars == '/*' and not commenting:
          commenting = True
          i += 2
        elif twoChars == '*/' and commenting:
          commenting = False
          i += 2
        elif twoChars == '//':
          if not commenting:
            break
          else:
            i += 2
        else:
          if not commenting:
            modified += line[i]
          i += 1
      if modified and not commenting:
        ans.append(modified)
        modified = ''

    return ans

class Solution {
  public List<String> removeComments(String[] source) {
    List<String> ans = new ArrayList<>();
    boolean commenting = false;
    StringBuilder modified = new StringBuilder();

    for (final String line : source) {
      for (int i = 0; i < line.length();) {
        if (i + 1 == line.length()) {
          if (!commenting)
            modified.append(line.charAt(i));
          ++i;
          break;
        }
        String twoChars = line.substring(i, i + 2);
        if (twoChars.equals("/*") && !commenting) {
          commenting = true;
          i += 2;
        } else if (twoChars.equals("*/") && commenting) {
          commenting = false;
          i += 2;
        } else if (twoChars.equals("//")) {
          if (!commenting)
            break;
          else
            i += 2;
        } else {
          if (!commenting)
            modified.append(line.charAt(i));
          ++i;
        }
      }
      if (modified.length() > 0 && !commenting) {
        ans.add(modified.toString());
        modified.setLength(0);
      }
    }

    return ans;
  }
}

class Solution {
 public:
  vector<string> removeComments(vector<string>& source) {
    vector<string> ans;
    bool commenting = false;
    string modified;

    for (const string& line : source) {
      for (int i = 0; i < line.length();) {
        if (i + 1 == line.length()) {
          if (!commenting)
            modified += line[i];
          ++i;
          break;
        }
        const string& twoChars = line.substr(i, 2);
        if (twoChars == "/*" && !commenting) {
          commenting = true;
          i += 2;
        } else if (twoChars == "*/" && commenting) {
          commenting = false;
          i += 2;
        } else if (twoChars == "//") {
          if (!commenting)
            break;
          else
            i += 2;
        } else {
          if (!commenting)
            modified += line[i];
          ++i;
        }
      }
      if (modified.length() > 0 && !commenting) {
        ans.push_back(modified);
        modified = "";
      }
    }

    return ans;
  }
};


Count Different Palindromic Subsequences

Given a string s, return the number of different non-empty palindromic
subsequences in `s`. Since the answer may be very large, return it modulo `109
+ 7`.

A subsequence of a string is obtained by deleting zero or more characters from
the string.

A sequence is palindromic if it is equal to the sequence reversed.

Two sequences `a1, a2, ...` and `b1, b2, ...` are different if there is some
`i` for which `ai != bi`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def countPalindromicSubsequences(self, s: str) -> int:
    kMod = 1_000_000_007
    n = len(s)
    dp = [[0] * n for _ in range(n)]

    for i in range(n):
      dp[i][i] = 1

    for d in range(1, n):
      for i in range(n - d):
        j = i + d
        if s[i] == s[j]:
          lo = i + 1
          hi = j - 1
          while lo <= hi and s[lo] != s[i]:
            lo += 1
          while lo <= hi and s[hi] != s[i]:
            hi -= 1
          if lo > hi:
            dp[i][j] = dp[i + 1][j - 1] * 2 + 2
          elif lo == hi:
            dp[i][j] = dp[i + 1][j - 1] * 2 + 1
          else:
            dp[i][j] = dp[i + 1][j - 1] * 2 - dp[lo + 1][hi - 1]
        else:
          dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1]
        dp[i][j] = (dp[i][j] + kMod) % kMod

    return dp[0][n - 1]

class Solution {
  public int countPalindromicSubsequences(String s) {
    final int MOD = 1_000_000_007;
    final int n = s.length();
    // dp[i][j] := the number of different non-empty palindromic subsequences in
    // s[i..j]
    int[][] dp = new int[n][n];

    for (int i = 0; i < n; ++i)
      dp[i][i] = 1;

    for (int d = 1; d < n; ++d)
      for (int i = 0; i + d < n; ++i) {
        final int j = i + d;
        if (s.charAt(i) == s.charAt(j)) {
          int lo = i + 1;
          int hi = j - 1;
          while (lo <= hi && s.charAt(lo) != s.charAt(i))
            ++lo;
          while (lo <= hi && s.charAt(hi) != s.charAt(i))
            --hi;
          if (lo > hi)
            dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
          else if (lo == hi)
            dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
          else
            dp[i][j] = dp[i + 1][j - 1] * 2 - dp[lo + 1][hi - 1];
        } else {
          dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1];
        }
        dp[i][j] = (int) ((dp[i][j] + MOD) % MOD);
      }

    return dp[0][n - 1];
  }
}

class Solution {
 public:
  int countPalindromicSubsequences(string s) {
    constexpr int kMod = 1'000'000'007;
    const int n = s.length();
    // dp[i][j] := the number of different non-empty palindromic subsequences in
    // s[i..j]
    vector<vector<long>> dp(n, vector<long>(n));

    for (int i = 0; i < n; ++i)
      dp[i][i] = 1;

    for (int d = 1; d < n; ++d)
      for (int i = 0; i + d < n; ++i) {
        const int j = i + d;
        if (s[i] == s[j]) {
          int lo = i + 1;
          int hi = j - 1;
          while (lo <= hi && s[lo] != s[i])
            ++lo;
          while (lo <= hi && s[hi] != s[i])
            --hi;
          if (lo > hi)
            dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
          else if (lo == hi)
            dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
          else
            dp[i][j] = dp[i + 1][j - 1] * 2 - dp[lo + 1][hi - 1];
        } else {
          dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1];
        }
        dp[i][j] = (dp[i][j] + kMod) % kMod;
      }

    return dp[0][n - 1];
  }
};


We are given an array `asteroids` of integers representing asteroids in a row.

For each asteroid, the absolute value represents its size, and the sign
represents its direction (positive meaning right, negative meaning left). Each
asteroid moves at the same speed.

Find out the state of the asteroids after all collisions. If two asteroids
meet, the smaller one will explode. If both are the same size, both will
explode. Two asteroids moving in the same direction will never meet.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def asteroidCollision(self, asteroids: List[int]) -> List[int]:
    stack = []

    for a in asteroids:
      if a > 0:
        stack.append(a)
      else:
        while stack and stack[-1] > 0 and stack[-1] < -a:
          stack.pop()
        if not stack or stack[-1] < 0:
          stack.append(a)
        elif stack[-1] == -a:
          stack.pop()
        else:
          pass

    return stack

class Solution {
  public int[] asteroidCollision(int[] asteroids) {
    Stack<Integer> stack = new Stack<>();

    for (final int a : asteroids)
      if (a > 0) {
        stack.push(a);
      } else { // a < 0
        // Destroy the previous positive one(s).
        while (!stack.isEmpty() && stack.peek() > 0 && stack.peek() < -a)
          stack.pop();
        if (stack.isEmpty() || stack.peek() < 0)
          stack.push(a);
        else if (stack.peek() == -a)
          stack.pop(); // Both asteroids explode.
        else           // stack[-1] > the current asteroid.
          ;            // Destroy the current asteroid, so do nothing.
      }

    return stack.stream().mapToInt(Integer::intValue).toArray();
  }
}

class Solution {
 public:
  vector<int> asteroidCollision(vector<int>& asteroids) {
    vector<int> stack;

    for (const int a : asteroids)
      if (a > 0) {
        stack.push_back(a);
      } else {  // a < 0
        // Destroy the previous positive one(s).
        while (!stack.empty() && stack.back() > 0 && stack.back() < -a)
          stack.pop_back();
        if (stack.empty() || stack.back() < 0)
          stack.push_back(a);
        else if (stack.back() == -a)
          stack.pop_back();  // Both asteroids explode.
        else                 // stack[-1] > the current asteroid.
          ;                  // Destroy the current asteroid, so do nothing.
      }

    return stack;
  }
};


You are given a network of `n` nodes, labeled from `1` to `n`. You are also
given `times`, a list of travel times as directed edges `times[i] = (ui, vi,
wi)`, where `ui` is the source node, `vi` is the target node, and `wi` is the
time it takes for a signal to travel from source to target.

We will send a signal from a given node `k`. Return the minimum time it takes
for all the `n` nodes to receive the signal. If it is impossible for all the
`n` nodes to receive the signal, return `-1`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
    graph = [[] for _ in range(n)]

    for u, v, w in times:
      graph[u - 1].append((v - 1, w))

    return self._dijkstra(graph, k - 1)

  def _dijkstra(self, graph: List[List[Tuple[int, int]]], src: int) -> int:
    dist = [math.inf] * len(graph)

    dist[src] = 0
    minHeap = [(dist[src], src)]

    while minHeap:
      d, u = heapq.heappop(minHeap)
      if d > dist[u]:
        continue
      for v, w in graph[u]:
        if d + w < dist[v]:
          dist[v] = d + w
          heapq.heappush(minHeap, (dist[v], v))

    maxDist = max(dist)
    return maxDist if maxDist != math.inf else -1

class Solution {
  public int networkDelayTime(int[][] times, int n, int k) {
    List<Pair<Integer, Integer>>[] graph = new List[n];

    for (int i = 0; i < n; i++)
      graph[i] = new ArrayList<>();

    for (int[] time : times) {
      final int u = time[0] - 1;
      final int v = time[1] - 1;
      final int w = time[2];
      graph[u].add(new Pair<>(v, w));
    }

    return dijkstra(graph, k - 1);
  }

  private int dijkstra(List<Pair<Integer, Integer>>[] graph, int src) {
    int[] dist = new int[graph.length];
    Arrays.fill(dist, Integer.MAX_VALUE);

    dist[src] = 0;
    Queue<Pair<Integer, Integer>> minHeap =
        new PriorityQueue<>(Comparator.comparingInt(Pair::getKey)) {
          { offer(new Pair<>(dist[src], src)); } // (d, u)
        };

    while (!minHeap.isEmpty()) {
      final int d = minHeap.peek().getKey();
      final int u = minHeap.poll().getValue();
      if (d > dist[u])
        continue;
      for (Pair<Integer, Integer> pair : graph[u]) {
        final int v = pair.getKey();
        final int w = pair.getValue();
        if (d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.offer(new Pair<>(dist[v], v));
        }
      }
    }

    final int maxDist = Arrays.stream(dist).max().getAsInt();
    return maxDist == Integer.MAX_VALUE ? -1 : maxDist;
  }
}

class Solution {
 public:
  int networkDelayTime(vector<vector<int>>& times, int n, int k) {
    vector<vector<pair<int, int>>> graph(n);

    for (const vector<int>& time : times) {
      const int u = time[0] - 1;
      const int v = time[1] - 1;
      const int w = time[2];
      graph[u].emplace_back(v, w);
    }

    return dijkstra(graph, k - 1);
  }

 private:
  int dijkstra(const vector<vector<pair<int, int>>>& graph, int src) {
    vector<int> dist(graph.size(), INT_MAX);

    dist[src] = 0;
    using P = pair<int, int>;  // (d, u)
    priority_queue<P, vector<P>, greater<>> minHeap;
    minHeap.emplace(dist[src], src);

    while (!minHeap.empty()) {
      const auto [d, u] = minHeap.top();
      minHeap.pop();
      if (d > dist[u])
        continue;
      for (const auto& [v, w] : graph[u])
        if (d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.emplace(dist[v], v);
        }
    }

    const int maxDist = ranges::max(dist);
    return maxDist == INT_MAX ? -1 : maxDist;
  }
};


Given an expression such as `expression = "e + 8 - a + 5"` and an evaluation
map such as `{"e": 1}` (given in terms of `evalvars = ["e"]` and `evalints =
[1]`), return a list of tokens representing the simplified expression, such as
`["-1*a","14"]`

* An expression alternates chunks and symbols, with a space separating each chunk and symbol.
* A chunk is either an expression in parentheses, a variable, or a non-negative integer.
* A variable is a string of lowercase letters (not including digits.) Note that variables can be multiple letters, and note that variables never have a leading coefficient or unary operator like `"2x"` or `"-x"`.

Expressions are evaluated in the usual order: brackets first, then
multiplication, then addition and subtraction.

* For example, `expression = "1 + 2 * 3"` has an answer of `["7"]`.

The format of the output is as follows:

* For each term of free variables with a non-zero coefficient, we write the free variables within a term in sorted order lexicographically.
* For example, we would never write a term like `"b*a*c"`, only `"a*b*c"`.
* Terms have degrees equal to the number of free variables being multiplied, counting multiplicity. We write the largest degree terms of our answer first, breaking ties by lexicographic order ignoring the leading coefficient of the term.
* For example, `"a*a*b*c"` has degree `4`.
* The leading coefficient of the term is placed directly to the left with an asterisk separating it from the variables (if they exist.) A leading coefficient of 1 is still printed.
* An example of a well-formatted answer is `["-2*a*a*a", "3*a*a*b", "3*b*b", "4*a", "5*c", "-6"]`.
* Terms (including constant terms) with coefficient `0` are not included.
* For example, an expression of `"0"` has an output of `[]`.

Note: You may assume that the given expression is always valid. All
intermediate results will be in the range of `[-231, 231 - 1]`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Poly:
  def __init__(self, term: str = None, coef: int = None):
    if term and coef:
      self.terms = collections.Counter({term: coef})
    else:
      self.terms = collections.Counter()

  def __add__(self, other):
    for term, coef in other.terms.items():
      self.terms[term] += coef
    return self

  def __sub__(self, other):
    for term, coef in other.terms.items():
      self.terms[term] -= coef
    return self

  def __mul__(self, other):
    res = Poly()
    for a, aCoef in self.terms.items():
      for b, bCoef in other.terms.items():
        res.terms[self._merge(a, b)] += aCoef * bCoef
    return res

  def toList(self) -> List[str]:
    for term in list(self.terms.keys()):
      if not self.terms[term]:
        del self.terms[term]

    def cmp(term: str) -> tuple:
      if term == '1':
        return (0,)
      var = term.split('*')
      return (-len(var), term)

    def concat(term: str) -> str:
      if term == '1':
        return str(self.terms[term])
      return str(self.terms[term]) + '*' + term

    terms = list(self.terms.keys())
    terms.sort(key=cmp)
    return [concat(term) for term in terms]

  def _merge(self, a: str, b: str) -> str:
    if a == '1':
      return b
    if b == '1':
      return a
    res = []
    A = a.split('*')
    B = b.split('*')
    i = 0
    j = 0
    while i < len(A) and j < len(B):
      if A[i] < B[j]:
        res.append(A[i])
        i += 1
      else:
        res.append(B[j])
        j += 1
    return '*'.join(res + A[i:] + B[j:])

class Solution:
  def basicCalculatorIV(self, expression: str, evalvars: List[str], evalints: List[int]) -> List[str]:
    tokens = list(self._getTokens(expression))
    evalMap = {a: b for a, b in zip(evalvars, evalints)}

    for i, token in enumerate(tokens):
      if token in evalMap:
        tokens[i] = str(evalMap[token])

    postfix = self._infixToPostfix(tokens)
    return self._evaluate(postfix).toList()

  def _getTokens(self, s: str) -> Iterator[str]:
    i = 0
    for j, c in enumerate(s):
      if c == ' ':
        if i < j:
          yield s[i:j]
        i = j + 1
      elif c in '()+-*':
        if i < j:
          yield s[i:j]
        yield c
        i = j + 1
    if i < len(s):
      yield s[i:]

  def _infixToPostfix(self, tokens: List[str]) -> List[str]:
    postfix = []
    ops = []

    def precedes(prevOp: str, currOp: str) -> bool:
      if prevOp == '(':
        return False
      return prevOp == '*' or currOp in '+-'

    for token in tokens:
      if token == '(':
        ops.append(token)
      elif token == ')':
        while ops[-1] != '(':
          postfix.append(ops.pop())
        ops.pop()
      elif token in '+-*':
        while ops and precedes(ops[-1], token):
          postfix.append(ops.pop())
        ops.append(token)
      else:
        postfix.append(token)
    return postfix + ops[::-1]

  def _evaluate(self, postfix: List[str]) -> Poly:
    polys: List[Poly] = []
    for token in postfix:
      if token in '+-*':
        b = polys.pop()
        a = polys.pop()
        if token == '+':
          polys.append(a + b)
        elif token == '-':
          polys.append(a - b)
        else:
          polys.append(a * b)
      elif token.lstrip('-').isnumeric():
        polys.append(Poly("1", int(token)))
      else:
        polys.append(Poly(token, 1))
    return polys[0]

class Poly {
  public Poly add(Poly o) {
    for (final String term : o.terms.keySet())
      terms.merge(term, o.terms.get(term), Integer::sum);
    return this;
  }

  public Poly minus(Poly o) {
    for (final String term : o.terms.keySet())
      terms.merge(term, -o.terms.get(term), Integer::sum);
    return this;
  }

  public Poly mult(Poly o) {
    Poly res = new Poly();
    for (final String a : terms.keySet())
      for (final String b : o.terms.keySet())
        res.terms.merge(merge(a, b), terms.get(a) * o.terms.get(b), Integer::sum);
    return res;
  }

  // @Override
  // Public String toString() {
  //   StringBuilder sb = new StringBuilder();
  //   sb.append("{");
  //   for (final String term : terms.keySet())
  //     sb.append(term).append(": ").append(terms.get(term)).append(", ");
  //   sb.append("}");
  //   return sb.toString();
  // }

  public List<String> toList() {
    List<String> res = new ArrayList<>();
    List<String> keys = new ArrayList<>(terms.keySet());
    Collections.sort(keys, new Comparator<String>() {
      @Override
      public int compare(final String a, final String b) {
        // the minimum degree is the last
        if (a.equals("1"))
          return 1;
        if (b.equals("1"))
          return -1;
        String[] as = a.split("\\*");
        String[] bs = b.split("\\*");
        // the maximum degree is the first
        // Break ties by their lexicographic orders.
        return as.length == bs.length ? a.compareTo(b) : bs.length - as.length;
      }
    });
    for (final String key : keys)
      if (terms.get(key) != 0)
        res.add(concat(key));
    return res;
  }

  public Poly() {}
  public Poly(final String term, int coef) {
    terms.put(term, coef);
  }

  private Map<String, Integer> terms = new HashMap<>();

  // e.g. merge("a*b", "a*c") -> "a*a*b*c"
  private static String merge(final String a, final String b) {
    if (a.equals("1"))
      return b;
    if (b.equals("1"))
      return a;
    StringBuilder sb = new StringBuilder();
    String[] A = a.split("\\*");
    String[] B = b.split("\\*");
    int i = 0; // A's index
    int j = 0; // B's index
    while (i < A.length && j < B.length)
      if (A[i].compareTo(B[j]) < 0)
        sb.append("*").append(A[i++]);
      else
        sb.append("*").append(B[j++]);
    while (i < A.length)
      sb.append("*").append(A[i++]);
    while (j < B.length)
      sb.append("*").append(B[j++]);
    return sb.substring(1).toString();
  }

  private String concat(final String term) {
    if (term.equals("1"))
      return String.valueOf(terms.get(term));
    return new StringBuilder().append(terms.get(term)).append('*').append(term).toString();
  }
}

class Solution {
  public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
    List<String> tokens = getTokens(expression);
    Map<String, Integer> evalMap = new HashMap<>();

    for (int i = 0; i < evalvars.length; ++i)
      evalMap.put(evalvars[i], evalints[i]);

    for (int i = 0; i < tokens.size(); ++i)
      if (evalMap.containsKey(tokens.get(i)))
        tokens.set(i, String.valueOf(evalMap.get(tokens.get(i))));

    List<String> postfix = infixToPostfix(tokens);
    return evaluate(postfix).toList();
  }

  private List<String> getTokens(final String s) {
    List<String> tokens = new ArrayList<>();
    int i = 0;
    for (int j = 0; j < s.length(); ++j)
      if (s.charAt(j) == ' ') {
        if (i < j)
          tokens.add(s.substring(i, j));
        i = j + 1;
      } else if ("()+-*".contains(s.substring(j, j + 1))) {
        if (i < j)
          tokens.add(s.substring(i, j));
        tokens.add(s.substring(j, j + 1));
        i = j + 1;
      }
    if (i < s.length())
      tokens.add(s.substring(i));
    return tokens;
  }

  private boolean isOperator(final String token) {
    return token.equals("+") || token.equals("-") || token.equals("*");
  }

  private boolean precedes(final String prevOp, final String currOp) {
    if (prevOp.equals("("))
      return false;
    return prevOp.equals("*") || currOp.equals("+") || currOp.equals("-");
  }

  private List<String> infixToPostfix(List<String> tokens) {
    List<String> postfix = new ArrayList<>();
    Deque<String> ops = new ArrayDeque<>();

    for (final String token : tokens)
      if (token.equals("(")) {
        ops.push(token);
      } else if (token.equals(")")) {
        while (!ops.peek().equals("("))
          postfix.add(ops.pop());
        ops.pop();
      } else if (isOperator(token)) {
        while (!ops.isEmpty() && precedes(ops.peek(), token))
          postfix.add(ops.pop());
        ops.push(token);
      } else { // isOperand(token)
        postfix.add(token);
      }

    while (!ops.isEmpty())
      postfix.add(ops.pop());

    return postfix;
  }

  private Poly evaluate(List<String> postfix) {
    LinkedList<Poly> polys = new LinkedList<>();
    for (final String token : postfix)
      if (isOperator(token)) {
        final Poly b = polys.removeLast();
        final Poly a = polys.removeLast();
        if (token.equals("+"))
          polys.add(a.add(b));
        else if (token.equals("-"))
          polys.add(a.minus(b));
        else // token == "*"
          polys.add(a.mult(b));
      } else if (token.charAt(0) == '-' || token.chars().allMatch(c -> Character.isDigit(c))) {
        polys.add(new Poly("1", Integer.parseInt(token)));
      } else {
        polys.add(new Poly(token, 1));
      }
    return polys.getFirst();
  }
}

class Poly {
  friend Poly operator+(const Poly& lhs, const Poly& rhs) {
    Poly res(lhs);
    for (const auto& [term, coef] : rhs.terms)
      res.terms[term] += coef;
    return res;
  }

  friend Poly operator-(const Poly& lhs, const Poly& rhs) {
    Poly res(lhs);
    for (const auto& [term, coef] : rhs.terms)
      res.terms[term] -= coef;
    return res;
  }

  friend Poly operator*(const Poly& lhs, const Poly& rhs) {
    Poly res;
    for (const auto& [a, aCoef] : lhs.terms)
      for (const auto& [b, bCoef] : rhs.terms)
        res.terms[merge(a, b)] += aCoef * bCoef;
    return res;
  }

  // Friend ostream& operator<<(ostream& os, const Poly& poly) {
  //   os << "{";
  //   for (const auto& [term, coef] : poly.terms)
  //     os << term << ": " << coef << ", ";
  //   os << "}";
  //   return os;
  // }

 public:
  vector<string> toList() {
    vector<string> res;
    vector<string> keys;
    for (const auto& [term, _] : terms)
      keys.push_back(term);
    ranges::sort(keys, [&](const string& a, const string& b) {
      // the minimum degree is the last
      if (a == "1")
        return false;
      if (b == "1")
        return true;
      const vector<string> as = split(a, '*');
      const vector<string> bs = split(b, '*');
      // the maximum degree is the first
      // Break ties by their lexicographic orders.
      return as.size() == bs.size() ? a < b : as.size() > bs.size();
    });
    auto concat = [&](const string& term) -> string {
      if (term == "1")
        return to_string(terms[term]);
      return to_string(terms[term]) + '*' + term;
    };
    for (const string& key : keys)
      if (terms[key])
        res.push_back(concat(key));
    return res;
  }

  Poly() = default;
  Poly(const string& term, int coef) {
    terms[term] = coef;
  }

 private:
  unordered_map<string, int> terms;

  // e.g. merge("a*b", "a*c") -> "a*a*b*c"
  static string merge(const string& a, const string& b) {
    if (a == "1")
      return b;
    if (b == "1")
      return a;
    string res;
    vector<string> A = split(a, '*');
    vector<string> B = split(b, '*');
    int i = 0;  // A's index
    int j = 0;  // B's index
    while (i < A.size() && j < B.size())
      if (A[i] < B[j])
        res += '*' + A[i++];
      else
        res += '*' + B[j++];
    while (i < A.size())
      res += '*' + A[i++];
    while (j < B.size())
      res += '*' + B[j++];
    return res.substr(1);
  }

  static vector<string> split(const string& token, char c) {
    vector<string> vars;
    istringstream iss(token);
    for (string var; getline(iss, var, c);)
      vars.push_back(var);
    return vars;
  }
};

class Solution {
 public:
  vector<string> basicCalculatorIV(string expression, vector<string>& evalvars,
                                   vector<int>& evalints) {
    vector<string> tokens = getTokens(expression);
    unordered_map<string, int> evalMap;

    for (int i = 0; i < evalvars.size(); ++i)
      evalMap[evalvars[i]] = evalints[i];

    for (string& token : tokens)
      if (const auto it = evalMap.find(token); it != evalMap.cend())
        token = to_string(it->second);

    const vector<string>& postfix = infixToPostfix(tokens);
    return evaluate(postfix).toList();
  }

 private:
  vector<string> getTokens(const string& s) {
    vector<string> tokens;
    int i = 0;
    for (int j = 0; j < s.length(); ++j)
      if (s[j] == ' ') {
        if (i < j)
          tokens.push_back(s.substr(i, j - i));
        i = j + 1;
      } else if (string("()+-*").find(s[j]) != string::npos) {
        if (i < j)
          tokens.push_back(s.substr(i, j - i));
        tokens.push_back(s.substr(j, 1));
        i = j + 1;
      }
    if (i < s.length())
      tokens.push_back(s.substr(i));
    return tokens;
  }

  bool isOperator(const string& token) {
    return token == "+" || token == "-" || token == "*";
  }

  vector<string> infixToPostfix(const vector<string>& tokens) {
    vector<string> postfix;
    stack<string> ops;

    auto precedes = [](const string& prevOp, const string& currOp) -> bool {
      if (prevOp == "(")
        return false;
      return prevOp == "*" || currOp == "+" || currOp == "-";
    };

    for (const string& token : tokens)
      if (token == "(") {
        ops.push(token);
      } else if (token == ")") {
        while (ops.top() != "(")
          postfix.push_back(ops.top()), ops.pop();
        ops.pop();
      } else if (isOperator(token)) {
        while (!ops.empty() && precedes(ops.top(), token))
          postfix.push_back(ops.top()), ops.pop();
        ops.push(token);
      } else {  // isOperand(token)
        postfix.push_back(token);
      }

    while (!ops.empty())
      postfix.push_back(ops.top()), ops.pop();

    return postfix;
  }

  Poly evaluate(const vector<string>& postfix) {
    vector<Poly> polys;
    for (const string& token : postfix)
      if (isOperator(token)) {
        const Poly b = polys.back();
        polys.pop_back();
        const Poly a = polys.back();
        polys.pop_back();
        if (token == "+")
          polys.push_back(a + b);
        else if (token == "-")
          polys.push_back(a - b);
        else  // token == "*"
          polys.push_back(a * b);
      } else if (token[0] == '-' ||
                 ranges::all_of(token, [](char c) { return isdigit(c); })) {
        polys.push_back(Poly("1", stoi(token)));
      } else {
        polys.push_back(Poly(token, 1));
      }
    return polys[0];
  }
};


In a string composed of `'L'`, `'R'`, and `'X'` characters, like
`"RXXLRXRXL"`, a move consists of either replacing one occurrence of `"XL"`
with `"LX"`, or replacing one occurrence of `"RX"` with `"XR"`. Given the
starting string `start` and the ending string `end`, return `True` if and only
if there exists a sequence of moves to transform one string to the other.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def canTransform(self, start: str, end: str) -> bool:
    if start.replace('X', '') != end.replace('X', ''):
      return False

    i = 0
    j = 0

    while i < len(start) and j < len(end):
      while i < len(start) and start[i] == 'X':
        i += 1
      while j < len(end) and end[j] == 'X':
        j += 1
      if i == len(start) and j == len(end):
        return True
      if i == len(start) or j == len(end):
        return False
      if start[i] == 'L' and i < j:
        return False
      if start[i] == 'R' and i > j:
        return False
      i += 1
      j += 1

    return True

class Solution {
  public boolean canTransform(String start, String end) {
    if (!start.replace("X", "").equals(end.replace("X", "")))
      return false;

    int i = 0; // start's index
    int j = 0; // end's index

    while (i < start.length() && j < end.length()) {
      while (i < start.length() && start.charAt(i) == 'X')
        ++i;
      while (j < end.length() && end.charAt(j) == 'X')
        ++j;
      if (i == start.length() && j == end.length())
        return true;
      if (i == start.length() || j == end.length())
        return false;
      // L can only move to left.
      if (start.charAt(i) == 'L' && i < j)
        return false;
      // R can only move to right.
      if (start.charAt(i) == 'R' && i > j)
        return false;
      ++i;
      ++j;
    }

    return true;
  }
}

class Solution {
 public:
  bool canTransform(string start, string end) {
    if (removeX(start) != removeX(end))
      return false;

    int i = 0;  // start's index
    int j = 0;  // end's index

    while (i < start.length() && j < end.length()) {
      while (i < start.length() && start[i] == 'X')
        ++i;
      while (j < end.length() && end[j] == 'X')
        ++j;
      if (i == start.length() && j == end.length())
        return true;
      if (i == start.length() || j == end.length())
        return false;
      // L can only move to left.
      if (start[i] == 'L' && i < j)
        return false;
      // R can only move to right.
      if (start[i] == 'R' && i > j)
        return false;
      ++i;
      ++j;
    }

    return true;
  }

 private:
  string removeX(const string& s) {
    string t = s;
    std::erase(t, 'X');
    return t;
  }
};


You are given an `n x n` binary grid `board`. In each move, you can swap any
two rows with each other, or any two columns with each other.

Return the minimum number of moves to transform the board into a chessboard
board. If the task is impossible, return `-1`.

A chessboard board is a board where no `0`'s and no `1`'s are 4-directionally
adjacent.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def movesToChessboard(self, board: List[List[int]]) -> int:
    n = len(board)

    for i in range(n):
      for j in range(n):
        if board[0][0] ^ board[i][0] ^ board[0][j] ^ board[i][j]:
          return -1

    rowSum = sum(board[0])
    colSum = sum(board[i][0] for i in range(n))

    if rowSum != n // 2 and rowSum != (n + 1) // 2:
      return -1
    if colSum != n // 2 and colSum != (n + 1) // 2:
      return -1

    rowSwaps = sum(board[i][0] == (i & 1) for i in range(n))
    colSwaps = sum(board[0][i] == (i & 1) for i in range(n))

    if n & 1:
      if rowSwaps & 1:
        rowSwaps = n - rowSwaps
      if colSwaps & 1:
        colSwaps = n - colSwaps
    else:
      rowSwaps = min(rowSwaps, n - rowSwaps)
      colSwaps = min(colSwaps, n - colSwaps)

    return (rowSwaps + colSwaps) // 2

class Solution {
  public int movesToChessboard(int[][] board) {
    final int n = board.length;
    int rowSum = 0;
    int colSum = 0;
    int rowSwaps = 0;
    int colSwaps = 0;

    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        if ((board[0][0] ^ board[i][0] ^ board[0][j] ^ board[i][j]) == 1)
          return -1;

    for (int i = 0; i < n; ++i) {
      rowSum += board[0][i];
      colSum += board[i][0];
    }

    if (rowSum != n / 2 && rowSum != (n + 1) / 2)
      return -1;
    if (colSum != n / 2 && colSum != (n + 1) / 2)
      return -1;

    for (int i = 0; i < n; ++i) {
      if (board[i][0] == (i & 1))
        ++rowSwaps;
      if (board[0][i] == (i & 1))
        ++colSwaps;
    }

    if (n % 2 == 1) {
      if (rowSwaps % 2 == 1)
        rowSwaps = n - rowSwaps;
      if (colSwaps % 2 == 1)
        colSwaps = n - colSwaps;
    } else {
      rowSwaps = Math.min(rowSwaps, n - rowSwaps);
      colSwaps = Math.min(colSwaps, n - colSwaps);
    }

    return (rowSwaps + colSwaps) / 2;
  }
}

class Solution {
 public:
  int movesToChessboard(vector<vector<int>>& board) {
    const int n = board.size();
    int rowSum = 0;
    int colSum = 0;
    int rowSwaps = 0;
    int colSwaps = 0;

    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        if (board[0][0] ^ board[i][0] ^ board[0][j] ^ board[i][j] == 1)
          return -1;

    for (int i = 0; i < n; ++i) {
      rowSum += board[0][i];
      colSum += board[i][0];
    }

    if (rowSum != n / 2 && rowSum != (n + 1) / 2)
      return -1;
    if (colSum != n / 2 && colSum != (n + 1) / 2)
      return -1;

    for (int i = 0; i < n; ++i) {
      rowSwaps += board[i][0] == (i & 1);
      colSwaps += board[0][i] == (i & 1);
    }

    if (n % 2 == 1) {
      if (rowSwaps % 2 == 1)
        rowSwaps = n - rowSwaps;
      if (colSwaps % 2 == 1)
        colSwaps = n - colSwaps;
    } else {
      rowSwaps = min(rowSwaps, n - rowSwaps);
      colSwaps = min(colSwaps, n - colSwaps);
    }

    return (rowSwaps + colSwaps) / 2;
  }
};


You are given a sorted integer array `arr` containing `1` and prime numbers,
where all the integers of `arr` are unique. You are also given an integer `k`.

For every `i` and `j` where `0 <= i < j < arr.length`, we consider the
fraction `arr[i] / arr[j]`.

Return the `kth` smallest fraction considered. Return your answer as an array
of integers of size `2`, where `answer[0] == arr[i]` and `answer[1] ==
arr[j]`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def kthSmallestPrimeFraction(self, arr: List[int], k: int) -> List[int]:
    n = len(arr)
    ans = [0, 1]
    l = 0
    r = 1

    while True:
      m = (l + r) / 2
      ans[0] = 0
      count = 0
      j = 1

      for i in range(n):
        while j < n and arr[i] > m * arr[j]:
          j += 1
        count += n - j
        if j == n:
          break
        if ans[0] * arr[j] < ans[1] * arr[i]:
          ans[0] = arr[i]
          ans[1] = arr[j]

      if count < k:
        l = m
      elif count > k:
        r = m
      else:
        return ans

class Solution {
  public int[] kthSmallestPrimeFraction(int[] arr, int k) {
    final int n = arr.length;
    double l = 0.0;
    double r = 1.0;

    while (l < r) {
      final double m = (l + r) / 2.0;
      int fractionsNoGreaterThanM = 0;
      int p = 0;
      int q = 1;

      // For each index i, find the first index j s.t. arr[i] / arr[j] <= m,
      // so fractionsNoGreaterThanM for index i will be n - j.
      for (int i = 0, j = 1; i < n; ++i) {
        while (j < n && arr[i] > m * arr[j])
          ++j;
        if (j == n)
          break;
        fractionsNoGreaterThanM += n - j;
        if (p * arr[j] < q * arr[i]) {
          p = arr[i];
          q = arr[j];
        }
      }

      if (fractionsNoGreaterThanM == k)
        return new int[] {p, q};
      if (fractionsNoGreaterThanM > k)
        r = m;
      else
        l = m;
    }

    throw new IllegalArgumentException();
  }
}

class Solution {
 public:
  vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {
    const int n = arr.size();
    double l = 0.0;
    double r = 1.0;

    while (l < r) {
      const double m = (l + r) / 2.0;
      int fractionsNoGreaterThanM = 0;
      int p = 0;
      int q = 1;

      // For each index i, find the first index j s.t. arr[i] / arr[j] <= m,
      // so fractionsNoGreaterThanM for index i will be n - j.
      for (int i = 0, j = 1; i < n; ++i) {
        while (j < n && arr[i] > m * arr[j])
          ++j;
        if (j == n)
          break;
        fractionsNoGreaterThanM += n - j;
        if (p * arr[j] < q * arr[i]) {
          p = arr[i];
          q = arr[j];
        }
      }

      if (fractionsNoGreaterThanM == k)
        return {p, q};
      if (fractionsNoGreaterThanM > k)
        r = m;
      else
        l = m;
    }

    throw;
  }
};


There are `n` cities connected by some number of flights. You are given an
array `flights` where `flights[i] = [fromi, toi, pricei]` indicates that there
is a flight from city `fromi` to city `toi` with cost `pricei`.

You are also given three integers `src`, `dst`, and `k`, return the cheapest
price from `src` to `dst` with at most `k` stops. If there is no such route,
return `-1`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:
    graph = [[] for _ in range(n)]

    for u, v, w in flights:
      graph[u].append((v, w))

    return self._dijkstra(graph, src, dst, k)

  def _dijkstra(self, graph: List[List[Tuple[int, int]]], src: int, dst: int, k: int) -> int:
    dist=[]
    for i in range(len(graph)):
      dist.append([math.inf for _ in range(k + 2)])

    dist[src][k + 1] = 0
    minHeap = [(dist[src][k + 1], src, k + 1)]

    while minHeap:
      d, u, stops = heapq.heappop(minHeap)
      if u == dst:
        return d
      if stops == 0 or d > dist[u][stops]:
        continue
      for v, w in graph[u]:
        if d + w < dist[v][stops - 1]:
          dist[v][stops - 1] = d + w
          heapq.heappush(minHeap, (dist[v][stops - 1], v, stops - 1))

    return -1

class Solution {
  public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
    List<Pair<Integer, Integer>>[] graph = new List[n];

    for (int i = 0; i < n; i++)
      graph[i] = new ArrayList<>();

    for (int[] flight : flights) {
      final int u = flight[0];
      final int v = flight[1];
      final int w = flight[2];
      graph[u].add(new Pair<>(v, w));
    }

    return dijkstra(graph, src, dst, k);
  }

  private int dijkstra(List<Pair<Integer, Integer>>[] graph, int src, int dst, int k) {
    int[][] dist = new int[graph.length][k + 2];
    Arrays.stream(dist).forEach(A -> Arrays.fill(A, Integer.MAX_VALUE));

    dist[src][k + 1] = 0;
    Queue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0])) {
      { offer(new int[] {dist[src][k + 1], src, k + 1}); } // (d, u, stops)
    };

    while (!minHeap.isEmpty()) {
      final int d = minHeap.peek()[0];
      final int u = minHeap.peek()[1];
      final int stops = minHeap.poll()[2];
      if (u == dst)
        return d;
      if (stops == 0 || d > dist[u][stops])
        continue;
      for (Pair<Integer, Integer> pair : graph[u]) {
        final int v = pair.getKey();
        final int w = pair.getValue();
        if (d + w < dist[v][stops - 1]) {
          dist[v][stops - 1] = d + w;
          minHeap.offer(new int[] {dist[v][stops - 1], v, stops - 1});
        }
      }
    }

    return -1;
  }
}

class Solution {
 public:
  int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst,
                        int k) {
    vector<vector<pair<int, int>>> graph(n);

    for (const vector<int>& flight : flights) {
      const int u = flight[0];
      const int v = flight[1];
      const int w = flight[2];
      graph[u].emplace_back(v, w);
    }

    return dijkstra(graph, src, dst, k);
  }

 private:
  int dijkstra(const vector<vector<pair<int, int>>>& graph, int src, int dst,
               int k) {
    vector<vector<int>> dist(graph.size(), vector<int>(k + 2, INT_MAX));

    dist[src][k + 1] = 0;
    using T = tuple<int, int, int>;  // (d, u, stops)
    priority_queue<T, vector<T>, greater<>> minHeap;
    minHeap.emplace(dist[src][k + 1], src, k + 1);

    while (!minHeap.empty()) {
      const auto [d, u, stops] = minHeap.top();
      minHeap.pop();
      if (u == dst)
        return d;
      if (stops == 0 || d > dist[u][stops])
        continue;
      for (const auto& [v, w] : graph[u])
        if (d + w < dist[v][stops - 1]) {
          dist[v][stops - 1] = d + w;
          minHeap.emplace(dist[v][stops - 1], v, stops - 1);
        }
    }

    return -1;
  }
};


Given a Tic-Tac-Toe board as a string array `board`, return `true` if and only
if it is possible to reach this board position during the course of a valid
tic-tac-toe game.

The board is a `3 x 3` array that consists of characters `' '`, `'X'`, and
`'O'`. The `' '` character represents an empty square.

Here are the rules of Tic-Tac-Toe:

* Players take turns placing characters into empty squares `' '`.
* The first player always places `'X'` characters, while the second player always places `'O'` characters.
* `'X'` and `'O'` characters are always placed into empty squares, never filled ones.
* The game ends when there are three of the same (non-empty) character filling any row, column, or diagonal.
* The game also ends if all squares are non-empty.
* No more moves can be played if the game is over.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def validTicTacToe(self, board: List[str]) -> bool:
    def isWin(c: str) -> bool:
      return any(row.count(c) == 3 for row in board) or any(row.count(c) == 3 for row in list(zip(*board))) or all(board[i][i] == c for i in range(3)) or all(board[i][2 - i] == c for i in range(3))

    countX = sum(row.count('X') for row in board)
    countO = sum(row.count('O') for row in board)

    if countX < countO or countX - countO > 1:
      return False
    if isWin('X') and countX == countO or isWin('O') and countX != countO:
      return False

    return True

class Solution {
  public boolean validTicTacToe(String[] board) {
    final int countX = sum(board, 'X');
    final int countO = sum(board, 'O');

    if (countX < countO || countX - countO > 1)
      return false;
    if (isWinned(board, 'X') && countX == countO || //
        isWinned(board, 'O') && countX != countO)
      return false;

    return true;
  }

  private int sum(final String[] board, char c) {
    int ans = 0;

    for (final String row : board)
      ans += row.chars().filter(i -> i == c).count();

    return ans;
  }

  private boolean isWinned(final String[] board, char c) {
    String[] rotated = rotate(board);

    return Arrays.stream(board).anyMatch(row -> row.chars().filter(i -> i == c).count() == 3) ||
        Arrays.stream(rotated).anyMatch(row -> row.chars().filter(i -> i == c).count() == 3) ||
        board[0].charAt(0) == c && board[1].charAt(1) == c && board[2].charAt(2) == c ||
        board[0].charAt(2) == c && board[1].charAt(1) == c && board[2].charAt(0) == c;
  }

  private String[] rotate(final String[] board) {
    String[] rotated = new String[3];

    for (final String row : board)
      for (int i = 0; i < 3; ++i)
        rotated[i] += row.charAt(i);

    return rotated;
  }
}

class Solution {
 public:
  bool validTicTacToe(vector<string>& board) {
    const int countX = sum(board, 'X');
    const int countO = sum(board, 'O');

    if (countX < countO || countX - countO > 1)
      return false;
    if (isWinned(board, 'X') && countX == countO ||
        isWinned(board, 'O') && countX != countO)
      return false;

    return true;
  }

 private:
  int sum(const vector<string>& board, char c) {
    int ans = 0;

    for (const string& row : board)
      ans += ranges::count(row, c);

    return ans;
  }

  bool isWinned(const vector<string>& board, char c) {
    vector<string> rotated = rotate(board);

    auto equalsToThree = [&c](const string& row) {
      return ranges::count(row, c) == 3;
    };

    return ranges::any_of(board, equalsToThree) ||
           ranges::any_of(rotated, equalsToThree) ||
           board[0][0] == c && board[1][1] == c && board[2][2] == c ||
           board[0][2] == c && board[1][1] == c && board[2][0] == c;
  }

  vector<string> rotate(const vector<string>& board) {
    vector<string> rotated(3);

    for (const string& row : board)
      for (int i = 0; i < 3; ++i)
        rotated[i].push_back(row[i]);

    return rotated;
  }
};


You are given an integer array `nums`.

You should move each element of `nums` into one of the two arrays `A` and `B`
such that `A` and `B` are non-empty, and `average(A) == average(B)`.

Return `true` if it is possible to achieve that and `false` otherwise.

Note that for an array `arr`, `average(arr)` is the sum of all the elements of
`arr` over the length of `arr`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def splitArraySameAverage(self, nums: List[int]) -> bool:
    n = len(nums)
    summ = sum(nums)
    if not any(i * summ % n == 0 for i in range(1, n // 2 + 1)):
      return False

    sums = [set() for _ in range(n // 2 + 1)]
    sums[0].add(0)

    for num in nums:
      for i in range(n // 2, 0, -1):
        for val in sums[i - 1]:
          sums[i].add(num + val)

    for i in range(1, n // 2 + 1):
      if i * summ % n == 0 and i * summ // n in sums[i]:
        return True

    return False

class Solution {
  public boolean splitArraySameAverage(int[] nums) {
    final int n = nums.length;
    final int sum = Arrays.stream(nums).sum();
    if (!isPossible(sum, n))
      return false;

    List<Set<Integer>> sums = new ArrayList<>();

    for (int i = 0; i < n / 2 + 1; ++i)
      sums.add(new HashSet<>());
    sums.get(0).add(0);

    for (final int num : nums)
      for (int i = n / 2; i > 0; --i)
        for (final int val : sums.get(i - 1))
          sums.get(i).add(num + val);

    for (int i = 1; i < n / 2 + 1; ++i)
      if (i * sum % n == 0 && sums.get(i).contains(i * sum / n))
        return true;

    return false;
  }

  private boolean isPossible(int sum, int n) {
    for (int i = 1; i < n / 2 + 1; ++i)
      if (i * sum % n == 0)
        return true;
    return false;
  }
}

class Solution {
 public:
  bool splitArraySameAverage(vector<int>& nums) {
    const int n = nums.size();
    const int sum = accumulate(nums.begin(), nums.end(), 0);
    if (!isPossible(sum, n))
      return false;

    vector<unordered_set<int>> sums(n / 2 + 1);
    sums[0].insert(0);

    for (const int num : nums)
      for (int i = n / 2; i > 0; --i)
        for (const int val : sums[i - 1])
          sums[i].insert(num + val);

    for (int i = 1; i < n / 2 + 1; ++i)
      if (i * sum % n == 0 && sums[i].contains(i * sum / n))
        return true;

    return false;
  }

 private:
  bool isPossible(int sum, int n) {
    for (int i = 1; i < n / 2 + 1; ++i)
      if (i * sum % n == 0)
        return true;
    return false;
  }
};


You are given an array `routes` representing bus routes where `routes[i]` is a
bus route that the `ith` bus repeats forever.

* For example, if `routes[0] = [1, 5, 7]`, this means that the `0th` bus travels in the sequence `1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ...` forever.

You will start at the bus stop `source` (You are not on any bus initially),
and you want to go to the bus stop `target`. You can travel between bus stops
by buses only.

Return the least number of buses you must take to travel from `source` to
`target`. Return `-1` if it is not possible.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
    if source == target:
      return 0

    graph = collections.defaultdict(list)
    usedBuses = set()

    for i in range(len(routes)):
      for route in routes[i]:
        graph[route].append(i)

    ans = 0
    q = collections.deque([source])

    while q:
      ans += 1
      for _ in range(len(q)):
        for bus in graph[q.popleft()]:
          if bus in usedBuses:
            continue
          usedBuses.add(bus)
          for nextRoute in routes[bus]:
            if nextRoute == target:
              return ans
            q.append(nextRoute)

    return -1

class Solution {
  public int numBusesToDestination(int[][] routes, int source, int target) {
    if (source == target)
      return 0;

    Map<Integer, List<Integer>> graph = new HashMap<>(); // {route: [buses]}
    Set<Integer> usedBuses = new HashSet<>();

    for (int i = 0; i < routes.length; ++i)
      for (final int route : routes[i]) {
        graph.putIfAbsent(route, new ArrayList<>());
        graph.get(route).add(i);
      }

    Queue<Integer> q = new ArrayDeque<>(List.of(source));

    for (int step = 1; !q.isEmpty(); ++step)
      for (int sz = q.size(); sz > 0; --sz) {
        for (final int bus : graph.getOrDefault(q.poll(), new ArrayList<>()))
          if (usedBuses.add(bus))
            for (final int nextRoute : routes[bus]) {
              if (nextRoute == target)
                return step;
              q.offer(nextRoute);
            }
      }

    return -1;
  }
}

class Solution {
 public:
  int numBusesToDestination(vector<vector<int>>& routes, int source,
                            int target) {
    if (source == target)
      return 0;

    unordered_map<int, vector<int>> graph;  // {route: [buses]}
    unordered_set<int> usedBuses;

    for (int i = 0; i < routes.size(); ++i)
      for (const int route : routes[i])
        graph[route].push_back(i);

    queue<int> q{{source}};

    for (int step = 1; !q.empty(); ++step)
      for (int sz = q.size(); sz > 0; --sz) {
        const int route = q.front();
        q.pop();
        for (const int bus : graph[route])
          if (usedBuses.insert(bus).second)
            for (const int nextRoute : routes[bus]) {
              if (nextRoute == target)
                return step;
              q.push(nextRoute);
            }
      }

    return -1;
  }
};


There are `n` dominoes in a line, and we place each domino vertically upright.
In the beginning, we simultaneously push some of the dominoes either to the
left or to the right.

After each second, each domino that is falling to the left pushes the adjacent
domino on the left. Similarly, the dominoes falling to the right push their
adjacent dominoes standing on the right.

When a vertical domino has dominoes falling on it from both sides, it stays
still due to the balance of the forces.

For the purposes of this question, we will consider that a falling domino
expends no additional force to a falling or already fallen domino.

You are given a string `dominoes` representing the initial state where:

* `dominoes[i] = 'L'`, if the `ith` domino has been pushed to the left,
* `dominoes[i] = 'R'`, if the `ith` domino has been pushed to the right, and
* `dominoes[i] = '.'`, if the `ith` domino has not been pushed.

Return a string representing the final state.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def pushDominoes(self, dominoes: str) -> str:
    ans = list(dominoes)
    L = -1
    R = -1

    for i in range(len(dominoes) + 1):
      if i == len(dominoes) or dominoes[i] == 'R':
        if L < R:
          while R < i:
            ans[R] = 'R'
            R += 1
        R = i
      elif dominoes[i] == 'L':
        if R < L or (L, R) == (-1, -1):
          if (L, R) == (-1, -1):
            L += 1
          while L < i:
            ans[L] = 'L'
            L += 1
        else:
          l = R + 1
          r = i - 1
          while l < r:
            ans[l] = 'R'
            ans[r] = 'L'
            l += 1
            r -= 1
        L = i

    return ''.join(ans)

class Solution {
  public String pushDominoes(String dominoes) {
    char[] s = dominoes.toCharArray();
    int L = -1;
    int R = -1;

    for (int i = 0; i <= dominoes.length(); ++i)
      if (i == dominoes.length() || s[i] == 'R') {
        if (L < R)
          while (R < i)
            s[R++] = 'R';
        R = i;
      } else if (s[i] == 'L') {
        if (R < L || L == -1 && R == -1) {
          if (L == -1 && R == -1)
            ++L;
          while (L < i)
            s[L++] = 'L';
        } else {
          int l = R + 1;
          int r = i - 1;
          while (l < r) {
            s[l++] = 'R';
            s[r--] = 'L';
          }
        }
        L = i;
      }

    return new String(s);
  }
}

class Solution {
 public:
  string pushDominoes(string dominoes) {
    int L = -1;
    int R = -1;

    for (int i = 0; i <= dominoes.length(); ++i)
      if (i == dominoes.length() || dominoes[i] == 'R') {
        if (L < R)
          while (R < i)
            dominoes[R++] = 'R';
        R = i;
      } else if (dominoes[i] == 'L') {
        if (R < L || L == -1 && R == -1) {
          if (L == -1 && R == -1)
            ++L;
          while (L < i)
            dominoes[L++] = 'L';
        } else {
          int l = R + 1;
          int r = i - 1;
          while (l < r) {
            dominoes[l++] = 'R';
            dominoes[r--] = 'L';
          }
        }
        L = i;
      }

    return dominoes;
  }
};


You may recall that an array `arr` is a mountain array if and only if:

* `arr.length >= 3`
* There exists some index `i` (0-indexed) with `0 < i < arr.length - 1` such that:
* `arr[0] < arr[1] < ... < arr[i - 1] < arr[i]`
* `arr[i] > arr[i + 1] > ... > arr[arr.length - 1]`

Given an integer array `arr`, return the length of the longest subarray, which
is a mountain. Return `0` if there is no mountain subarray.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def longestMountain(self, arr: List[int]) -> int:
    ans = 0
    i = 0

    while i + 1 < len(arr):
      while i + 1 < len(arr) and arr[i] == arr[i + 1]:
        i += 1

      increasing = 0
      decreasing = 0

      while i + 1 < len(arr) and arr[i] < arr[i + 1]:
        increasing += 1
        i += 1

      while i + 1 < len(arr) and arr[i] > arr[i + 1]:
        decreasing += 1
        i += 1

      if increasing > 0 and decreasing > 0:
        ans = max(ans, increasing + decreasing + 1)

    return ans

class Solution {
  public int longestMountain(int[] arr) {
    int ans = 0;

    for (int i = 0; i + 1 < arr.length;) {
      while (i + 1 < arr.length && arr[i] == arr[i + 1])
        ++i;

      int increasing = 0;
      int decreasing = 0;

      while (i + 1 < arr.length && arr[i] < arr[i + 1]) {
        ++increasing;
        ++i;
      }

      while (i + 1 < arr.length && arr[i] > arr[i + 1]) {
        ++decreasing;
        ++i;
      }

      if (increasing > 0 && decreasing > 0)
        ans = Math.max(ans, increasing + decreasing + 1);
    }

    return ans;
  }
}

class Solution {
 public:
  int longestMountain(vector<int>& arr) {
    int ans = 0;

    for (int i = 0; i + 1 < arr.size();) {
      while (i + 1 < arr.size() && arr[i] == arr[i + 1])
        ++i;

      int increasing = 0;
      int decreasing = 0;

      while (i + 1 < arr.size() && arr[i] < arr[i + 1]) {
        ++increasing;
        ++i;
      }

      while (i + 1 < arr.size() && arr[i] > arr[i + 1]) {
        ++decreasing;
        ++i;
      }

      if (increasing > 0 && decreasing > 0)
        ans = max(ans, increasing + decreasing + 1);
    }

    return ans;
  }
};