// Leetcode 394. Decode string
string Repeat(const string& str, const int num) {
if (num == 1) return str;
if (!num) return "";
const auto str_half = Repeat(str, num/2);
return str_half + str_half + (num&1?str:"");
}
string decodeString(string s, const int stt = 0) {
string ans;
int num = 0;
for (int i = stt; i < s.size(); ++i) {
if (s[i] >= 'a' && s[i] <= 'z') {
ans += s[i];
} else if (s[i] >= '0' && s[i] <= '9') {
num = num * 10 + s[i] - '0';
} else if (s[i] == '[') {
int cnt = 1;
const int left = i;
while (cnt) {
++i;
if (s[i] == ']')
--cnt;
if (s[i] == '[')
++cnt;
}
const string new_str = decodeString(s.substr(left+1, i - left - 1));
ans += Repeat(new_str, num);
num = 0;
}
}
return ans;
}
// Leetcode 366. Find Leaves of Binary Tree
int CollectLeaves(const TreeNode* root, vector<vector<int>>& ans) {
if (!root) return -1;
const int left = CollectLeaves(root->left, ans);
const int right = CollectLeaves(root->right, ans);
const int level = max(left, right) + 1;
if (ans.size() <= level)
ans.push_back({});
ans[level].push_back(root->val);
return level;
}
// Leetcode 243. shortest word distance
int shortestDistance(vector<string>& words, string word1, string word2) {
int idx1 = -1;
int idx2 = -1;
int fin_dis = INT_MAX;
for (int idx = 0; idx < words.size(); ++idx) {
if (words[idx] == word1) {
idx1 = idx;
}
if (words[idx] == word2) {
idx2 = idx;
}
if (idx1!=-1 && idx2!=-1) {
fin_dis = min(fin_dis, abs(idx1-idx2));
}
}
return fin_dis;
}
// Leetcode 23 Merge k Sorted Lists
// with priority_queue/divide conquer
ListNode* MergeLists(vector<ListNode*>& lists, const int stt, const int fin) {
if (stt == fin) return lists[stt];
if (stt > fin) return nullptr;
ListNode* left = MergeLists(lists, stt, stt + (fin - stt) / 2);
ListNode* right = MergeLists(lists, stt + (fin - stt) / 2 + 1, fin);
ListNode* root = new ListNode(0);
ListNode* cur = root;
while (left && right) {
if (left->val <= right->val) {
cur->next = left;
left = left->next;
} else {
cur->next = right;
right = right->next;
}
cur = cur->next;
}
if (left) {
cur->next = left;
}
if (right) {
cur->next = right;
}
return root->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
return MergeLists(lists, 0, lists.size()-1);
}
// Leetcode 470. Implement Rand10() using Rand7(). Random number generator from other random generator
int rand10() {
int result = 40;
while (true) {
const int cur = (rand7() - 1) * 7 + (rand7() - 1);
if (cur < result) {
result = cur;
break;
}
}
return result % 10 + 1;
}
// Generate methods:
// Implement randM() using randN() when M > N:
// Step 1: Use randN() to generate randX(), where X >= M. In this problem, I use 7 * (rand7() - 1) + (rand7() - 1) to generate rand49() - 1.
// Step 2: Use randX() to generate randM(). In this problem, I use rand49() to generate rand40() then generate rand10.
// Note: N^b * (randN() - 1) + N^(b - 1) * (randN() - 1) + N^(b - 2) * (randN() - 1) + ... + N^0 * (randN() - 1) generates randX() - 1, where X = N^(b + 1).
// More Examples
// (1) Implement rand11() using rand3():
public int rand11() {
int result = 22;
while (result >= 22) {result = 3 * 3 * (rand3() - 1) + 3 * (rand3() - 1) + (rand3() - 1);}
return result % 11 + 1;
}
// Idea: rand3() -> rand27() -> rand22 -> rand11
// Time Comlexity: O(27/22)
// (2) Implement rand9() using rand7():
public int rand9() {
int result = 45;
while (result >= 45) {result = 7 * (rand7() - 1) + (rand7() - 1);}
return result % 9 + 1;
}
// Idea: rand7() -> rand49() -> rand45() -> rand9()
// Time Comlexity: O(49/45)
// (3) Implement rand13() using rand6():
public int rand13() {
int result = 26;
while (result >= 26) {result = 6 * (rand6() - 1) + (rand6() - 1);}
return result % 13 + 1;
}
// Idea: rand6() -> rand36() -> rand26 -> rand13()
// Time Comlexity: O(36/26)
// Course schedule/how to decide only one schedule(if no cycle, only | E | = | V | - 1
// 207. Course Schedule
bool DFS(const int i, vector<int>& visited,
unordered_map<int, vector<int>>& graph) {
if (visited[i] == 2) return true;
visited[i] = 1;
for (const auto& node : graph[i]) {
if (visited[node] == 1)
return false;
const bool res = DFS(node, visited, graph);
if (!res) return res;
}
visited[i] = 2;
return true;
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
unordered_map<int, vector<int>> graph;
vector<int> visited(numCourses + 1, 0);
for (const auto& pre : prerequisites) {
graph[pre[0]].emplace_back(pre[1]);
}
for (int i = 0; i < numCourses; ++i) {
if (!visited[i]) {
const bool res = DFS(i, visited, graph);
if (!res)
return res;
}
}
return true;
}
// 210. Course Schedule II
// Method 1: topological sort
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
unordered_map<int, vector<int>> graph;
vector<int> indegrees(numCourses + 1, 0);
for (const auto& pre : prerequisites) {
graph[pre[1]].emplace_back(pre[0]);
++indegrees[pre[0]];
}
vector<int> ans;
queue<int> que;
for (int i = 0; i < numCourses; ++i) {
if (!indegrees[i]) {
ans.push_back(i);
que.push(i);
}
}
while (!que.empty()) {
const int tp = que.front();
que.pop();
for (const auto& node : graph[tp]) {
--indegrees[node];
if (!indegrees[node]) {
ans.push_back(node);
que.push(node);
}
}
}
return ans.size() == numCourses? ans : vector<int>();
}
// Method 2: DFS
bool DFS(unordered_map<int, vector<int>>& graph, const int i, stack<int>& record,
vector<int>& visited) {
if (visited[i] == 2) return true;
visited[i] = 1;
for (const auto& n : graph[i]) {
if (visited[n] == 1) return false;
if (!DFS(graph, n, record, visited))
return false;
}
visited[i] = 2;
record.push(i);
return true;
}
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
stack<int> record;
unordered_map<int, vector<int>> graph;
vector<int> visited(numCourses + 1, 0);
for (const auto& pre : prerequisites) {
graph[pre[0]].emplace_back(pre[1]);
}
for (int i = 0; i < numCourses; ++i) {
if (!visited[i]) {
if (!DFS(graph, i, record, visited)) {
return {};
}
}
}
vector<int> ans;
while (!record.empty()) {
ans.emplace_back(record.top());
record.pop();
}
reverse(begin(ans), end(ans));
return ans;
}
// 630. Course Schedule III*
int scheduleCourse(vector<vector<int>>& courses) {
sort(begin(courses), end(courses), [](const vector<int>& v1,
const vector<int>& v2) {
return v1[1] < v2[1];
});
int res = 0;
priority_queue<int> heap;
for (const auto& c : courses) {
res += c[0];
heap.push(c[0]);
if (res > c[1]) {
res -= heap.top();
heap.pop();
}
}
return heap.size();
}
// 1462. Course Schedule IV
vector<bool> checkIfPrerequisite(int numCourses, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
vector<vector<bool>> path(numCourses+1, vector<bool>(numCourses+1, false));
for (const auto& p : prerequisites) {
path[p[0]][p[1]] = true;
}
for (int i = 0; i < numCourses; ++i) {
path[i][i] = true;
}
for (int k = 0; k < numCourses; ++k) {
for (int i = 0; i < numCourses; ++i) {
for (int j = 0; j < numCourses; ++j) {
path[i][j] = path[i][j] || (path[i][k] && path[k][j]);
}
}
}
vector<bool> res;
for (const auto& q : queries) {
res.push_back(path[q[0]][q[1]]);
}
return res;
}
// 373(多路归并)
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
if (nums1.empty() || nums2.empty()) return {};
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> heap;
for (int i = 0; i < nums2.size(); ++i) {
heap.push({nums2[i] + nums1[0], i, 0});
}
vector<vector<int>> res;
while (k-- && heap.size()) {
const auto tp = heap.top();
res.push_back({nums1[tp[2]], nums2[tp[1]]});
heap.pop();
if (tp[2] + 1< nums1.size()) {
heap.push({nums2[tp[1]] + nums1[tp[2]+1], tp[1], tp[2]+1});
}
}
return res;
}
// 1439. Find the Kth Smallest Sum of a Matrix With Sorted Rows
// https://leetcode-cn.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/solution/bao-li-jie-fa-zui-xiao-dui-by-coldme-2/
// Google onsite Compress 2D array
// https://leetcode.com/discuss/interview-question/326564/Google-or-Onsite-interview-or-Compress-2D-Array/302395
// 1. Reserve all the orders
// flatten the whole array matrix
// sort the array, assume we get arr[i], i=0,n-1
// build the reverse map of arr[i]->i+1
// traverse the matrix and replace the value using the reversed map
// *2. Leetcode 1632. Rank Transform of a matrix
int Find(int idx, vector<int>& p) {
if (idx != p[idx]) {
p[idx] = Find(p[idx], p);
}
return p[idx];
}
vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) {
int rows = matrix.size();
int cols = rows?matrix[0].size() : 0;
map<int, vector<int>> points;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
points[matrix[i][j]].push_back(i * cols + j);
}
}
vector<int> rank(rows + cols, 0);
for (const auto& pts : points) {
vector<int> p(rows + cols, 0);
iota(p.begin(), p.end(), 0);
for (const auto& pt : pts.second) {
const int i = Find(pt / cols, p);
const int j = Find(pt % cols + rows, p);
p[j] = i;
rank[i] = max({rank[j], rank[i]});
}
for (const auto& pt : pts.second) {
const auto &cur_rank = Find(pt/cols, p);
matrix[pt/cols][pt%cols] = rank[cur_rank] + 1;
rank[pt/cols] = rank[cur_rank] + 1;
rank[pt%cols + rows] = rank[cur_rank] + 1;
}
}
return matrix;
}
// Merge binary search tree
// https://www.geeksforgeeks.org/merge-two-bsts-with-limited-extra-space/
/* A utility function to print Inoder traversal of a Binary Tree */
void inorder(node *root) {
if (root != NULL) {
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
}
// The function to print data of two BSTs in sorted order
void merge(node *root1, node *root2) {
// s1 is stack to hold nodes of first BST
snode *s1 = NULL;
// Current node of first BST
node *current1 = root1;
// s2 is stack to hold nodes of second BST
snode *s2 = NULL;
// Current node of second BST
node *current2 = root2;
// If first BST is empty, then output is inorder
// traversal of second BST
if (root1 == NULL) {
inorder(root2);
return;
}
// If second BST is empty, then output is inorder
// traversal of first BST
if (root2 == NULL) {
inorder(root1);
return ;
}
// Run the loop while there are nodes not yet printed.
// The nodes may be in stack(explored, but not printed)
// or may be not yet explored
while (current1 != NULL || !isEmpty(s1) ||
current2 != NULL || !isEmpty(s2)) {
// Following steps follow iterative Inorder Traversal
if (current1 != NULL || current2 != NULL ) {
// Reach the leftmost node of both BSTs and push ancestors of
// leftmost nodes to stack s1 and s2 respectively
if (current1 != NULL) {
push(&s1, current1);
current1 = current1->left;
}
if (current2 != NULL) {
push(&s2, current2);
current2 = current2->left;
}
}
else {
// If we reach a NULL node and either of the stacks is empty,
// then one tree is exhausted, ptint the other tree
if (isEmpty(s1)) {
while (!isEmpty(s2)) {
current2 = pop (&s2);
current2->left = NULL;
inorder(current2);
}
return ;
}
if (isEmpty(s2)) {
while (!isEmpty(s1)) {
current1 = pop (&s1);
current1->left = NULL;
inorder(current1);
}
return ;
}
// Pop an element from both stacks and compare the
// popped elements
current1 = pop(&s1);
current2 = pop(&s2);
// If element of first tree is smaller, then print it
// and push the right subtree. If the element is larger,
// then we push it back to the corresponding stack.
if (current1->data < current2->data) {
cout<<current1->data<<" ";
current1 = current1->right;
push(&s2, current2);
current2 = NULL;
}
else {
cout<<current2->data<<" ";
current2 = current2->right;
push(&s1, current1);
current1 = NULL;
}
}
}
}
// 617. Merge Two Binary Trees
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(!t1)
return t2;
if(!t2)
return t1;
int val1 = t1?t1->val:0;
int val2 = t2?t2->val:0;
TreeNode* root = t1?t1:t2;
root->val = val1+val2;
root->left = mergeTrees(t1?t1->left:NULL, t2?t2->left:NULL);
root->right = mergeTrees(t1?t1->right:NULL, t2?t2->right:NULL);
return root;
}
// Queue: 907. Sum of Subarray Minimums;
// 416. separate one array into two, make the sum of difference the smallest;
// 1239. Maximum Length of a Concatenated String with Unique Characters;
// https://leetcode.com/problems/remove-k-digits/
// 1293. Shortest Path in a Grid with Obstacles Elimination
// 815. Bus Routes
int numBusesToDestination(vector<vector<int>>& routes, int S, int T) {
assert(routes.size() && routes[0].size() );
unordered_map<int, unordered_set<int>> rec;
for(int s1 = 0; s1<routes.size(); s1++) {
for(int s2 = 0; s2<routes[s1].size(); s2++)
rec[routes[s1][s2]].insert(s1);
}
// stop->count
queue<pair<int,int>> que;
que.push(make_pair(S, 0));
unordered_set<int> visited;
while(!que.empty()) {
int stop = que.front().first;
int num = que.front().second;
que.pop();
if(T==stop)
return num;
for(auto route:rec[stop]) {
for(auto bus:routes[route]) {
if(visited.find(bus)==visited.end()) {
visited.insert(bus);
que.push(make_pair(bus, num+1));
}
}
routes[route].clear();
}
}
return -1;
}
// 863. All Nodes Distance K in Binary Tree
vector<int> answer;
vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
answer.clear();
getDistance(root, target, K);
return answer;
}
int getDistance(TreeNode* root, TreeNode* target, int K) {
if (root == nullptr) {
return -1;
}
if (root == target) {
BFSGetNode(root, K);
return 0;
}
int left_dis = getDistance(root->left, target, K);
int right_dis = getDistance(root->right, target, K);
if (left_dis >= 0) {
if (left_dis == K - 1) {
answer.push_back(root->val);
}
BFSGetNode(root->right, K - left_dis - 2);
return left_dis + 1;
}
if (right_dis >= 0) {
if (right_dis == K - 1) {
answer.push_back(root->val);
}
BFSGetNode(root->left, K - right_dis - 2);
return right_dis + 1;
}
return -1;
}
void BFSGetNode(TreeNode* cur_root, int depth) {
if (!cur_root) {
return;
}
if (!depth) {
answer.push_back(cur_root->val);
return;
}
BFSGetNode(cur_root->left, depth - 1);
BFSGetNode(cur_root->right, depth - 1);
}
// 364. Nested List Weight Sum II
int depthSumInverse(vector<NestedInteger>& nestedList) {
int cum_sum = 0;
int cur_sum = 0;
queue<vector<NestedInteger>> que;
que.push(nestedList);
while (!que.empty()) {
int len = que.size();
cum_sum += cur_sum;
for (int idx = 0; idx < len; ++idx) {
vector<NestedInteger> tp = que.front();
que.pop();
for (auto ele: tp) {
if (ele.isInteger()) {
cur_sum += ele.getInteger();
cum_sum += ele.getInteger();
}
else {
que.push(ele.getList());
}
}
}
}
return cum_sum;
}
// 323. find total number of connected component in undirected graph
class UnionFind {
public:
vector<int> rec;
vector<int> num;
int comp;
UnionFind(int n) {
rec = vector<int>(n, 0);
num = vector<int>(n, 1);
for (int idx = 0; idx < n; ++idx) {
rec[idx] = idx;
}
comp = n;
}
int findParent(int node) {
if (node != rec[node]) {
rec[node] = findParent(rec[node]);
}
return rec[node];
}
void unionEdges(vector<int> edge) {
int p_1 = findParent(edge[0]);
int p_2 = findParent(edge[1]);
if (p_1 != p_2) {
if (num[p_1] > num[p_2]) {
num[p_1] += num[p_2];
rec[p_2] = p_1;
}
else {
num[p_2] += num[p_1];
rec[p_1] = p_2;
}
--comp;
}
}
};
class Solution {
public:
int countComponents(int n, vector<vector<int>>& edges) {
if (n <= 0) {
return 0;
}
UnionFind* uf = new UnionFind(n);
for (auto edge:edges) {
uf->unionEdges(edge);
}
return uf->comp;
}
};
// 311. OOD: implement a 2D matrix class that supports a matrix multiplication function.
template <classname T>
class A {
public:
void Do(const T& t) {}
}
template void A::Do<int>(const int&);
template void A::Do<std::string>(const std::string&);
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
void setLength( double len ) {
length = len;
}
void setBreadth( double bre ) {
breadth = bre;
}
void setHeight( double hei ) {
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b) {
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Operation
vector<vector<int>> multiply(vector<vector<int>>& mat1, vector<vector<int>>& mat2) {
unordered_map<int, unordered_set<int>> sparse_index1;
unordered_map<int, unordered_set<int>> sparse_index2;
const int k = mat1.size();
const int n = mat2[0].size();
for (int i = 0; i < mat1.size(); ++i) {
for (int j = 0; j < mat1[0].size(); ++j) {
if (mat1[i][j]) {
sparse_index1[i].insert(j);
}
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < mat2.size(); ++j) {
if (mat2[j][i]) {
sparse_index2[i].insert(j);
}
}
}
vector<vector<int>> ans(k, vector<int>(n, 0));
for (int i = 0; i < k; ++i) {
for (int j = 0; j < n; ++j) {
if (!sparse_index1[i].empty() && !sparse_index2[j].empty()) {
const auto& j_col = sparse_index2[j];
for (const auto& ele : sparse_index1[i]) {
if (i == 1) cout << ele << " " << i << " " << j << endl;
if (j_col.count(ele) > 0) {
ans[i][j] += mat1[i][ele]*mat2[ele][j];
}
}
}
}
}
return ans;
}
// Leetcode. 218 The Skyline Problem
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<vector<int>> pts;
for (const auto& pt: buildings) {
pts.push_back({pt[0], -pt[2]});
pts.push_back({pt[1], pt[2]});
}
sort(begin(pts), end(pts));
multiset<int> m({0});
int prev_max = 0;
vector<vector<int>> ans;
for (const auto& pt : pts) {
if (pt[1] < 0) m.insert(-pt[1]); // 左端点,高度入堆
else m.erase(m.find(pt[1])); // 右端点,高度出堆
const auto cur_max = *crbegin(m); // 当前最大高度高度
if (cur_max != prev_max) { // 当前最大高度不等于最大高度perv表示这是一个转折点
ans.push_back({pt[0], cur_max}); // 添加坐标
prev_max = cur_max; // 更新最大高度
}
}
return ans;
}
// 1374. Generate a String With Characters That Have Odd Counts
string GenerateTheString(char c, const int n) {
if (n == 1) return string(1, c);
if (!n) return "";
const string str = GenerateTheString(c, n/2);
return str + str + (n&1? string(1, c):"");
}
string generateTheString(int n) {
if (n == 1) return "a";
return n&1? GenerateTheString('b', n / 2 + 1) +
GenerateTheString('b', n / 2) : GenerateTheString('b', n - 1) +
"c";
}
// 79. Word Search
int dir[4][2] = { {0, -1}, {1, 0}, {0, 1}, {-1, 0 } };
bool findWord(vector<vector<char>>& board,
string word,
int cur_idx,
vector<vector<bool>>& rec,
int r_idx,
int c_idx) {
if (cur_idx + 1 == word.size()) {
return true;
}
for (int idx = 0; idx < 4; ++idx) {
int cur_r = dir[idx][1] + r_idx;
int cur_c = dir[idx][0] + c_idx;
if (cur_r < 0 || cur_r >= board.size() || cur_c < 0 || cur_c >= board[0].size() || rec[cur_r][cur_c]) {
continue;
}
if (board[cur_r][cur_c] == word[cur_idx+1]) {
if (cur_idx+2 == word.size()) {
return true;
}
rec[cur_r][cur_c] = true;
bool cur_res = findWord(board, word, cur_idx+1, rec, cur_r, cur_c);
if (cur_res) {
return cur_res;
}
rec[cur_r][cur_c] = false;
}
}
return false;
}
bool exist(vector<vector<char>>& board, string word) {
if (!board.size() || !board[0].size()) {
return false;
}
int row = board.size();
int col = board[0].size();
for (int r = 0; r < row; ++r) {
for (int c = 0; c < col; ++c) {
if (board[r][c] == word[0] ) {
vector<vector<bool>> rec(row, vector<bool>(col, false));
rec[r][c] = true;
if (findWord(board, word, 0, rec, r, c)) {
return true;
}
}
}
}
return false;
}
// 212. Word Search II
struct Node {
bool is_word = false;
Node* child[26] = {nullptr};
};
unique_ptr<Node> parent_ = make_unique<Node>();
unordered_set<string> result_set_;
int m_ = 0;
int n_ = 0;
void ConstructTrie(const vector<string>& words) {
for (const auto word : words) {
Node* cur_node = parent_.get();
for (int i = 0; i < word.size(); ++i) {
if (!cur_node->child[word[i]-'a']) {
cur_node->child[word[i]-'a'] = new Node();
}
if (i == word.size() - 1) {
cur_node->child[word[i]-'a']->is_word = true;
}
cur_node = cur_node->child[word[i]-'a'];
}
}
}
bool IsEmpltyChild(const Node* head) {
for (int i = 0; i < 26; ++i) {
if (head->child[i]) return false;
}
return true;
}
const int dirs[2][4] = { {-1, 0, 1, 0}, {0, 1, 0, -1 } };
vector<vector<char>> board_;
void Search(const int row, const int col, Node* cur_node,
string cur_str, vector<vector<char>>& visited) {
const int cur_idx = visited[row][col] - 'a';
Node* child = cur_node->child[cur_idx];
if (!child) return;
if (child->is_word) result_set_.insert(cur_str);
const auto c = visited[row][col];
visited[row][col] = '*';
for (int i = 0; i < 4; ++i) {
const int new_row = row + dirs[0][i];
const int new_col = col + dirs[1][i];
if (new_row < 0 || new_row >= m_ || new_col < 0 || new_col >= n_) continue;
if (visited[new_row][new_col] == '*') continue;
if (child->child[visited[new_row][new_col] - 'a']) {
Node* node = child->child[visited[new_row][new_col] - 'a'];
const string new_str = cur_str + visited[new_row][new_col];
if (node != nullptr) {
Search(new_row, new_col, child, new_str, visited);
}
}
}
visited[row][col] = c;
if (IsEmpltyChild(child)) {
delete child;
cur_node->child[cur_idx] = nullptr;
}
}
void SearchInTrie(const int row, const int col) {
Node* cur_node = parent_.get();
string cur_str(1, board_[row][col]);
Search(row, col, cur_node, cur_str, board_);
}
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
ConstructTrie(words);
m_ = board.size();
n_ = board[0].size();
board_ = board;
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[0].size(); ++j) {
SearchInTrie(i, j);
}
}
return vector<string>(result_set_.begin(), result_set_.end());
}
// 1200. Minimum Absolute Difference
vector<vector<int>> minimumAbsDifference(vector<int>& arr) {
if (arr.empty()) {
return {};
}
std::sort(arr.begin(), arr.end());
vector<vector<int>> min_pair;
int cur_diff = INT_MAX;
for (int ind = 1; ind < arr.size(); ++ind) {
if (arr[ind] - arr[ind-1] == cur_diff) {
min_pair.emplace_back(vector<int>({arr[ind-1], arr[ind]}));
}
else if (arr[ind] - arr[ind-1] < cur_diff) {
cur_diff = arr[ind] - arr[ind-1];
min_pair.clear();
min_pair.emplace_back(vector<int>({arr[ind-1], arr[ind]}));
}
}
return min_pair;
}
// 340. Longest Substring with At Most K Distinct Characters if streaming.
int lengthOfLongestSubstringKDistinct(string s, int k) {
int res = 0;
unordered_map<int, int> record;
for (int i = 0, j = 0; i < s.size(); ++i) {
++record[s[i]];
while (record.size() > k) {
--record[s[j]];
if (!record[s[j]])
record.erase(s[j]);
++j;
}
res = max(res, i - j + 1);
}
return res;
}
// 85. maximum rectangle
int maximalRectangle(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
vector<int> heights(matrix[0].size() + 2, 0);
int max_area = 0;
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[0].size(); ++j) {
if (matrix[i][j] == '0') {
heights[j+1] = 0;
} else {
++heights[j+1];
}
}
max_area = max(max_area, MaxHistogramArea(heights));
}
return max_area;
}
int MaxHistogramArea(const vector<int>& heights) {
stack<int> record;
record.push(heights[0]);
int max_area = 0;
for (int i = 1; i < heights.size(); ++i) {
while (heights[record.top()] > heights[i]) {
const int mid = record.top();
record.pop();
max_area = max(max_area, heights[mid] * (i - record.top() - 1));
}
record.push(i);
}
return max_area;
}
// 116. Populating Next Right Pointers in Each Node
Node* connect(Node* root) {
if (!root) return root;
if (root->next) {
if (root->right && root->next->left) {
root->right->next = root->next->left;
}
}
if (root->left && root->right)
root->left->next = root->right;
connect(root->left);
connect(root->right);
return root;
}
// 124. Binary Tree Maximum Path Sum
int MaxPathSum(TreeNode* root, int& max_sum) {
if (root == nullptr) return 0;
int left_sum = max(MaxPathSum(root->left, max_sum), 0);
int right_sum = max(MaxPathSum(root->right, max_sum), 0);
int root_val = root->val;
max_sum = max(root_val + left_sum + right_sum, max_sum);
return max(root_val + left_sum, root_val + right_sum);
}
int maxPathSum(TreeNode* root) {
int max_sum = INT_MIN;
if (root != nullptr)
MaxPathSum(root, max_sum);
return max_sum;
}
// 133. Clone Graph
unordered_map<Node*, Node*> record;
Node* cloneGraph(Node* node) {
if (!node) return nullptr;
if (record.count(node) > 0)
return record[node];
vector<Node*> new_neighbors;
record[node] = new Node(node->val);
for (const auto& n : node->neighbors) {
record[n] = cloneGraph(n);
new_neighbors.push_back(record[n]);
}
record[node]->neighbors.swap(new_neighbors);
return record[node];
}
// 297. Serialize and Deserialize Binary Tree
string serialize(TreeNode* root) {
queue<TreeNode*> que({root});
string str;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; ++i) {
const auto tp = que.front();
que.pop();
if (tp) {
que.push(tp->left);
que.push(tp->right);
str += to_string(tp->val) + ",";
} else {
str += "n,";
}
}
}
return str;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
if (data.empty()) return nullptr;
TreeNode* root = nullptr;
queue<TreeNode*> que;
int cur = 0;
int count = 0;
bool neg = false;
for (int i = 0; i < data.size(); ++i) {
if (data[i] == ',') {
TreeNode* tmp = cur < -1000? nullptr:new TreeNode(neg?-cur:cur);
if (!root) {
root = tmp;
} else {
while (!que.empty()) {
auto tp = que.front();
if (!tp) {
que.pop();
continue;
}
if (!count) tp->left = tmp;
else tp->right = tmp;
++count;
if (count == 2) {
count = 0;
que.pop();
}
break;
}
}
que.push(tmp);
cur = 0;
neg = false;
} else if (data[i] == 'n') {
cur = -1001;
} else if (data[i] == '-') {
neg = true;
}
else {
cur = cur*10 + data[i] - '0';
}
}
return root;
}
// 402. Remove K Digits
string removeKdigits(string num, int k) {
stack<char> stk;
const int K = k;
int index = 0;
for (const auto& c : num) {
while (!stk.empty() && stk.top() > c) {
stk.pop();
--k;
if (!k)
break;
}
if (!k) break;
stk.push(c);
++index;
}
string ans;
while (!stk.empty()) {
ans = string(1, stk.top()) + ans;
stk.pop();
}
ans += num.substr(index);
ans = ans.substr(0, num.size() - K);
string ans2;
index = 0;
while (index < ans.size()) {
if (ans[index] != '0') {
ans2 += ans.substr(index);
break;
}
++index;
}
return ans2.empty() ? "0" : ans2;
}
Didi interview preparation
2019-09-04
