Compare commits
131 Commits
18ecf286e4
...
c920f9bfd4
| Author | SHA1 | Date |
|---|---|---|
|
|
c920f9bfd4 | |
|
|
de11fa9dc3 | |
|
|
bde1ceb0c2 | |
|
|
40036c20dc | |
|
|
9c9e1f4604 | |
|
|
290cdd7b8e | |
|
|
7f8946ce7a | |
|
|
9860bb7a54 | |
|
|
cc60ceaceb | |
|
|
3a01c0e2a2 | |
|
|
0ec5b02f1f | |
|
|
5f1912bf21 | |
|
|
b84f583b51 | |
|
|
50666fbdbd | |
|
|
44c80466fa | |
|
|
2c85f9fc4b | |
|
|
4dcff98da5 | |
|
|
615c8444a3 | |
|
|
6471f95007 | |
|
|
d4b780b2f0 | |
|
|
6ee1746ac6 | |
|
|
062ec6091a | |
|
|
bce7fa8ad0 | |
|
|
71fa620cd9 | |
|
|
bfa1062df6 | |
|
|
78365bc52a | |
|
|
611beb5be6 | |
|
|
32f7bd3bd0 | |
|
|
477e490bb4 | |
|
|
dbb28499e4 | |
|
|
e4093d32fd | |
|
|
586ed15310 | |
|
|
c3e72eb840 | |
|
|
111c4692c1 | |
|
|
9b372dc10f | |
|
|
06b1e482b1 | |
|
|
85661e9df6 | |
|
|
3fbd7623d9 | |
|
|
f9f7f6929f | |
|
|
0ba5fb7cb8 | |
|
|
6b5ae005d9 | |
|
|
2e711e443b | |
|
|
036f3b7f5d | |
|
|
85fcd9e620 | |
|
|
aa6da656d3 | |
|
|
2deff47e80 | |
|
|
d77ba88558 | |
|
|
8be4d84d34 | |
|
|
5c584f805c | |
|
|
61cd797e28 | |
|
|
dab70cedf8 | |
|
|
873ac4de1e | |
|
|
a9ff3c5bc0 | |
|
|
1c281801e8 | |
|
|
6b86835c06 | |
|
|
1ff4e631c2 | |
|
|
31043a54dc | |
|
|
cc6c4312ea | |
|
|
1b168df890 | |
|
|
476514de0b | |
|
|
4bfff21cdf | |
|
|
dd230c20a5 | |
|
|
e5a7e1f172 | |
|
|
a3d4cd6548 | |
|
|
5d896a3452 | |
|
|
c79ce48e37 | |
|
|
fe2a0b6707 | |
|
|
c9be7ea9e7 | |
|
|
599532847a | |
|
|
169e6b33a2 | |
|
|
e2e4efacce | |
|
|
f8243bfdb3 | |
|
|
aafc1b7c9f | |
|
|
cec4f35834 | |
|
|
c16d1460c7 | |
|
|
60316eaccc | |
|
|
b2430377a0 | |
|
|
e057d343a7 | |
|
|
7b1e933924 | |
|
|
0fee3db3b8 | |
|
|
c0825640b4 | |
|
|
eedc44ba5c | |
|
|
0bf2639257 | |
|
|
ba5d3bb409 | |
|
|
bc2e434c78 | |
|
|
8066fae29f | |
|
|
c5ff11cf9d | |
|
|
5dd5ebe1c0 | |
|
|
10d5427eb3 | |
|
|
6b55e52a56 | |
|
|
76787b7d48 | |
|
|
8a10e73747 | |
|
|
0bc79d6395 | |
|
|
5fb0da597d | |
|
|
e785f9fff0 | |
|
|
f3af871281 | |
|
|
069752dd3f | |
|
|
0207e06a04 | |
|
|
4ff7357336 | |
|
|
ea38815e5c | |
|
|
cb6cd0b214 | |
|
|
693d676aad | |
|
|
b9564c775d | |
|
|
a5c848b17c | |
|
|
66ac5f1bf2 | |
|
|
a8e062f2b6 | |
|
|
ccb2bb4385 | |
|
|
bebbcb0aa5 | |
|
|
56ed525c17 | |
|
|
6c5916645b | |
|
|
27593e9adf | |
|
|
4969678067 | |
|
|
755c0c2800 | |
|
|
f76f1f9566 | |
|
|
e7bd890aa5 | |
|
|
57976e72fb | |
|
|
d14b269d11 | |
|
|
63af3ba10d | |
|
|
7a0acbf6a3 | |
|
|
acd093331d | |
|
|
e4d15ecf06 | |
|
|
2cc35c392a | |
|
|
d38873562f | |
|
|
431ced268f | |
|
|
da5f92691c | |
|
|
35f4170a85 | |
|
|
6fdf7e8391 | |
|
|
692c3ba537 | |
|
|
b8916e9ab7 | |
|
|
9c89a0e22f | |
|
|
da93f6229e |
|
|
@ -0,0 +1,69 @@
|
|||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
class CustomFunction {
|
||||
public:
|
||||
int f(int x, int y);
|
||||
};
|
||||
|
||||
/**
|
||||
* 1237. Find Positive Integer Solution for a Given Equation
|
||||
* Given a callable function f(x, y) with a hidden formula and a value z, reverse engineer the formula and return all positive integer pairs x and y where f(x,y) == z. You may return the pairs in any order.
|
||||
*
|
||||
* While the exact formula is hidden, the function is monotonically increasing, i.e.:
|
||||
*
|
||||
* f(x, y) < f(x + 1, y)
|
||||
* f(x, y) < f(x, y + 1)
|
||||
* The function interface is defined like this:
|
||||
*
|
||||
* interface CustomFunction {
|
||||
* public:
|
||||
* // Returns some positive integer f(x, y) for two positive integers x and y based on a formula.
|
||||
* int f(int x, int y);
|
||||
* };
|
||||
* We will judge your solution as follows:
|
||||
*
|
||||
* The judge has a list of 9 hidden implementations of CustomFunction, along with a way to generate an answer key of all valid pairs for a specific z.
|
||||
* The judge will receive two inputs: a function_id (to determine which implementation to test your code with), and the target z.
|
||||
* The judge will call your findSolution and compare your results with the answer key.
|
||||
* If your results match the answer key, your solution will be Accepted.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<std::vector<int>> findSolution(CustomFunction& cf, int z) {
|
||||
std::vector<int> p(1000);
|
||||
std::iota(p.begin(), p.end(), 1);
|
||||
auto L = std::lower_bound(p.begin(), p.end(), z, [&](int x, int y) {
|
||||
return cf.f(x, 1000) < y;
|
||||
}), R = std::upper_bound(p.begin(), p.end(), z, [&](int x, int y) {
|
||||
return cf.f(y, 1) > x;
|
||||
});
|
||||
std::vector<std::vector<int>> ret;
|
||||
std::for_each(L, R, [&](int x) {
|
||||
auto L2 = std::lower_bound(p.begin(), p.end(), z, [&](int m, int n) {
|
||||
return cf.f(x, m) < n;
|
||||
}), R2 = std::upper_bound(p.begin(), p.end(), z, [&](int m, int n) {
|
||||
return cf.f(x, n) > m;
|
||||
});
|
||||
std::for_each(L2, R2, [&](int y) {
|
||||
ret.push_back({x, y});
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int CustomFunction::f(int x, int y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CustomFunction f;
|
||||
auto ret = Solution::findSolution(f, 5);
|
||||
for (auto p : ret)
|
||||
std::cout << p[0] << ", " << p[1] << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#include <algorithm>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 226. Invert Binary Tree
|
||||
* Given the root of a binary tree, invert the tree, and return its root.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static TreeNode* invertTree(TreeNode* root) {
|
||||
return root ? (std::swap(root->left, root->right), invertTree(root->left), invertTree(root->right), root) : nullptr;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <queue>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
#include <execution>
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static double maxAverageRatio(std::vector<std::vector<int>>& c, int ex) {
|
||||
int n = c.size();
|
||||
double ans = std::transform_reduce(
|
||||
std::execution::par,
|
||||
c.begin(),
|
||||
c.end(),
|
||||
0.0,
|
||||
std::plus{},
|
||||
[](const std::vector<int>& x) {
|
||||
return double(x[0]) / double(x[1]);
|
||||
}
|
||||
);
|
||||
std::priority_queue<std::pair<double, int>> incr;
|
||||
for (int i = 0; i < n; ++i)
|
||||
incr.emplace(double(c[i][0] + 1) / double(c[i][1] + 1) - double(c[i][0]) / double(c[i][1]), i);
|
||||
while (ex--) {
|
||||
const auto [delta, i] = incr.top();
|
||||
incr.pop();
|
||||
ans += delta;
|
||||
++c[i][0], ++c[i][1];
|
||||
incr.emplace(double(c[i][0] + 1) / double(c[i][1] + 1) - double(c[i][0]) / double(c[i][1]), i);
|
||||
}
|
||||
return ans / n;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<std::vector<int>> c {
|
||||
{2,4},{3,9},{4,5},{2,10}
|
||||
};
|
||||
std::printf("%.6f\n", Solution::maxAverageRatio(c, 4));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#include <vector>
|
||||
#include <utility>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 103. Binary Tree Zigzag Level Order Traversal
|
||||
*
|
||||
* Given the root of a binary tree, return the zigzag level order traversal of its nodes' values. (i.e., from left to right, then right to left for the next level and alternate between).
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<std::vector<int>> zigzagLevelOrder(const TreeNode* root) {
|
||||
if (!root)
|
||||
return {};
|
||||
std::vector<std::vector<int>> ret {{}};
|
||||
std::queue<std::pair<const TreeNode*, int>> q;
|
||||
q.emplace(root, 0);
|
||||
for (int n = 0; !q.empty(); ) {
|
||||
const auto [ptr, lv] = q.front();
|
||||
q.pop();
|
||||
if (lv > n) {
|
||||
ret.emplace_back();
|
||||
++n;
|
||||
}
|
||||
ret.back().push_back(ptr->val);
|
||||
if (ptr->left)
|
||||
q.emplace(ptr->left, 1 + lv);
|
||||
if (ptr->right)
|
||||
q.emplace(ptr->right, 1 + lv);
|
||||
}
|
||||
for (int i = 1; i < ret.size(); i += 2)
|
||||
std::reverse(ret[i].begin(), ret[i].end());
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* 2347. Best Poker Hand
|
||||
*
|
||||
* You are given an integer array ranks and a character array suits. You have 5 cards where the ith card has a rank of ranks[i] and a suit of suits[i].
|
||||
*
|
||||
* The following are the types of poker hands you can make from best to worst:
|
||||
*
|
||||
* "Flush": Five cards of the same suit.
|
||||
* "Three of a Kind": Three cards of the same rank.
|
||||
* "Pair": Two cards of the same rank.
|
||||
* "High Card": Any single card.
|
||||
* Return a string representing the best type of poker hand you can make with the given cards.
|
||||
*
|
||||
* Note that the return values are case-sensitive.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static inline std::string bestHand(const std::vector<int>& ranks, const std::vector<char>& suits) {
|
||||
if (std::adjacent_find(suits.begin(), suits.end(), std::not_equal_to<>()) == suits.end())
|
||||
return "Flush";
|
||||
uint8_t cnt[13]{};
|
||||
for (auto i : ranks)
|
||||
++cnt[i - 1];
|
||||
auto m = *std::max_element(cnt, cnt + 13);
|
||||
if (m >= 3)
|
||||
return "Three of a Kind";
|
||||
if (m >= 2)
|
||||
return "Pair";
|
||||
return "High Card";
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 35. Search Insert Position
|
||||
*
|
||||
* Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
|
||||
* You must write an algorithm with O(log n) runtime complexity.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static inline int searchInsert(const std::vector<int>& nums, int target) {
|
||||
return std::lower_bound(nums.begin(), nums.end(), target) - nums.begin();
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
/**
|
||||
* 1326. Minimum Number of Taps to Open to Water a Garden
|
||||
*
|
||||
* There is a one-dimensional garden on the x-axis. The garden starts at the point 0 and ends at the point n. (i.e The length of the garden is n).
|
||||
* There are n + 1 taps located at points [0, 1, ..., n] in the garden.
|
||||
* Given an integer n and an integer array ranges of length n + 1 where ranges[i] (0-indexed) means the i-th tap can water the area [i - ranges[i], i + ranges[i]] if it was open.
|
||||
* Return the minimum number of taps that should be open to water the whole garden, If the garden cannot be watered return -1.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minTaps(int n, const std::vector<int>& ranges) {
|
||||
std::vector<int> adv(n + 1, -1);
|
||||
for (int i = 0; i <= n; ++i) {
|
||||
if (!ranges[i])
|
||||
continue;
|
||||
// L, R inclusive
|
||||
int L = std::max(0, i - ranges[i]), R = std::min(n, i + ranges[i]);
|
||||
for (int j = L; j <= R; ++j)
|
||||
adv[j] = std::max(adv[j], R);
|
||||
}
|
||||
int ans = 0;
|
||||
for (int i = 0; i < n; ++ans) {
|
||||
if (adv[i] < i || (i == adv[i] && i < n))
|
||||
return -1;
|
||||
i = adv[i];
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::printf("%d\n", Solution::minTaps(35, {1,0,4,0,4,1,4,3,1,1,1,2,1,4,0,3,0,3,0,3,0,5,3,0,0,1,2,1,2,4,3,0,1,0,5,2}));
|
||||
std::printf("%d\n", Solution::minTaps(7, {1,2,1,0,2,1,0,1}));
|
||||
std::printf("%d\n", Solution::minTaps(3, {0,0,0,0}));
|
||||
std::printf("%d\n", Solution::minTaps(5, {3,0,1,1,0,0}));
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 540. Single Element in a Sorted Array
|
||||
*
|
||||
* You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once.
|
||||
* Return the single element that appears only once.
|
||||
* Your solution must run in O(log n) time and O(1) space.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int singleNonDuplicate(const std::vector<int>& nums) {
|
||||
int L = 0, R = nums.size() >> 1; // inclusive
|
||||
while (L < R) {
|
||||
int M = (L + R) >> 1;
|
||||
if (nums[(M << 1) | 1] - nums[M << 1]) R = M;
|
||||
else L = M + 1;
|
||||
}
|
||||
return nums[L << 1];
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::singleNonDuplicate({3,3,7,7,10,11,11});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1144. Decrease Elements To Make Array Zigzag
|
||||
*
|
||||
* Given an array nums of integers, a move consists of choosing any element and decreasing it by 1.
|
||||
* An array A is a zigzag array if either:
|
||||
* Every even-indexed element is greater than adjacent elements, ie. A[0] > A[1] < A[2] > A[3] < A[4] > ...
|
||||
* OR, every odd-indexed element is greater than adjacent elements, ie. A[0] < A[1] > A[2] < A[3] > A[4] < ...
|
||||
* Return the minimum number of moves to transform the given array nums into a zigzag array.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int movesToMakeZigzag(const std::vector<int>& nums) {
|
||||
int tmp, c1 = 0, c2 = 0;
|
||||
const int n = nums.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
tmp = 0x7FFFFFFF;
|
||||
if (i > 0)
|
||||
tmp = std::min(tmp, nums[i - 1]);
|
||||
if (i + 1 < n)
|
||||
tmp = std::min(tmp, nums[i + 1]);
|
||||
if (nums[i] >= tmp)
|
||||
if (i & 1)
|
||||
c1 += nums[i] - (tmp - 1);
|
||||
else
|
||||
c2 += nums[i] - (tmp - 1);
|
||||
}
|
||||
return std::min(c1, c2);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* 427. Construct Quad Tree
|
||||
* Given a n * n matrix grid of 0's and 1's only. We want to represent the grid with a Quad-Tree.
|
||||
* Return the root of the Quad-Tree representing the grid.
|
||||
*
|
||||
* Refer: 220429-CN.cpp
|
||||
*/
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* 2363. Merge Similar Items
|
||||
*
|
||||
* You are given two 2D integer arrays, items1 and items2, representing two sets of items. Each array items has the following properties:
|
||||
*
|
||||
* items[i] = [valuei, weighti] where valuei represents the value and weighti represents the weight of the ith item.
|
||||
* The value of each item in items is unique.
|
||||
* Return a 2D integer array ret where ret[i] = [valuei, weighti], with weighti being the sum of weights of all items with value valuei.
|
||||
*
|
||||
* Note: ret should be returned in ascending order by value.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<std::vector<int>> mergeSimilarItems(const std::vector<std::vector<int>>& items1, const std::vector<std::vector<int>>& items2) {
|
||||
std::map<int, int> m;
|
||||
for (const auto &item: items1)
|
||||
m[item[0]] += item[1];
|
||||
for (const auto &item: items2)
|
||||
m[item[0]] += item[1];
|
||||
std::vector<std::vector<int>> ret;
|
||||
std::transform(m.begin(), m.end(), std::back_inserter(ret), [](const auto& x) {
|
||||
return std::vector<int>{x.first, x.second};
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x = 0, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 652. Find Duplicate Subtrees
|
||||
*
|
||||
* Given the root of a binary tree, return all duplicate subtrees.
|
||||
* For each kind of duplicate subtrees, you only need to return the root node of any one of them.
|
||||
* Two trees are duplicate if they have the same structure with the same node values.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::unordered_map<std::string, TreeNode*> strToNode;
|
||||
std::unordered_map<std::string, int> strCnt;
|
||||
|
||||
// Pre-order
|
||||
std::string toStr(TreeNode* r) {
|
||||
if (!r)
|
||||
return "";
|
||||
auto ret = std::to_string(r->val)
|
||||
.append("(")
|
||||
.append(toStr(r->left))
|
||||
.append(")(")
|
||||
.append(toStr(r->right))
|
||||
.append(")");
|
||||
strToNode[ret] = r;
|
||||
++strCnt[ret];
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<TreeNode*> findDuplicateSubtrees(TreeNode* r) {
|
||||
toStr(r);
|
||||
std::vector<TreeNode*> ret;
|
||||
for (const auto& [str, c] : strCnt) {
|
||||
if (c <= 1)
|
||||
continue;
|
||||
ret.push_back(strToNode[str]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
|
||||
PROJECT(2302)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
ADD_EXECUTABLE(2302 230228.cpp)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 2373. Largest Local Values in a Matrix
|
||||
*
|
||||
* You are given an n x n integer matrix grid.
|
||||
*
|
||||
* Generate an integer matrix maxLocal of size (n - 2) x (n - 2) such that:
|
||||
*
|
||||
* maxLocal[i][j] is equal to the largest value of the 3 x 3 matrix in grid centered around row i + 1 and column j + 1.
|
||||
* In other words, we want to find the largest value in every contiguous 3 x 3 matrix in grid.
|
||||
*
|
||||
* Return the generated matrix.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<std::vector<int>> largestLocal(const std::vector<std::vector<int>>& grid) {
|
||||
const int n = grid.size(), t = n - 2;
|
||||
auto ret = std::vector<std::vector<int>>(t, std::vector<int>(t));
|
||||
for (int i = 0; i < t; ++i)
|
||||
for (int j = 0; j < t; ++j)
|
||||
for (int k = 0; k < 3; ++k)
|
||||
for (int l = 0; l < 3; ++l)
|
||||
ret[i][j] = std::max(ret[i][j], grid[i + k][j + l]);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* 912. Sort an Array
|
||||
*
|
||||
* Given an array of integers nums, sort the array in ascending order and return it.
|
||||
* You must solve the problem without using any built-in functions in O(nlog(n)) time complexity and with the smallest space complexity possible.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static inline const int S = 50001;
|
||||
|
||||
public:
|
||||
static std::vector<int> sortArray(const std::vector<int>& nums) {
|
||||
const int n = nums.size();
|
||||
std::vector<int> ret(n);
|
||||
uint16_t bucket[100005]{};
|
||||
for (int i : nums)
|
||||
++bucket[i + S];
|
||||
for (int i = 0, pos = 0; i < 100005; ++i)
|
||||
for (int j = 0, ins = i - S; j < bucket[i]; ++j)
|
||||
ret[pos++] = ins;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 面试题 05.02. Binary Number to String LCCI
|
||||
*
|
||||
* Given a real number between 0 and 1 (e.g., 0.72) that is passed in as a double, print the binary representation. If the number cannot be represented accurately in binary with at most 32 characters, print "ERROR".
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::string printBin(const double n) {
|
||||
const auto b = *reinterpret_cast<const unsigned long long*>(&n);
|
||||
const auto d = 1023 - ((b >> 52) & 0x7FF);
|
||||
const auto e = b & 0x000FFFFFFFFFFFFF;
|
||||
|
||||
const auto mask = (1ULL << (52 - (31 - d))) - 1;
|
||||
if (e & mask)
|
||||
return "ERROR";
|
||||
auto ret = std::string("0.").append(d - 1, '0').append(1, '1');
|
||||
for (int i = 0; i < 31 - d; ++i)
|
||||
ret.push_back(((1ULL << (51 - i)) & e) ? '1' : '0');
|
||||
for (; '0' == ret.back(); ret.pop_back());
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::printBin(0.1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 443. String Compression
|
||||
*
|
||||
* Given an array of characters chars, compress it using the following algorithm:
|
||||
*
|
||||
* Begin with an empty string s. For each group of consecutive repeating characters in chars:
|
||||
*
|
||||
* If the group's length is 1, append the character to s.
|
||||
* Otherwise, append the character followed by the group's length.
|
||||
* The compressed string s should not be returned separately, but instead, be stored in the input character array chars. Note that group lengths that are 10 or longer will be split into multiple characters in chars.
|
||||
*
|
||||
* After you are done modifying the input array, return the new length of the array.
|
||||
*
|
||||
* You must write an algorithm that uses only constant extra space.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int compress(std::vector<char>& c) {
|
||||
const int n = c.size();
|
||||
int pos = 0, ct = 1;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
// Look ahead
|
||||
if (i + 1 < n && c[i] == c[1 + i]) {
|
||||
++ct;
|
||||
} else {
|
||||
c[pos++] = c[i];
|
||||
if (ct > 1)
|
||||
for (char x : std::to_string(ct))
|
||||
c[pos++] = x;
|
||||
ct = 1;
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
const char* s = "abbbbbbbbbbbb";
|
||||
std::vector<char> c;
|
||||
for (const char* ptr = s; *ptr; ++ptr)
|
||||
c.push_back(*ptr);
|
||||
int n = Solution::compress(c);
|
||||
for (int i = 0; i < n; ++i)
|
||||
std::cout << c[i];
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 28. Find the Index of the First Occurrence in a String
|
||||
*
|
||||
* Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int strStr(const std::string& s, const std::string& t) {
|
||||
const int m = s.length(), n = t.length();
|
||||
std::vector<int> p(n);
|
||||
for (int i = 1; i < n; ++i) {
|
||||
int j = p[i - 1];
|
||||
for (; j > 0 && t[i] != t[j]; j = p[j - 1]);
|
||||
p[i] = j + (t[i] == t[j]);
|
||||
}
|
||||
for (int i = 0, j = 0; i < m; ++i) {
|
||||
for (; j > 0 && s[i] != t[j]; j = p[j - 1]);
|
||||
if (s[i] == t[j] && ++j >= n)
|
||||
return i - j + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::strStr("busasasasasapsadpp", "sasasasapsad");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode* next;
|
||||
|
||||
explicit ListNode(int x = 0, ListNode* next = nullptr) : val(x), next(next) {}
|
||||
};
|
||||
|
||||
ListNode* construct(int x) {
|
||||
return new ListNode(x);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
ListNode* construct(int x, Ts... xs) {
|
||||
return new ListNode(x, construct(xs...));
|
||||
}
|
||||
|
||||
/**
|
||||
* 382. Linked List Random Node
|
||||
* Given a singly linked list, return a random node's value from the linked list. Each node must have the same probability of being chosen.
|
||||
*
|
||||
* Implement the Solution class:
|
||||
*
|
||||
* Solution(ListNode head) Initializes the object with the head of the singly-linked list head.
|
||||
* int getRandom() Chooses a node randomly from the list and returns its value. All the nodes of the list should be equally likely to be chosen.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::vector<short> s;
|
||||
|
||||
public:
|
||||
explicit Solution(ListNode* head) {
|
||||
for (auto* ptr = head; ptr; ptr = ptr->next)
|
||||
s.push_back(ptr->val);
|
||||
std::srand(std::time(nullptr));
|
||||
}
|
||||
|
||||
int getRandom() const {
|
||||
int r = rand();
|
||||
for (; r >= RAND_MAX / s.size() * s.size(); r = rand());
|
||||
return s[r % s.size()];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x = 0, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode* next;
|
||||
|
||||
explicit ListNode(int x = 0, ListNode* next = nullptr) : val(x), next(next) {}
|
||||
};
|
||||
|
||||
ListNode* construct(int x) {
|
||||
return new ListNode(x);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
ListNode* construct(int x, Ts... xs) {
|
||||
return new ListNode(x, construct(xs...));
|
||||
}
|
||||
|
||||
/**
|
||||
* 109. Convert Sorted List to Binary Search Tree
|
||||
*
|
||||
* Given the head of a singly linked list where elements are sorted in ascending order, convert it to a height-balanced binary search tree.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static TreeNode* helper(const std::vector<int>& v, int s, int e) {
|
||||
switch (e - s) {
|
||||
case 1:
|
||||
return new TreeNode(v[s]);
|
||||
case 2:
|
||||
return new TreeNode(v[s + 1], new TreeNode(v[s]), nullptr);
|
||||
}
|
||||
int mid = (s + e) >> 1;
|
||||
return new TreeNode(
|
||||
v[mid],
|
||||
helper(v, s, mid),
|
||||
helper(v, mid + 1, e)
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
static TreeNode* sortedListToBST(ListNode* head) {
|
||||
if (!head)
|
||||
return nullptr;
|
||||
std::vector<int> v;
|
||||
for (const ListNode* ptr = head; ptr; ptr = ptr->next)
|
||||
v.push_back(ptr->val);
|
||||
return helper(v, 0, v.size());
|
||||
}
|
||||
};
|
||||
|
||||
int h(const TreeNode* r) {
|
||||
return r ? std::max(h(r->left), h(r->right)) + 1 : 0;
|
||||
}
|
||||
|
||||
bool isBalanced(const TreeNode* r) {
|
||||
if (!r)
|
||||
return true;
|
||||
if (!isBalanced(r->left)) {
|
||||
std::printf("Not balanced: val = %d, L not balanced.\n", r->val);
|
||||
return false;
|
||||
} else if (!isBalanced(r->right)) {
|
||||
std::printf("Not balanced: val = %d, R not balanced.\n", r->val);
|
||||
return false;
|
||||
}
|
||||
int hl = h(r->left), hr = h(r->right);
|
||||
if (std::abs(hl - hr) > 1) {
|
||||
std::printf("Not balanced, val = %d, hl = %d, hr = %d\n", r->val, hl, hr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string to_string(const TreeNode* r) {
|
||||
if (!r)
|
||||
return "[]";
|
||||
return std::string("[") + std::to_string(r->val) + to_string(r->left) + to_string(r->right) + "]";
|
||||
}
|
||||
|
||||
int main() {
|
||||
ListNode* h = construct(-10, -3, 0, 5, 9, 10, 12, 14, 666, 3344);
|
||||
TreeNode* r = Solution::sortedListToBST(h);
|
||||
std::printf("%s\n", to_string(r).c_str());
|
||||
std::printf("Is balanced: %s\n", isBalanced(r) ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#include <queue>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode* next;
|
||||
|
||||
explicit ListNode(int x = 0, ListNode* next = nullptr) : val(x), next(next) {}
|
||||
};
|
||||
|
||||
ListNode* construct(int x) {
|
||||
return new ListNode(x);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
ListNode* construct(int x, Ts... xs) {
|
||||
return new ListNode(x, construct(xs...));
|
||||
}
|
||||
|
||||
struct cmp {
|
||||
bool operator()(const ListNode* x, const ListNode* y) {
|
||||
return x && (!y || x->val > y->val);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 23. Merge k Sorted Lists
|
||||
*
|
||||
* You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.
|
||||
* Merge all the linked-lists into one sorted linked-list and return it.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static ListNode* mergeKLists(const std::vector<ListNode*>& lists) {
|
||||
if (lists.empty())
|
||||
return nullptr;
|
||||
std::priority_queue<ListNode*, std::vector<ListNode*>, cmp> q(lists.begin(), lists.end());
|
||||
ListNode* ptr = new ListNode(0), * head = ptr;
|
||||
for (; !q.empty() && !q.top(); q.pop());
|
||||
while (!q.empty()) {
|
||||
ListNode* p = q.top();
|
||||
q.pop();
|
||||
ptr = ptr->next = new ListNode(p->val);
|
||||
if (p->next)
|
||||
q.push(p->next);
|
||||
}
|
||||
return head->next;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
ListNode* h = Solution::mergeKLists({
|
||||
construct(1, 4, 5),
|
||||
nullptr,
|
||||
construct(1, 3, 4),
|
||||
construct(2, 6),
|
||||
nullptr,
|
||||
nullptr
|
||||
});
|
||||
for (ListNode* ptr = h; ptr; ptr = ptr->next)
|
||||
std::cout << ptr->val << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2383. Minimum Hours of Training to Win a Competition
|
||||
*
|
||||
* You are entering a competition, and are given two positive integers initialEnergy and initialExperience denoting your initial energy and initial experience respectively.
|
||||
* You are also given two 0-indexed integer arrays energy and experience, both of length n.
|
||||
* You will face n opponents in order. The energy and experience of the ith opponent is denoted by energy[i] and experience[i] respectively. When you face an opponent, you need to have both strictly greater experience and energy to defeat them and move to the next opponent if available.
|
||||
* Defeating the ith opponent increases your experience by experience[i], but decreases your energy by energy[i].
|
||||
* Before starting the competition, you can train for some number of hours. After each hour of training, you can either choose to increase your initial experience by one, or increase your initial energy by one.
|
||||
* Return the minimum number of training hours required to defeat all n opponents.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minNumberOfHours(int iEn, int iEx, const std::vector<int>& en, const std::vector<int>& ex) {
|
||||
int ans = std::max(0, std::reduce(en.begin(), en.end(), 0) - iEn + 1);
|
||||
for (int i : ex) {
|
||||
if (i >= iEx) {
|
||||
ans += i - iEx + 1;
|
||||
iEx = i + 1;
|
||||
}
|
||||
iEx += i;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::minNumberOfHours(5, 3, {1,4,3,2}, {2,6,3,1});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x = 0, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 101. Symmetric Tree
|
||||
*
|
||||
* Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static bool helper(TreeNode* L, TreeNode* R) {
|
||||
if (!L && !R)
|
||||
return true;
|
||||
if (!L || !R)
|
||||
return false;
|
||||
return (L->val == R->val) && helper(L->right, R->left) && helper(L->left, R->right);
|
||||
}
|
||||
|
||||
public:
|
||||
static bool isSymmetric(TreeNode* r) {
|
||||
return !r || helper(r->left, r->right);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 1605. Find Valid Matrix Given Row and Column Sums
|
||||
*
|
||||
* You are given two arrays rowSum and colSum of non-negative integers where rowSum[i] is the sum of the elements in the ith row and colSum[j] is the sum of the elements of the jth column of a 2D matrix. In other words, you do not know the elements of the matrix, but you do know the sums of each row and column.
|
||||
* Find any matrix of non-negative integers of size rowSum.length x colSum.length that satisfies the rowSum and colSum requirements.
|
||||
* Return a 2D array representing any matrix that fulfills the requirements. It's guaranteed that at least one matrix that fulfills the requirements exists.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<std::vector<int>> restoreMatrix(std::vector<int>& rowSum, std::vector<int>& colSum) {
|
||||
const int rn = rowSum.size(), cn = colSum.size();
|
||||
std::vector<std::vector<int>> ret(rn, std::vector<int>(cn));
|
||||
for (int rp = 0, cp = 0, inc; rp < rn && cp < cn; ) {
|
||||
inc = std::min(rowSum[rp], colSum[cp]);
|
||||
ret[rp][cp] = inc;
|
||||
rp += !(rowSum[rp] -= inc);
|
||||
cp += !(colSum[cp] -= inc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
std::vector<int> rs = {3,8}, cs = {4,7};
|
||||
auto r = Solution::restoreMatrix(rs, cs);
|
||||
for (const auto& i : r) {
|
||||
for (const auto& j : i)
|
||||
std::printf("%d ", j);
|
||||
std::printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include <functional>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 129. Sum Root to Leaf Numbers
|
||||
*
|
||||
* You are given the root of a binary tree containing digits from 0 to 9 only.
|
||||
* Each root-to-leaf path in the tree represents a number.
|
||||
* For example, the root-to-leaf path 1 -> 2 -> 3 represents the number 123.
|
||||
* Return the total sum of all root-to-leaf numbers. Test cases are generated so that the answer will fit in a 32-bit integer.
|
||||
* A leaf node is a node with no children.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int sumNumbers(const TreeNode* root) {
|
||||
if (!root)
|
||||
return 0;
|
||||
int stack[16]{root->val}, ptr = 0, ans = 0;
|
||||
std::function<void(const TreeNode*)> dfs = [&](const TreeNode* r) {
|
||||
if (!r->left && !r->right) {
|
||||
ans += stack[ptr];
|
||||
return;
|
||||
}
|
||||
++ptr;
|
||||
if (r->left) {
|
||||
stack[ptr] = 10 * stack[ptr - 1] + r->left->val;
|
||||
dfs(r->left);
|
||||
}
|
||||
if (r->right) {
|
||||
stack[ptr] = 10 * stack[ptr - 1] + r->right->val;
|
||||
dfs(r->right);
|
||||
}
|
||||
--ptr;
|
||||
};
|
||||
dfs(root);
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1615. Maximal Network Rank
|
||||
*
|
||||
* There is an infrastructure of n cities with some number of roads connecting these cities. Each roads[i] = [ai, bi] indicates that there is a bidirectional road between cities ai and bi.
|
||||
* The network rank of two different cities is defined as the total number of directly connected roads to either city. If a road is directly connected to both cities, it is only counted once.
|
||||
* The maximal network rank of the infrastructure is the maximum network rank of all pairs of different cities.
|
||||
* Given the integer n and the array roads, return the maximal network rank of the entire infrastructure.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int maximalNetworkRank(int n, const std::vector<std::vector<int>>& roads) {
|
||||
bool G[105][105]{};
|
||||
int cnt[105]{};
|
||||
for (const auto& i : roads) {
|
||||
G[i[0]][i[1]] = G[i[1]][i[0]] = true;
|
||||
++cnt[i[0]];
|
||||
++cnt[i[1]];
|
||||
}
|
||||
int ans = 0;
|
||||
for (int i = 0; i < n; ++i)
|
||||
for (int j = 0; j < n; ++j)
|
||||
if (i != j)
|
||||
ans = std::max(ans, cnt[i] + cnt[j] - G[i][j]);
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <queue>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 958. Check Completeness of a Binary Tree
|
||||
*
|
||||
* Given the root of a binary tree, determine if it is a complete binary tree.
|
||||
* In a complete binary tree, every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool isCompleteTree(const TreeNode* r) {
|
||||
std::queue<std::pair<int, const TreeNode*>> q;
|
||||
q.emplace(1, r);
|
||||
for (int c = 1; !q.empty(); ++c) {
|
||||
const auto [v, p] = q.front();
|
||||
q.pop();
|
||||
if (v != c)
|
||||
return false;
|
||||
if (p->left) {
|
||||
q.emplace(v << 1, p->left);
|
||||
if (p->right)
|
||||
q.emplace(v << 1 | 1, p->right);
|
||||
} else if (p->right) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto* t = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)), new TreeNode(3, nullptr, new TreeNode(6)));
|
||||
std::cout << Solution::isCompleteTree(t);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2488. Count Subarrays With Median K
|
||||
*
|
||||
* You are given an array nums of size n consisting of distinct integers from 1 to n and a positive integer k.
|
||||
*
|
||||
* Return the number of non-empty subarrays in nums that have a median equal to k.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The median of an array is the middle element after sorting the array in ascending order. If the array is of even length, the median is the left middle element.
|
||||
* For example, the median of [2,3,1,4] is 2, and the median of [8,4,3,5,1] is 4.
|
||||
* A subarray is a contiguous part of an array.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static inline constexpr int sgn(int x) { return (x > 0) - (x < 0); }
|
||||
|
||||
public:
|
||||
static int countSubarrays(const std::vector<int>& nums, int k) {
|
||||
const int n = nums.size(), pos = std::find(nums.begin(), nums.end(), k) - nums.begin();
|
||||
std::vector<int> prefix(n);
|
||||
prefix[0] = sgn(nums[0] - k);
|
||||
for (int i = 1; i < n; ++i)
|
||||
prefix[i] = prefix[i - 1] + sgn(nums[i] - k);
|
||||
std::unordered_map<int, int> m;
|
||||
for (int i = 0; i < pos; ++i)
|
||||
++m[prefix[i]];
|
||||
++m[0];
|
||||
int ans = 0;
|
||||
for (int i = pos; i < n; ++i)
|
||||
ans += m[prefix[i]] + m[prefix[i] - 1];
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::countSubarrays({3,2,1,4,5}, 4);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#include <vector>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 106. Construct Binary Tree from Inorder and Postorder Traversal
|
||||
*
|
||||
* Given two integer arrays inorder and postorder where inorder is the inorder traversal of a binary tree and postorder is the postorder traversal of the same tree, construct and return the binary tree.
|
||||
*/
|
||||
|
||||
using VCI = std::vector<int>::const_iterator;
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static TreeNode* bT(VCI is, VCI ie, VCI ps, VCI pe) {
|
||||
if (is == ie || ps == pe)
|
||||
return nullptr;
|
||||
int r = *(pe - 1);
|
||||
int pos = std::find(is, ie, r) - is;
|
||||
return new TreeNode(
|
||||
r,
|
||||
bT(is, is + pos, ps, ps + pos),
|
||||
bT(is + pos + 1, ie, ps + pos, pe - 1)
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
static TreeNode* buildTree(const std::vector<int>& inorder, const std::vector<int>& postorder) {
|
||||
return bT(inorder.begin(), inorder.end(), postorder.begin(), postorder.end());
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Solution::buildTree({-1}, {-1});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2389. Longest Subsequence With Limited Sum
|
||||
*
|
||||
* You are given an integer array nums of length n, and an integer array queries of length m.
|
||||
* Return an array answer of length m where answer[i] is the maximum size of a subsequence that you can take from nums such that the sum of its elements is less than or equal to queries[i].
|
||||
* A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<int> answerQueries(std::vector<int>& n, const std::vector<int>& q) {
|
||||
std::sort(n.begin(), n.end());
|
||||
for (int i = 1; i < n.size(); ++i)
|
||||
n[i] += n[i - 1];
|
||||
std::vector<int> ret(q.size());
|
||||
for (int i = 0; i < q.size(); ++i)
|
||||
ret[i] = std::upper_bound(n.begin(), n.end(), q[i]) - n.begin();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<int> n {4,5,2,1};
|
||||
for (int i : Solution::answerQueries(n, {3,10,21}))
|
||||
std::cout << i << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 208. Implement Trie (Prefix Tree)
|
||||
*
|
||||
* A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
|
||||
*
|
||||
* Implement the Trie class:
|
||||
*
|
||||
* Trie() Initializes the trie object.
|
||||
* void insert(String word) Inserts the string word into the trie.
|
||||
* boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
|
||||
* boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.
|
||||
*/
|
||||
|
||||
struct TrieNode {
|
||||
TrieNode* p[26] = {};
|
||||
bool terminate = false;
|
||||
};
|
||||
|
||||
class Trie {
|
||||
private:
|
||||
TrieNode r;
|
||||
|
||||
public:
|
||||
Trie() = default;
|
||||
|
||||
void insert(const std::string& word) {
|
||||
TrieNode* ptr = &this->r;
|
||||
for (char i : word) {
|
||||
if (!ptr->p[i - 'a'])
|
||||
ptr->p[i - 'a'] = new TrieNode;
|
||||
ptr = ptr->p[i - 'a'];
|
||||
}
|
||||
ptr->terminate = true;
|
||||
}
|
||||
|
||||
bool search(const std::string& word) const {
|
||||
const TrieNode* ptr = &this->r;
|
||||
for (char i : word) {
|
||||
if (!ptr->p[i - 'a'])
|
||||
return false;
|
||||
ptr = ptr->p[i - 'a'];
|
||||
}
|
||||
return ptr && ptr->terminate;
|
||||
}
|
||||
|
||||
bool startsWith(const std::string& prefix) const {
|
||||
const TrieNode* ptr = &this->r;
|
||||
for (char i : prefix) {
|
||||
if (!ptr->p[i - 'a'])
|
||||
return false;
|
||||
ptr = ptr->p[i - 'a'];
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Trie trie;
|
||||
trie.insert("apple");
|
||||
std::cout << trie.search("apple"); // return True
|
||||
std::cout << trie.search("app"); // return False
|
||||
std::cout << trie.startsWith("app"); // return True
|
||||
trie.insert("app");
|
||||
std::cout << trie.search("app"); // return True
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 1616. Split Two Strings to Make Palindrome
|
||||
*
|
||||
* You are given two strings a and b of the same length. Choose an index and split both strings at the same index, splitting a into two strings: aprefix and asuffix where a = aprefix + asuffix, and splitting b into two strings: bprefix and bsuffix where b = bprefix + bsuffix. Check if aprefix + bsuffix or bprefix + asuffix forms a palindrome.
|
||||
* When you split a string s into sprefix and ssuffix, either ssuffix or sprefix is allowed to be empty. For example, if s = "abc", then "" + "abc", "a" + "bc", "ab" + "c" , and "abc" + "" are valid splits.
|
||||
* Return true if it is possible to form a palindrome string, otherwise return false.
|
||||
* Notice that x + y denotes the concatenation of strings x and y.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool checkPalindromeFormation(const std::string& a, const std::string& b) {
|
||||
const int m = a.length(), n = b.length();
|
||||
if (m == 1 || n == 1)
|
||||
return true;
|
||||
|
||||
// prefix[shorter](b) + suffix[longer](a)
|
||||
// prefix b, base a
|
||||
if (n >= ((m >> 1) + (m & 1))) {
|
||||
bool OK = true;
|
||||
// prefix (i) operates on a first and optionally switches to b
|
||||
// suffix (j) always operates on a
|
||||
for (int i = (m >> 1) - !(m & 1), j = m >> 1, switched = 0; i >= 0; --i, ++j) {
|
||||
if ((switched ? b : a)[i] == a[j])
|
||||
continue;
|
||||
switched = 1;
|
||||
if (b[i] == a[j])
|
||||
continue;
|
||||
OK = false;
|
||||
break;
|
||||
}
|
||||
if (OK) return true;
|
||||
}
|
||||
|
||||
// prefix(a) + suffix(b)
|
||||
// prefix a, base b
|
||||
if (m >= ((n >> 1) + (n & 1))) {
|
||||
bool OK = true;
|
||||
for (int i = (n >> 1) - !(n & 1), j = m >> 1, switched = 0; i >= 0; --i, ++j) {
|
||||
if ((switched ? a : b)[i] == b[j])
|
||||
continue;
|
||||
switched = 1;
|
||||
if (a[i] == b[j])
|
||||
continue;
|
||||
OK = false;
|
||||
break;
|
||||
}
|
||||
if (OK) return true;
|
||||
}
|
||||
|
||||
// prefix a, base a
|
||||
if (n >= m) {
|
||||
bool OK = true;
|
||||
for (int i = (m >> 1) - !(m & 1), j = m >> 1, switched = 0; i >= 0; --i, ++j) {
|
||||
if (((switched |= (j >= m)) ? b : a)[j] == a[i])
|
||||
continue;
|
||||
switched = 1;
|
||||
if (a[i] == b[j])
|
||||
continue;
|
||||
OK = false;
|
||||
break;
|
||||
}
|
||||
if (OK) return true;
|
||||
}
|
||||
|
||||
// prefix b, base b
|
||||
if (m >= n) {
|
||||
bool OK = true;
|
||||
for (int i = (n >> 1) - !(n & 1), j = m >> 1, switched = 0; i >= 0; --i, ++j) {
|
||||
if (((switched |= (j >= n)) ? a : b)[j] == b[i])
|
||||
continue;
|
||||
switched = 1;
|
||||
if (b[i] == a[j])
|
||||
continue;
|
||||
OK = false;
|
||||
break;
|
||||
}
|
||||
if (OK) return true;
|
||||
}
|
||||
|
||||
// can NEVER reach here
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
bool ans = Solution::checkPalindromeFormation(
|
||||
"aejbaalflrmkswrydwdkdwdyrwskmrlfqizjezd",
|
||||
"uvebspqckawkhbrtlqwblfwzfptanhiglaabjea"
|
||||
);
|
||||
std::printf(ans ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 1472. Design Browser History
|
||||
*
|
||||
* You have a browser of one tab where you start on the homepage and you can visit another url, get back in the history number of steps or move forward in the history number of steps.
|
||||
*
|
||||
* Implement the BrowserHistory class:
|
||||
*
|
||||
* BrowserHistory(string homepage) Initializes the object with the homepage of the browser.
|
||||
* void visit(string url) Visits url from the current page. It clears up all the forward history.
|
||||
* string back(int steps) Move steps back in history. If you can only return x steps in the history and steps > x, you will return only x steps. Return the current url after moving back in history at most steps.
|
||||
* string forward(int steps) Move steps forward in history. If you can only forward x steps in the history and steps > x, you will forward only x steps. Return the current url after forwarding in history at most steps.
|
||||
*/
|
||||
|
||||
class BrowserHistory {
|
||||
private:
|
||||
int pos = 0, cap = 0;
|
||||
std::vector<std::string> s;
|
||||
|
||||
public:
|
||||
explicit BrowserHistory(const std::string& homepage) {
|
||||
s.push_back(homepage);
|
||||
}
|
||||
|
||||
void visit(const std::string& url) {
|
||||
if ((cap = ++pos) == s.size())
|
||||
s.push_back(url);
|
||||
else
|
||||
s[pos] = url;
|
||||
}
|
||||
|
||||
std::string back(int steps) {
|
||||
return s[pos = std::max(0, pos - steps)];
|
||||
}
|
||||
|
||||
std::string forward(int steps) {
|
||||
return s[pos = std::min(cap, pos + steps)];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include <string>
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 1625. Lexicographically Smallest String After Applying Operations
|
||||
*
|
||||
* You are given a string s of even length consisting of digits from 0 to 9, and two integers a and b.
|
||||
*
|
||||
* You can apply either of the following two operations any number of times and in any order on s:
|
||||
*
|
||||
* Add a to all odd indices of s (0-indexed). Digits post 9 are cycled back to 0. For example, if s = "3456" and a = 5, s becomes "3951".
|
||||
* Rotate s to the right by b positions. For example, if s = "3456" and b = 1, s becomes "6345".
|
||||
* Return the lexicographically smallest string you can obtain by applying the above operations any number of times on s.
|
||||
*
|
||||
* A string a is lexicographically smaller than a string b (of the same length) if in the first position where a and b differ, string a has a letter that appears earlier in the alphabet than the corresponding letter in b. For example, "0158" is lexicographically smaller than "0190" because the first position they differ is at the third letter, and '5' comes before '9'.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static inline std::string rotate(const std::string& s, int b) {
|
||||
return b == s.length() ? s : (s.substr(s.length() - b) + s.substr(0, s.length() - b));
|
||||
}
|
||||
|
||||
static inline std::string plus(std::string s, int a) {
|
||||
for (int i = 1; i < s.length(); i += 2)
|
||||
s[i] = '0' + (s[i] - '0' + a) % 10;
|
||||
return s;
|
||||
}
|
||||
|
||||
public:
|
||||
static std::string findLexSmallestString(std::string s, int a, int b) {
|
||||
std::queue<std::string> q;
|
||||
std::unordered_set<std::string> set;
|
||||
q.push(s);
|
||||
set.insert(s);
|
||||
while (!q.empty()) {
|
||||
std::string str = q.front();
|
||||
q.pop();
|
||||
std::string rot = rotate(str, b);
|
||||
if (!set.count(rot)) {
|
||||
set.insert(rot);
|
||||
q.push(std::move(rot));
|
||||
}
|
||||
std::string add = plus(str, a);
|
||||
if (!set.count(add)) {
|
||||
set.insert(add);
|
||||
q.push(std::move(add));
|
||||
}
|
||||
if (str < s)
|
||||
s = std::move(str);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::findLexSmallestString("5525", 9, 2);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include <string>
|
||||
#include <queue>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 211. Design Add and Search Words Data Structure
|
||||
* Design a data structure that supports adding new words and finding if a string matches any previously added string.
|
||||
*
|
||||
* Implement the WordDictionary class:
|
||||
*
|
||||
* WordDictionary() Initializes the object.
|
||||
* void addWord(word) Adds word to the data structure, it can be matched later.
|
||||
* bool search(word) Returns true if there is any string in the data structure that matches word or false otherwise. word may contain dots '.' where dots can be matched with any letter.
|
||||
*
|
||||
* Refer: 220128.cpp (it does not accept this solution now. 19/03/'23)
|
||||
* And it should not fail, since the time complexity of BFS and DFS are the same (O(n), where n is the number of nodes)
|
||||
*/
|
||||
|
||||
struct TrieNode {
|
||||
TrieNode* p[26] = {};
|
||||
bool terminate = false;
|
||||
};
|
||||
|
||||
class WordDictionary {
|
||||
private:
|
||||
TrieNode r;
|
||||
|
||||
static bool dfs(const TrieNode* const ptr, const char* const str) {
|
||||
if (!*str)
|
||||
return ptr->terminate;
|
||||
if (*str == '.') {
|
||||
for (const TrieNode* const i : ptr->p)
|
||||
if (i && dfs(i, str + 1))
|
||||
return true;
|
||||
} else if (ptr->p[*str - 'a'] && dfs(ptr->p[*str - 'a'], str + 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
WordDictionary() = default;
|
||||
|
||||
void addWord(const std::string& word) {
|
||||
TrieNode* ptr = &r;
|
||||
for (char i : word) {
|
||||
if (!ptr->p[i - 'a'])
|
||||
ptr->p[i - 'a'] = new TrieNode;
|
||||
ptr = ptr->p[i - 'a'];
|
||||
}
|
||||
ptr->terminate = true;
|
||||
}
|
||||
|
||||
bool search(const std::string& word) const {
|
||||
const char* const str = word.c_str();
|
||||
return dfs(&r, str);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
WordDictionary wordDictionary;
|
||||
wordDictionary.addWord("bad");
|
||||
wordDictionary.addWord("dad");
|
||||
wordDictionary.addWord("mad");
|
||||
std::cout << wordDictionary.search("pad"); // return False
|
||||
std::cout << wordDictionary.search("bad"); // return True
|
||||
std::cout << wordDictionary.search(".ad"); // return True
|
||||
std::cout << wordDictionary.search("b.."); // return True
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 605. Can Place Flowers
|
||||
* You have a long flowerbed in which some of the plots are planted, and some are not. However, flowers cannot be planted in adjacent plots.
|
||||
* Given an integer array flowerbed containing 0's and 1's, where 0 means empty and 1 means not empty, and an integer n, return if n new flowers can be planted in the flowerbed without violating the no-adjacent-flowers rule.
|
||||
*
|
||||
* Refer: 220118.cpp
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool canPlaceFlowers(const std::vector<int>& flowerbed, int n) {
|
||||
int cont0 = 1;
|
||||
for (int i : flowerbed) {
|
||||
if (i) {
|
||||
n -= (cont0 - 1) / 2;
|
||||
cont0 = 0;
|
||||
} else ++cont0;
|
||||
}
|
||||
return (n - cont0 / 2) <= 0;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 2469. Convert the Temperature
|
||||
*
|
||||
* You are given a non-negative floating point number rounded to two decimal places celsius, that denotes the temperature in Celsius.
|
||||
* You should convert Celsius into Kelvin and Fahrenheit and return it as an array ans = [kelvin, fahrenheit].
|
||||
* Return the array ans. Answers within 10-5 of the actual answer will be accepted.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<double> convertTemperature(double c) {
|
||||
return {c + 273.15, c * 1.8 + 32.0};
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2348. Number of Zero-Filled Subarrays
|
||||
*
|
||||
* Given an integer array nums, return the number of subarrays filled with 0.
|
||||
* A subarray is a contiguous non-empty sequence of elements within an array.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static constexpr long long f(long long x) {
|
||||
return x * (x + 1) / 2;
|
||||
}
|
||||
|
||||
public:
|
||||
static long long zeroFilledSubarray(const std::vector<int>& n) {
|
||||
long long ans = 0;
|
||||
int c = 0;
|
||||
for (int i : n) {
|
||||
if (i) {
|
||||
ans += f(c);
|
||||
c = 0;
|
||||
} else ++c;
|
||||
}
|
||||
return ans + f(c);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::zeroFilledSubarray({2,10,2019});
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,58 @@
|
|||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2492. Minimum Score of a Path Between Two Cities
|
||||
*
|
||||
* You are given a positive integer n representing n cities numbered from 1 to n. You are also given a 2D array roads where roads[i] = [ai, bi, distancei] indicates that there is a bidirectional road between cities ai and bi with a distance equal to distancei. The cities graph is not necessarily connected.
|
||||
*
|
||||
* The score of a path between two cities is defined as the minimum distance of a road in this path.
|
||||
*
|
||||
* Return the minimum possible score of a path between cities 1 and n.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* A path is a sequence of roads between two cities.
|
||||
* It is allowed for a path to contain the same road multiple times, and you can visit cities 1 and n multiple times along the path.
|
||||
* The test cases are generated such that there is at least one path between 1 and n.
|
||||
*/
|
||||
|
||||
class UnionFindSet {
|
||||
private:
|
||||
std::vector<int> f;
|
||||
|
||||
public:
|
||||
explicit UnionFindSet(int n) : f(n + 1) {
|
||||
std::iota(f.begin(), f.end(), 0);
|
||||
}
|
||||
|
||||
int find(int x) {
|
||||
return (x == f[x]) ? x : (f[x] = find(f[x]));
|
||||
}
|
||||
|
||||
// Merge y to x
|
||||
int uni(int x, int y) {
|
||||
return f[find(y)] = find(x);
|
||||
}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minScore(int n, const std::vector<std::vector<int>>& roads) {
|
||||
UnionFindSet ufs(n);
|
||||
for (const auto & road : roads)
|
||||
ufs.uni(road[0], road[1]);
|
||||
int ret = 0x7FFFFFFF;
|
||||
const int f1 = ufs.find(1);
|
||||
for (const auto& road: roads)
|
||||
if (ufs.find(road[0]) == f1)
|
||||
ret = std::min(ret, road[2]);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::minScore(14, {{2,9,2308},{2,5,2150},{12,3,4944},{13,5,5462},{2,10,2187},{2,12,8132},{2,13,3666},{4,14,3019},{2,4,6759},{2,14,9869},{1,10,8147},{3,4,7971},{9,13,8026},{5,12,9982},{10,9,6459}});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
#include <vector>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <concepts>
|
||||
|
||||
template<typename T>
|
||||
requires std::totally_ordered<T>
|
||||
class MinMaxSegTree {
|
||||
private:
|
||||
using V = std::vector<T>;
|
||||
using OF = const T& (*)(const T&, const T&);
|
||||
using BTF = std::function<T(int, int, int, const V&, V&, OF)>;
|
||||
|
||||
int n;
|
||||
V s, b;
|
||||
|
||||
static constexpr inline int calc(int n) {
|
||||
for (int i = 1; ; i <<= 1)
|
||||
if (i >= n)
|
||||
return i << 1;
|
||||
}
|
||||
|
||||
T query(int L, int R, int qL, int qR, int pos, const V& tree, OF op) const {
|
||||
if (L == qL && R == qR)
|
||||
return tree[pos];
|
||||
const int qM = (qL + qR) >> 1;
|
||||
if (R <= qM)
|
||||
return query(L, R, qL, qM, pos << 1, tree, op);
|
||||
if (qM <= L)
|
||||
return query(L, R, qM, qR, 1 | (pos << 1), tree, op);
|
||||
return op(query(L, qM, qL, qM, pos << 1, tree, op), query(qM, R, qM, qR, 1 | (pos << 1), tree, op));
|
||||
}
|
||||
|
||||
public:
|
||||
explicit MinMaxSegTree(const std::vector<T>& d) : n(d.size()), s(calc(n)), b(calc(n)) {
|
||||
BTF dfs = [&](int L, int R, int pos, const V& src, V& dst, OF op) {
|
||||
if (L == R - 1)
|
||||
return dst[pos] = src[L];
|
||||
const int M = (L + R) >> 1;
|
||||
return dst[pos] = op(dfs(L, M, pos << 1, src, dst, op), dfs(M, R, 1 | (pos << 1), src, dst, op));
|
||||
};
|
||||
dfs(0, n, 1, d, s, std::min);
|
||||
dfs(0, n, 1, d, b, std::max);
|
||||
}
|
||||
|
||||
T min(int L, int R) const {
|
||||
return query(L, R, 0, n, 1, s, std::min);
|
||||
}
|
||||
|
||||
T max(int L, int R) const {
|
||||
return query(L, R, 0, n, 1, b, std::max);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1630. Arithmetic Subarrays
|
||||
*
|
||||
* A sequence of numbers is called arithmetic if it consists of at least two elements, and the difference between every two consecutive elements is the same. More formally, a sequence s is arithmetic if and only if s[i+1] - s[i] == s[1] - s[0] for all valid i.
|
||||
*
|
||||
* For example, these are arithmetic sequences:
|
||||
*
|
||||
* 1, 3, 5, 7, 9
|
||||
* 7, 7, 7, 7
|
||||
* 3, -1, -5, -9
|
||||
* The following sequence is not arithmetic:
|
||||
*
|
||||
* 1, 1, 2, 5, 7
|
||||
* You are given an array of n integers, nums, and two arrays of m integers each, l and r, representing the m range queries, where the ith query is the range [l[i], r[i]]. All the arrays are 0-indexed.
|
||||
*
|
||||
* Return a list of boolean elements answer, where answer[i] is true if the subarray nums[l[i]], nums[l[i]+1], ... , nums[r[i]] can be rearranged to form an arithmetic sequence, and false otherwise.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<bool> checkArithmeticSubarrays(
|
||||
const std::vector<int>& nums,
|
||||
const std::vector<int>& l,
|
||||
const std::vector<int>& r
|
||||
) {
|
||||
auto tree = new MinMaxSegTree(nums);
|
||||
const int n = l.size(), k = nums.size();
|
||||
std::unordered_multimap<int, int> m;
|
||||
for (int i = 0; i < k; ++i)
|
||||
m.insert({nums[i], i});
|
||||
std::vector<bool> ret(n);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const int L = l[i], R = r[i] + 1, min = tree->min(L, R), max = tree->max(L, R);
|
||||
if ((max - min) % (R - L - 1))
|
||||
continue;
|
||||
int step = (max - min) / (R - L - 1);
|
||||
bool OK = true;
|
||||
for (int j = step + min; j < max; j += step) {
|
||||
const auto [MERs, MERe] = m.equal_range(j);
|
||||
if (!(OK = std::any_of(MERs, MERe, [L, R](auto&& x) { return x.second < R && x.second >= L; })))
|
||||
break;
|
||||
}
|
||||
ret[i] = OK;
|
||||
}
|
||||
delete tree;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto r = Solution::checkArithmeticSubarrays({-3,-6,-8,-4,-2,-8,-6,0,0,0,0},{1},{4});
|
||||
for (auto&& i : r) {
|
||||
std::cout << (i ? "true\n" : "false\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
|
||||
class UnionFindSet {
|
||||
private:
|
||||
std::vector<int> f;
|
||||
|
||||
public:
|
||||
explicit UnionFindSet(int n) : f(n + 1) {
|
||||
std::iota(f.begin(), f.end(), 0);
|
||||
}
|
||||
|
||||
int find(int x) {
|
||||
return (x == f[x]) ? x : (f[x] = find(f[x]));
|
||||
}
|
||||
|
||||
// Merge y to x
|
||||
int uni(int x, int y) {
|
||||
return f[find(y)] = find(x);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1319. Number of Operations to Make Network Connected
|
||||
*
|
||||
* There are n computers numbered from 0 to n - 1 connected by ethernet cables connections forming a network where connections[i] = [ai, bi] represents a connection between computers ai and bi. Any computer can reach any other computer directly or indirectly through the network.
|
||||
*
|
||||
* You are given an initial computer network connections. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected.
|
||||
*
|
||||
* Return the minimum number of times you need to do this in order to make all the computers connected. If it is not possible, return -1.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int makeConnected(int n, const std::vector<std::vector<int>>& connections) {
|
||||
if (connections.size() < n - 1)
|
||||
return -1;
|
||||
UnionFindSet ufs(n);
|
||||
for (const auto& i : connections)
|
||||
ufs.uni(i[0], i[1]);
|
||||
std::unordered_set<int> s;
|
||||
for (int i = 0; i < n; ++i)
|
||||
s.insert(ufs.find(i));
|
||||
return s.size() - 1;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
class KMP {
|
||||
private:
|
||||
std::string str;
|
||||
std::vector<int> m;
|
||||
int pos = 0;
|
||||
|
||||
public:
|
||||
explicit KMP(std::string s) : str(std::move(s)), m(str.length()) {
|
||||
for (int i = 1; i < str.length(); ++i) {
|
||||
int j = m[i - 1];
|
||||
for (; j > 0 && str[j] != str[i]; j = m[j - 1]);
|
||||
m[i] = j + (str[i] == str[j]);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& get_string() const {
|
||||
return str;
|
||||
}
|
||||
|
||||
bool advance(char ch) {
|
||||
if (ch == str[pos]) {
|
||||
++pos;
|
||||
} else {
|
||||
for (; pos > 0 && str[pos] != ch; pos = m[pos - 1]);
|
||||
pos += str[pos] == ch;
|
||||
}
|
||||
if (pos == str.length()) {
|
||||
pos = m[pos - 1];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1032. Stream of Characters
|
||||
*
|
||||
* Design an algorithm that accepts a stream of characters and checks if a suffix of these characters is a string of a given array of strings words.
|
||||
*
|
||||
* For example, if words = ["abc", "xyz"] and the stream added the four characters (one by one) 'a', 'x', 'y', and 'z', your algorithm should detect that the suffix "xyz" of the characters "axyz" matches "xyz" from words.
|
||||
*
|
||||
* Implement the StreamChecker class:
|
||||
*
|
||||
* StreamChecker(String[] words) Initializes the object with the strings array words.
|
||||
* boolean query(char letter) Accepts a new character from the stream and returns true if any non-empty suffix from the stream forms a word that is in words.
|
||||
*/
|
||||
|
||||
class StreamChecker {
|
||||
private:
|
||||
std::vector<KMP> sms;
|
||||
|
||||
public:
|
||||
explicit StreamChecker(const std::vector<std::string>& words) {
|
||||
sms.reserve(words.size());
|
||||
for (const std::string& i : words)
|
||||
sms.emplace_back(i);
|
||||
}
|
||||
|
||||
bool query(char c) {
|
||||
bool ret = false;
|
||||
for (KMP& sm : sms)
|
||||
ret |= sm.advance(c);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
StreamChecker sc({"acacac"});
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
std::cout << sc.query('a') << sc.query('c');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 1466. Reorder Routes to Make All Paths Lead to the City Zero
|
||||
*
|
||||
* There are n cities numbered from 0 to n - 1 and n - 1 roads such that there is only one way to travel between two different cities (this network form a tree). Last year, The ministry of transport decided to orient the roads in one direction because they are too narrow.
|
||||
* Roads are represented by connections where connections[i] = [ai, bi] represents a road from city ai to city bi.
|
||||
* This year, there will be a big event in the capital (city 0), and many people want to travel to this city.
|
||||
* Your task consists of reorienting some roads such that each city can visit the city 0. Return the minimum number of edges changed.
|
||||
* It's guaranteed that each city can reach city 0 after reorder.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minReorder(int n, const std::vector<std::vector<int>>& connections) {
|
||||
std::vector<std::unordered_set<int>> vs(n);
|
||||
for (const auto& i : connections) {
|
||||
vs[i[0]].insert(-i[1]);
|
||||
vs[i[1]].insert(i[0]);
|
||||
}
|
||||
std::vector<bool> vis(n);
|
||||
std::function<int(int)> dfs = [&](int cur) {
|
||||
vis[cur] = true;
|
||||
int ret = 0;
|
||||
for (int nx : vs[cur])
|
||||
if (!vis[std::abs(nx)])
|
||||
ret += (nx < 0) + dfs(std::abs(nx));
|
||||
return ret;
|
||||
};
|
||||
return dfs(0);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::minReorder(6, {
|
||||
{0, 1}, {1, 3}, {2, 3}, {4, 0}, {4, 5}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
int findLengthOfShortestSUBSEQUENCE(const std::vector<int>& arr) {
|
||||
const int n = arr.size();
|
||||
std::map<int, int> m;
|
||||
std::vector<int> dp(n);
|
||||
m[arr[0]] = dp[0] = 1;
|
||||
int ans = 1;
|
||||
for (int i = 1; i < n; ++i) {
|
||||
auto it = m.upper_bound(arr[i]);
|
||||
if (it == m.begin())
|
||||
ans = std::max(ans, m[arr[i]] = dp[i] = 1);
|
||||
else
|
||||
ans = std::max(ans, m[arr[i]] = dp[i] = 1 + (--it)->second);
|
||||
}
|
||||
return n - ans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1574. Shortest Subarray to be Removed to Make Array Sorted
|
||||
*
|
||||
* Given an integer array arr, remove a subarray (can be empty) from arr such that the remaining elements in arr are non-decreasing.
|
||||
* Return the length of the shortest subarray to remove.
|
||||
* A subarray is a contiguous subsequence of the array.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int findLengthOfShortestSubarray(const std::vector<int>& arr) {
|
||||
const int n = arr.size();
|
||||
const int* d = arr.data();
|
||||
int L = 0, R = n - 1;
|
||||
for (; L + 1 < n && d[L + 1] >= d[L]; ++L);
|
||||
for (; R && d[R - 1] <= d[R]; --R);
|
||||
if (L >= R)
|
||||
return 0;
|
||||
int ans = ++L;
|
||||
for (int i = n - 1; i >= R; --i)
|
||||
ans = std::max(ans, int(std::upper_bound(d, d + L, d[i]) - d + n - i));
|
||||
return n - ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Solution::findLengthOfShortestSubarray({10,13,17,21,15,15,9,17,22,22,13});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
class UnionFindSet {
|
||||
private:
|
||||
std::vector<int> f;
|
||||
|
||||
public:
|
||||
explicit UnionFindSet(int n) : f(n + 1) {
|
||||
std::iota(f.begin(), f.end(), 0);
|
||||
}
|
||||
|
||||
int find(int x) {
|
||||
return (x == f[x]) ? x : (f[x] = find(f[x]));
|
||||
}
|
||||
|
||||
// Merge y to x
|
||||
int uni(int x, int y) {
|
||||
return f[find(y)] = find(x);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 2316. Count Unreachable Pairs of Nodes in an Undirected Graph
|
||||
*
|
||||
* You are given an integer n. There is an undirected graph with n nodes, numbered from 0 to n - 1. You are given a 2D integer array edges where edges[i] = [ai, bi] denotes that there exists an undirected edge connecting nodes ai and bi.
|
||||
* Return the number of pairs of different nodes that are unreachable from each other.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static long long countPairs(int n, const std::vector<std::vector<int>>& edges) {
|
||||
UnionFindSet ufs(n);
|
||||
for (auto&& i : edges)
|
||||
ufs.uni(i[0], i[1]);
|
||||
std::unordered_map<int, int> m;
|
||||
for (int i = 0; i < n; ++i)
|
||||
++m[ufs.find(i)];
|
||||
long long ret = 0;
|
||||
for (auto&& [_, cnt] : m)
|
||||
ret += (long long)(n - cnt) * (long long)(cnt);
|
||||
return ret >> 1;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::countPairs(7, {
|
||||
{0,2},{0,5},{2,4},{1,6},{5,4}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
/**
|
||||
* 2395. Find Subarrays With Equal Sum
|
||||
*
|
||||
* Given a 0-indexed integer array nums, determine whether there exist two subarrays of length 2 with equal sum. Note that the two subarrays must begin at different indices.
|
||||
* Return true if these subarrays exist, and false otherwise.
|
||||
* A subarray is a contiguous non-empty sequence of elements within an array.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool findSubarrays(const std::vector<int>& nums) {
|
||||
const int n = nums.size();
|
||||
std::unordered_set<int> s;
|
||||
for (int i = 1; i < n; ++i)
|
||||
if (s.count(nums[i] + nums[i - 1]))
|
||||
return true;
|
||||
else
|
||||
s.insert(nums[i] + nums[i - 1]);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 1638. Count Substrings That Differ by One Character
|
||||
*
|
||||
* Given two strings s and t, find the number of ways you can choose a non-empty substring of s and replace a single character by a different character such that the resulting substring is a substring of t. In other words, find the number of substrings in s that differ from some substring in t by exactly one character.
|
||||
* For example, the underlined substrings in "computer" and "computation" only differ by the 'e'/'a', so this is a valid way.
|
||||
* Return the number of substrings that satisfy the condition above.
|
||||
* A substring is a contiguous sequence of characters within a string.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int countSubstrings(const std::string& s, const std::string& t) {
|
||||
const int m = s.length(), n = t.length();
|
||||
auto count = [m, n, &s, &t](int x, int y) {
|
||||
bool cap = false;
|
||||
int cnt = 0;
|
||||
for (int i = x, j = y; i < m && j < n; ++i, ++j) {
|
||||
if (s[i] != t[j]) {
|
||||
if (cap) break;
|
||||
else cap = true;
|
||||
}
|
||||
if (cap) ++cnt;
|
||||
}
|
||||
return cnt;
|
||||
};
|
||||
int ans = 0;
|
||||
for (int i = 0; i < m; ++i)
|
||||
for (int j = 0; j < n; ++j)
|
||||
ans += count(i, j);
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 64. Minimum Path Sum
|
||||
*
|
||||
* Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right, which minimizes the sum of all numbers along its path.
|
||||
* Note: You can only move either down or right at any point in time.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minPathSum(std::vector<std::vector<int>>& G) {
|
||||
const int m = G.size(), n = G.front().size();
|
||||
for (int i = m - 1; i >= 0; --i)
|
||||
for (int j = n - 1; j >= 0; --j)
|
||||
G[i][j] +=
|
||||
(i + 1 < m && j + 1 < n) ?
|
||||
std::min(G[i + 1][j], G[i][j + 1]) :
|
||||
((i + 1 < m ? G[i + 1][j] : 0) + (j + 1 < n ? G[i][j + 1] : 0));
|
||||
return G[0][0];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 983. Minimum Cost For Tickets
|
||||
*
|
||||
* You have planned some train traveling one year in advance. The days of the year in which you will travel are given as an integer array days. Each day is an integer from 1 to 365.
|
||||
*
|
||||
* Train tickets are sold in three different ways:
|
||||
*
|
||||
* a 1-day pass is sold for costs[0] dollars,
|
||||
* a 7-day pass is sold for costs[1] dollars, and
|
||||
* a 30-day pass is sold for costs[2] dollars.
|
||||
* The passes allow that many days of consecutive travel.
|
||||
*
|
||||
* For example, if we get a 7-day pass on day 2, then we can travel for 7 days: 2, 3, 4, 5, 6, 7, and 8.
|
||||
* Return the minimum number of dollars you need to travel every day in the given list of days.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int mincostTickets(const std::vector<int>& d, const std::vector<int>& c) {
|
||||
int dp[400]{};
|
||||
std::vector<bool> vis(400);
|
||||
std::for_each(d.begin(), d.end(), [&vis](int x) { vis[x] = true; });
|
||||
for (int i = 365; i; --i) {
|
||||
if (!vis[i]) {
|
||||
dp[i] = dp[i + 1];
|
||||
} else {
|
||||
dp[i] = std::min(dp[i + 1] + c[0], dp[i + 7] + c[1]);
|
||||
dp[i] = std::min(dp[i], dp[i + 30] + c[2]);
|
||||
}
|
||||
}
|
||||
return dp[1];
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::mincostTickets(
|
||||
{1,2,3,4,5,6,7,8,9,10,30,31},
|
||||
{2,7,15}
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#include <iostream>
|
||||
|
||||
class SolutionCalc {
|
||||
private:
|
||||
static constexpr inline int CI(int n, int x) {
|
||||
if (n <= 1)
|
||||
return 1;
|
||||
int ret = 0;
|
||||
for (int i = 1; i <= x; ++i)
|
||||
ret += CI(n - 1, i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr inline int countVowelStrings(int n) {
|
||||
return CI(n, 1) + CI(n, 2) + CI(n, 3) + CI(n, 4) + CI(n, 5);
|
||||
}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static constexpr inline int ANS[] = {
|
||||
5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650, 14950,
|
||||
17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905, 66045, 73815, 82251, 91390, 101270, 111930, 123410, 135751,
|
||||
148995, 163185, 178365, 194580, 211876, 230300, 249900, 270725, 292825, 316251,
|
||||
};
|
||||
|
||||
public:
|
||||
static constexpr inline int countVowelStrings(int n) {
|
||||
return ANS[n - 1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
for (int i = 1; i <= 50; ++i)
|
||||
std::cout << SolutionCalc::countVowelStrings(i) << ", ";
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 1402. Reducing Dishes
|
||||
*
|
||||
* A chef has collected data on the satisfaction level of his n dishes. Chef can cook any dish in 1 unit of time.
|
||||
* Like-time coefficient of a dish is defined as the time taken to cook that dish including previous dishes multiplied by its satisfaction level i.e. time[i] * satisfaction[i].
|
||||
* Return the maximum sum of like-time coefficient that the chef can obtain after dishes preparation.
|
||||
* Dishes can be prepared in any order and the chef can discard some dishes to get this maximum value.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int maxSatisfaction(const std::vector<int>& sa) {
|
||||
const int n = sa.size();
|
||||
std::vector<int> s(n);
|
||||
std::partial_sort_copy(sa.begin(), sa.end(), s.begin(), s.end());
|
||||
int ans = std::max(0, s[n - 1]);
|
||||
for (int i = n - 2, cur = s[n - 1]; i >= 0; --i)
|
||||
ans = std::max(ans, cur += (s[i] += s[i + 1]));
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Solution::maxSatisfaction({-1,-8,0,5,-9});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* 1637. Widest Vertical Area Between Two Points Containing No Points
|
||||
*
|
||||
* Given n points on a 2D plane where points[i] = [xi, yi], Return the widest vertical area between two points such that no points are inside the area.
|
||||
* A vertical area is an area of fixed-width extending infinitely along the y-axis (i.e., infinite height). The widest vertical area is the one with the maximum width.
|
||||
* Note that points on the edge of a vertical area are not considered included in the area.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static auto maxWidthOfVerticalArea(const std::vector<std::vector<int>>& p) {
|
||||
std::set<int> v;
|
||||
std::transform(p.begin(), p.end(), std::inserter(v, v.begin()), [](auto&& x) { return x[0]; });
|
||||
auto r = 0;
|
||||
for (auto i = std::next(v.begin()); i != v.end(); ++i)
|
||||
r = std::max(r, *i - *std::prev(i));
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 87. Scramble String
|
||||
* We can scramble a string s to get a string t using the following algorithm:
|
||||
*
|
||||
* If the length of the string is 1, stop.
|
||||
* If the length of the string is > 1, do the following:
|
||||
* Split the string into two non-empty substrings at a random index, i.e., if the string is s, divide it to x and y where s = x + y.
|
||||
* Randomly decide to swap the two substrings or to keep them in the same order. i.e., after this step, s may become s = x + y or s = y + x.
|
||||
* Apply step 1 recursively on each of the two substrings x and y.
|
||||
* Given two strings s1 and s2 of the same length, return true if s2 is a scrambled string of s1, otherwise, return false.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
// Const Char Pointer
|
||||
using CCP = const char*;
|
||||
|
||||
CCP s = nullptr, t = nullptr;
|
||||
int dp[31][31][31][31]{};
|
||||
|
||||
bool f(int m, int n, int p, int q) {
|
||||
if (m + 1 == n)
|
||||
return s[m] == t[p];
|
||||
int& ans = dp[m][n][p][q];
|
||||
if (ans)
|
||||
return (ans + 1);
|
||||
ans = 1;
|
||||
for (int i = m, j = p; i < n; ++i, ++j) {
|
||||
if (s[i] != t[j]) {
|
||||
ans = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ans)
|
||||
return ans;
|
||||
for (int i = m + 1; i < n; ++i) {
|
||||
if (f(m, i, p, p - m + i) && f(i, n, p - m + i, q))
|
||||
return ans = 1;
|
||||
if (f(m, i, q - (i - m), q) && f(i, n, p, q - (i - m)))
|
||||
return ans = 1;
|
||||
}
|
||||
ans = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool isScramble(const std::string& s1, const std::string& s2) {
|
||||
s = s1.c_str();
|
||||
t = s2.c_str();
|
||||
return f(0, s1.length(), 0, s2.length());
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 2367. Number of Arithmetic Triplets
|
||||
*
|
||||
* You are given a 0-indexed, strictly increasing integer array nums and a positive integer diff. A triplet (i, j, k) is an arithmetic triplet if the following conditions are met:
|
||||
*
|
||||
* i < j < k,
|
||||
* nums[j] - nums[i] == diff, and
|
||||
* nums[k] - nums[j] == diff.
|
||||
* Return the number of unique arithmetic triplets.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int arithmeticTriplets(const std::vector<int>& nums, int diff) {
|
||||
std::unordered_set<int> s(nums.begin(), nums.end());
|
||||
return std::count_if(nums.begin(), nums.end(), [&](int x) {
|
||||
return s.count(x + diff) && s.count(x + 2 * diff);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
|
||||
PROJECT(2303)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
ADD_EXECUTABLE(2303 230330.cpp)
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* 831. Masking Personal Information
|
||||
*
|
||||
* You are given a personal information string s, representing either an email address or a phone number. Return the masked personal information using the below rules.
|
||||
*
|
||||
* Email address:
|
||||
*
|
||||
* An email address is:
|
||||
*
|
||||
* A name consisting of uppercase and lowercase English letters, followed by
|
||||
* The '@' symbol, followed by
|
||||
* The domain consisting of uppercase and lowercase English letters with a dot '.' somewhere in the middle (not the first or last character).
|
||||
* To mask an email:
|
||||
*
|
||||
* The uppercase letters in the name and domain must be converted to lowercase letters.
|
||||
* The middle letters of the name (i.e., all but the first and last letters) must be replaced by 5 asterisks "*****".
|
||||
* Phone number:
|
||||
*
|
||||
* A phone number is formatted as follows:
|
||||
*
|
||||
* The phone number contains 10-13 digits.
|
||||
* The last 10 digits make up the local number.
|
||||
* The remaining 0-3 digits, in the beginning, make up the country code.
|
||||
* Separation characters from the set {'+', '-', '(', ')', ' '} separate the above digits in some way.
|
||||
* To mask a phone number:
|
||||
*
|
||||
* Remove all separation characters.
|
||||
* The masked phone number should have the form:
|
||||
* "***-***-XXXX" if the country code has 0 digits.
|
||||
* "+*-***-***-XXXX" if the country code has 1 digit.
|
||||
* "+**-***-***-XXXX" if the country code has 2 digits.
|
||||
* "+***-***-***-XXXX" if the country code has 3 digits.
|
||||
* "XXXX" is the last 4 digits of the local number.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static auto mail(const std::string& s) {
|
||||
auto pos = s.find('@');
|
||||
std::string ret;
|
||||
ret += std::tolower(s[0]);
|
||||
ret += "*****";
|
||||
ret += std::tolower(s[pos - 1]);
|
||||
ret += '@';
|
||||
for (int i = pos + 1; i < s.length(); ++i)
|
||||
ret += std::tolower(s[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static auto phone(const std::string& s) {
|
||||
auto cnt = std::count_if(s.begin(), s.end(), [&](auto&& x) { return std::isdigit(x); });
|
||||
std::string t;
|
||||
std::copy_if(s.begin(), s.end(), std::back_inserter(t), [](auto&& x) { return std::isdigit(x); });
|
||||
return (!(cnt - 10) ? std::string() : "+" + std::string(cnt - 10, '*') + '-') + "***-***-" + t.substr(t.length() - 4, 4);
|
||||
}
|
||||
|
||||
public:
|
||||
static auto maskPII(const std::string& s) {
|
||||
return ((s.find('@') != -1) ? mail : phone)(s);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 704. Binary Search
|
||||
*
|
||||
* Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.
|
||||
* You must write an algorithm with O(log n) runtime complexity.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int search(const std::vector<int>& nums, int target) {
|
||||
auto it = std::lower_bound(nums.begin(), nums.end(), target);
|
||||
return (it != nums.end() && target == *it) ? it - nums.begin() : -1;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1039. Minimum Score Triangulation of Polygon
|
||||
*
|
||||
* You have a convex n-sided polygon where each vertex has an integer value. You are given an integer array values where values[i] is the value of the ith vertex (i.e., clockwise order).
|
||||
* You will triangulate the polygon into n - 2 triangles. For each triangle, the value of that triangle is the product of the values of its vertices, and the total score of the triangulation is the sum of these values over all n - 2 triangles in the triangulation.
|
||||
* Return the smallest possible total score that you can achieve with some triangulation of the polygon.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::vector<int> val;
|
||||
int n = -1;
|
||||
|
||||
int dp[51][51]{};
|
||||
|
||||
int func(int f, int t) {
|
||||
int& ans = dp[f][t];
|
||||
if (ans)
|
||||
return ans;
|
||||
const int d = t - f;
|
||||
if (d < 2)
|
||||
return 0;
|
||||
if (d == 2) {
|
||||
ans = val[t];
|
||||
for (int i = f; i < t; ++i)
|
||||
ans *= val[i];
|
||||
return ans;
|
||||
}
|
||||
ans = 0x7FFFFFFF;
|
||||
for (int i = 1 + f, bp = val[f] * val[t]; i < t; ++i)
|
||||
ans = std::min(ans, bp * val[i] + func(f, i) + func(i, t));
|
||||
return ans;
|
||||
}
|
||||
|
||||
public:
|
||||
int minScoreTriangulation(std::vector<int> values) {
|
||||
val = std::move(values);
|
||||
n = val.size();
|
||||
return func(0, n - 1);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include <cstdio>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 2300. Successful Pairs of Spells and Potions
|
||||
*
|
||||
* You are given two positive integer arrays spells and potions, of length n and m respectively, where spells[i] represents the strength of the ith spell and potions[j] represents the strength of the jth potion.
|
||||
* You are also given an integer success. A spell and potion pair is considered successful if the product of their strengths is at least success.
|
||||
* Return an integer array pairs of length n where pairs[i] is the number of potions that will form a successful pair with the ith spell.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
using VI = std::vector<int>;
|
||||
using LL = long long;
|
||||
public:
|
||||
static VI successfulPairs(const VI& s, VI& p, LL t) {
|
||||
VI ret;
|
||||
std::sort(p.begin(), p.end());
|
||||
std::transform(s.begin(), s.end(), std::back_inserter(ret), [&](auto&& x) {
|
||||
return p.end() - std::lower_bound(p.begin(), p.end(), t / x + !!(t % x));
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
long long x = 7;
|
||||
std::vector<int> args_p {1, 2, 3, 4, 5};
|
||||
for (auto ret = Solution::successfulPairs({5, 1, 7}, args_p, x); auto&& i : ret) {
|
||||
std::printf("%d\n", i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1053. Previous Permutation With One Swap
|
||||
* Given an array of positive integers arr (not necessarily distinct), return the lexicographically largest permutation that is smaller than arr, that can be made with exactly one swap. If it cannot be done, then return the same array.
|
||||
* Note that a swap exchanges the positions of two numbers arr[i] and arr[j]
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
std::vector<int> prevPermOpt1(std::vector<int> arr) {
|
||||
if (std::is_sorted(arr.begin(), arr.end()))
|
||||
return arr;
|
||||
const int n = arr.size();
|
||||
for (int i = n - 2; i >= 0; --i) {
|
||||
if (arr[i] <= arr[i + 1])
|
||||
continue;
|
||||
int j = n - 1;
|
||||
for (; arr[j] >= arr[i] || arr[j] == arr[j - 1]; --j);
|
||||
std::swap(arr[i], arr[j]);
|
||||
return arr;
|
||||
}
|
||||
// Should not reach here
|
||||
return arr;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 881. Boats to Save People
|
||||
*
|
||||
* You are given an array people where people[i] is the weight of the ith person, and an infinite number of boats where each boat can carry a maximum weight of limit. Each boat carries at most two people at the same time, provided the sum of the weight of those people is at most limit.
|
||||
* Return the minimum number of boats to carry every given person.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int numRescueBoats(const std::vector<int>& people, int limit) {
|
||||
std::vector<uint16_t> bucket(30005);
|
||||
for (int i : people)
|
||||
++bucket[i];
|
||||
int ans = bucket[limit], i = 1, j = limit - 1, delta;
|
||||
for (; i < j; --j) {
|
||||
if (!bucket[j])
|
||||
continue;
|
||||
while (bucket[j] && i + j <= limit && i < j) {
|
||||
delta = std::min(bucket[j], bucket[i]);
|
||||
bucket[j] -= delta;
|
||||
bucket[i] -= delta;
|
||||
ans += delta;
|
||||
if (!bucket[i])
|
||||
++i;
|
||||
}
|
||||
if (bucket[j]) {
|
||||
if (i == j && i + j <= limit)
|
||||
ans += (bucket[i] >> 1) + (bucket[i] & 1);
|
||||
else
|
||||
ans += bucket[j];
|
||||
}
|
||||
bucket[j] = 0;
|
||||
}
|
||||
if (bucket[i])
|
||||
ans += (bucket[i] >> 1) + (bucket[i] & 1);
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::numRescueBoats({2,2}, 6);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1000. Minimum Cost to Merge Stones
|
||||
*
|
||||
* There are n piles of stones arranged in a row. The ith pile has stones[i] stones.
|
||||
* A move consists of merging exactly k consecutive piles into one pile, and the cost of this move is equal to the total number of stones in these k piles.
|
||||
* Return the minimum cost to merge all piles of stones into one pile. If it is impossible, return -1.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int mergeStones(const std::vector<int>& stones, int k) {
|
||||
const int n = stones.size();
|
||||
if (n == 1)
|
||||
return 0;
|
||||
if (n < k || k != 2 && (n % (k - 1)) != 1)
|
||||
return -1;
|
||||
int pSum[35]{ stones[0] };
|
||||
for (int i = 1; i < n; ++i)
|
||||
pSum[i] = pSum[i - 1] + stones[i];
|
||||
int dp[35][35]{};
|
||||
std::memset(dp, 0x3F, sizeof dp);
|
||||
for (int i = 0; i < n; ++i)
|
||||
dp[i][i] = 0;
|
||||
for (int len = 2; len <= n; ++len) {
|
||||
for (int L = 0; L < n && L + len <= n; ++L) {
|
||||
int R = L + len - 1; // inclusive
|
||||
for (int M = L; M < R; M += k - 1)
|
||||
dp[L][R] = std::min(dp[L][M] + dp[M + 1][R], dp[L][R]);
|
||||
if (0 == (R - L) % (k - 1))
|
||||
dp[L][R] += pSum[R] - (L ? pSum[L - 1] : 0);
|
||||
}
|
||||
}
|
||||
return dp[0][n - 1];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2405. Optimal Partition of String
|
||||
*
|
||||
* Given a string s, partition the string into one or more substrings such that the characters in each substring are unique. That is, no letter appears in a single substring more than once.
|
||||
* Return the minimum number of substrings in such a partition.
|
||||
* Note that each character should belong to exactly one substring in a partition.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int partitionString(const std::string& s) {
|
||||
int set = 0, ans = 0;
|
||||
for (auto&& ch : s) {
|
||||
if (int c = 1 << (ch - 'a'); set & c) {
|
||||
set = c;
|
||||
++ans;
|
||||
} else set |= c;
|
||||
}
|
||||
return ans + !!set;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::partitionString("abacaba");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
/**
|
||||
* 2427. Number of Common Factors
|
||||
*
|
||||
* Given two positive integers a and b, return the number of common factors of a and b.
|
||||
* An integer x is a common factor of a and b if x divides both a and b.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static constexpr inline int commonFactors(int a, int b) {
|
||||
int x = std::gcd(a, b), ret = 0;
|
||||
for (int i = 1; i * i <= x; ++i)
|
||||
ret += ((x % i == 0) << 1) - (i * i == x);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::commonFactors(452, 392);
|
||||
std::cout << std::gcd(452, 392);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 2439. Minimize Maximum of Array
|
||||
*
|
||||
* You are given a 0-indexed array nums comprising of n non-negative integers.
|
||||
*
|
||||
* In one operation, you must:
|
||||
*
|
||||
* Choose an integer i such that 1 <= i < n and nums[i] > 0.
|
||||
* Decrease nums[i] by 1.
|
||||
* Increase nums[i - 1] by 1.
|
||||
* Return the minimum possible value of the maximum integer of nums after performing any number of operations.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int minimizeArrayValue(const std::vector<int>& nums) {
|
||||
const int n = nums.size();
|
||||
int ret = 0;
|
||||
unsigned long long sum = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
sum += nums[i];
|
||||
ret = std::max(ret, static_cast<int>(sum / (i + 1) + !!(sum % (i + 1))));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::minimizeArrayValue({3,7,1,6});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class SolutionConstruct {
|
||||
private:
|
||||
static inline std::string toStr(int n) {
|
||||
int i = 31;
|
||||
for (; i >= 0 && !(n & (1 << i)); --i);
|
||||
std::string ret(i + 1, '0');
|
||||
for (int j = i; j >= 0; --j)
|
||||
if (n & (1 << j))
|
||||
ret[i - j] = '1';
|
||||
return ret.empty() ? "0" : ret;
|
||||
}
|
||||
|
||||
static inline int toInt(const std::string& s) {
|
||||
auto ret = 0, i = 1;
|
||||
for (auto it = s.rbegin(); it != s.rend(); ++it) {
|
||||
ret |= (*it & 1) ? i : 0;
|
||||
i <<= 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static constexpr inline int eval(int n) { return (n & 0x55555555) - (n & 0xAAAAAAAA); }
|
||||
|
||||
static const inline std::string L5[] = {"0", "1", "110", "111", "100", "101"};
|
||||
|
||||
static const inline std::string v[] = {"01", "00", "11", "10"};
|
||||
|
||||
public:
|
||||
static std::string baseNeg2(int n) {
|
||||
if (n <= 5)
|
||||
return L5[n];
|
||||
int cur, prev = 5, i = 4;
|
||||
for (; n > (cur = prev + (1 << i)); (prev = cur), (i += 2));
|
||||
auto ret = std::string(1, '0' | (n & 1));
|
||||
for (int x = (n - prev - 1) >> 1, j = 1; j < (i >> 1); (x >>= 2), ++j)
|
||||
ret = v[x & 3] + ret;
|
||||
return v[(n - prev > (cur - prev) / 2) + 2] + ret;
|
||||
}
|
||||
|
||||
static void test(int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int x = eval(i);
|
||||
if (x < 0)
|
||||
continue;
|
||||
if (i != toInt(baseNeg2(x)))
|
||||
std::printf("%d Bad!!\n", x);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1017. Convert to Base -2
|
||||
*
|
||||
* Given an integer n, return a binary string representing its representation in base -2.
|
||||
* Note that the returned string should not have leading zeros unless the string is "0".
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static const inline std::string L5[] = {"0", "1", "110", "111", "100", "101"};
|
||||
|
||||
static const inline std::string v[] = {"01", "00", "11", "10"};
|
||||
|
||||
public:
|
||||
static std::string baseNeg2(int n) {
|
||||
if (n <= 5)
|
||||
return L5[n];
|
||||
int cur, prev = 5, i = 4;
|
||||
for (; n > (cur = prev + (1 << i)); (prev = cur), (i += 2));
|
||||
auto ret = std::string(1, '0' | (n & 1));
|
||||
for (int x = (n - prev - 1) >> 1, j = 1; j < (i >> 1); (x >>= 2), ++j)
|
||||
ret = v[x & 3] + ret;
|
||||
return v[(n - prev > (cur - prev) / 2) + 2] + ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
SolutionConstruct::test(0x1000000);
|
||||
// std::cout << Solution::baseNeg2(77);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1254. Number of Closed Islands
|
||||
*
|
||||
* Given a 2D grid consists of 0s (land) and 1s (water). An island is a maximal 4-directionally connected group of 0s and a closed island is an island totally (all left, top, right, bottom) surrounded by 1s.
|
||||
* Return the number of closed islands.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static const inline int dX[] = {0, 1, 0, -1}, dY[] = {1, 0, -1, 0};
|
||||
public:
|
||||
static int closedIsland(std::vector<std::vector<int>>&);
|
||||
};
|
||||
|
||||
int Solution::closedIsland(std::vector<std::vector<int>>& G) {
|
||||
const int m = G.size(), n = G.front().size();
|
||||
std::vector<bool> vis(m * n);
|
||||
auto setAs1 = [&](int x, int y) {
|
||||
if (G[x][y]) return 0;
|
||||
std::queue<std::pair<int, int>> q;
|
||||
q.emplace(x, y);
|
||||
for (int nx, ny; !q.empty(); q.pop()) {
|
||||
auto&& [cx, cy] = q.front();
|
||||
G[cx][cy] = 1;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
nx = cx + dX[i];
|
||||
ny = cy + dY[i];
|
||||
if (nx >= 0 && nx < m && ny >= 0 && ny < n && G[nx][ny] == 0 && !vis[nx * n + ny]) {
|
||||
q.emplace(nx, ny);
|
||||
vis[nx * n + ny] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
for (int i = 0; i < n; ++i)
|
||||
setAs1(0, i), setAs1(m - 1, i);
|
||||
for (int i = 1; i < m; ++i)
|
||||
setAs1(i, 0), setAs1(i, n - 1);
|
||||
int ret = 0;
|
||||
for (int i = 1; i < m - 1; ++i)
|
||||
for (int j = 1; j < n - 1; ++j)
|
||||
ret += setAs1(i, j);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<std::vector<int>> a {
|
||||
{1,1,1,1,1,1,1,0},
|
||||
{1,0,0,0,0,1,1,0},
|
||||
{1,0,1,0,1,1,1,0},
|
||||
{1,0,0,0,0,1,0,1},
|
||||
{1,1,1,1,1,1,1,0}
|
||||
};
|
||||
std::cout << Solution::closedIsland(a);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
|
||||
/**
|
||||
* 1020. Number of Enclaves
|
||||
*
|
||||
* You are given an m x n binary matrix grid, where 0 represents a sea cell and 1 represents a land cell.
|
||||
* A move consists of walking from one land cell to another adjacent (4-directionally) land cell or walking off the boundary of the grid.
|
||||
* Return the number of land cells in grid for which we cannot walk off the boundary of the grid in any number of moves.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static const inline int dX[] = {0, 1, 0, -1}, dY[] = {1, 0, -1, 0};
|
||||
public:
|
||||
static int numEnclaves(std::vector<std::vector<int>>&);
|
||||
};
|
||||
|
||||
int Solution::numEnclaves(std::vector<std::vector<int>>& G) {
|
||||
const int m = G.size(), n = G.front().size();
|
||||
std::vector<bool> vis(m * n);
|
||||
auto setAs0 = [&](int x, int y) {
|
||||
if (G[x][y] == 0) return 0;
|
||||
std::queue<std::pair<int, int>> q;
|
||||
q.emplace(x, y);
|
||||
int ret = 0;
|
||||
for (int nx, ny; !q.empty(); q.pop()) {
|
||||
auto&& [cx, cy] = q.front();
|
||||
G[cx][cy] = 0;
|
||||
++ret;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
nx = cx + dX[i];
|
||||
ny = cy + dY[i];
|
||||
if (nx >= 0 && nx < m && ny >= 0 && ny < n && G[nx][ny] != 0 && !vis[nx * n + ny]) {
|
||||
q.emplace(nx, ny);
|
||||
vis[nx * n + ny] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
for (int i = 0; i < n; ++i)
|
||||
setAs0(0, i), setAs0(m - 1, i);
|
||||
for (int i = 1; i < m - 1; ++i)
|
||||
setAs0(i, 0), setAs0(i, n - 1);
|
||||
return std::transform_reduce(G.begin(), G.end(), 0, [](int x, int y){ return x + y; }, [](auto&& x) {
|
||||
return std::reduce(x.begin(), x.end(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<std::vector<int>> a {{0,0,0,0},{1,0,1,0},{0,1,1,0},{0,0,0,0}};
|
||||
std::cout << Solution::numEnclaves(a);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* 1125. Smallest Sufficient Team
|
||||
*
|
||||
* In a project, you have a list of required skills req_skills, and a list of people. The ith person people[i] contains a list of skills that the person has.
|
||||
*
|
||||
* Consider a sufficient team: a set of people such that for every required skill in req_skills, there is at least one person in the team who has that skill. We can represent these teams by the index of each person.
|
||||
*
|
||||
* For example, team = [0, 1, 3] represents the people with skills people[0], people[1], and people[3].
|
||||
* Return any sufficient team of the smallest possible size, represented by the index of each person. You may return the answer in any order.
|
||||
*
|
||||
* It is guaranteed an answer exists.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
template<typename T>
|
||||
using V = std::vector<T>;
|
||||
using VI = V<int>;
|
||||
using VS = V<std::string>;
|
||||
using VVS = V<VS>;
|
||||
|
||||
static VI smallestSufficientTeam(const VS&, const VVS&);
|
||||
};
|
||||
|
||||
Solution::VI Solution::smallestSufficientTeam(const VS& req, const VVS& p) {
|
||||
int n = 0;
|
||||
std::unordered_map<std::string, int> m;
|
||||
for (auto&& x : req)
|
||||
m[x] = n++;
|
||||
VI ps;
|
||||
for (auto&& x : p) {
|
||||
int y = 0;
|
||||
for (auto&& z : x)
|
||||
y |= (1 << m[z]);
|
||||
ps.push_back(y);
|
||||
}
|
||||
VI dp(1 << 16), father(1 << 16);
|
||||
const int full = (1 << n) - 1, k = ps.size();
|
||||
std::function<int(int)> d = [&](int current) {
|
||||
if (dp[current])
|
||||
return dp[current];
|
||||
if (current == full)
|
||||
return 0;
|
||||
int& ans = dp[current];
|
||||
ans = 0x7FFFFFFF;
|
||||
for (int i = 0, next; i < k; ++i) {
|
||||
next = current | ps[i];
|
||||
if (current == next)
|
||||
continue;
|
||||
if (int dn = d(next); 1 + dn < ans) {
|
||||
ans = 1 + dn;
|
||||
father[current] = i;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
};
|
||||
d(0);
|
||||
VI ret;
|
||||
for (int i = 0; i < full; i = i | ps[father[i]])
|
||||
ret.push_back(father[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
|
||||
for (auto&& x : vec)
|
||||
os << x;
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::smallestSufficientTeam({"algorithms","math","java","reactjs","csharp","aws"}, {
|
||||
{"algorithms","math","java"},
|
||||
{"algorithms","math","reactjs"},
|
||||
{"java","csharp","aws"},
|
||||
{"reactjs","csharp"},
|
||||
{"csharp","math"},
|
||||
{"aws","java"}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#include <bitset>
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class Node {
|
||||
public:
|
||||
int val;
|
||||
std::vector<Node*> neighbors;
|
||||
Node() {
|
||||
val = 0;
|
||||
neighbors = std::vector<Node*>();
|
||||
}
|
||||
explicit Node(int _val) {
|
||||
val = _val;
|
||||
neighbors = std::vector<Node*>();
|
||||
}
|
||||
Node(int _val, std::vector<Node*> _neighbors) {
|
||||
val = _val;
|
||||
neighbors = _neighbors;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 133. Clone Graph
|
||||
*
|
||||
* Given a reference of a node in a connected undirected graph.
|
||||
* Return a deep copy (clone) of the graph.
|
||||
* Each node in the graph contains a value (int) and a list (List[Node]) of its neighbors.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static Node* cloneGraph(Node*);
|
||||
};
|
||||
|
||||
Node* Solution::cloneGraph(Node* node) {
|
||||
if (!node)
|
||||
return nullptr;
|
||||
Node* s = new Node[102];
|
||||
std::bitset<102> vis;
|
||||
for (int i = 0; i < 102; ++i)
|
||||
s[i].val = i;
|
||||
std::queue<Node*> q;
|
||||
q.push(node);
|
||||
vis[node->val] = true;
|
||||
while (!q.empty()) {
|
||||
auto* ptr = q.front();
|
||||
q.pop();
|
||||
for (auto&& np : ptr->neighbors) {
|
||||
s[ptr->val].neighbors.push_back(s + np->val);
|
||||
if (!vis[np->val]) {
|
||||
vis[np->val] = true;
|
||||
q.push(np);
|
||||
}
|
||||
}
|
||||
}
|
||||
return s + node->val;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 2399. Check Distances Between Same Letters
|
||||
*
|
||||
* You are given a 0-indexed string s consisting of only lowercase English letters, where each letter in s appears exactly twice. You are also given a 0-indexed integer array distance of length 26.
|
||||
* Each letter in the alphabet is numbered from 0 to 25 (i.e. 'a' -> 0, 'b' -> 1, 'c' -> 2, ... , 'z' -> 25).
|
||||
* In a well-spaced string, the number of letters between the two occurrences of the ith letter is distance[i]. If the ith letter does not appear in s, then distance[i] can be ignored.
|
||||
* Return true if s is a well-spaced string, otherwise return false.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool checkDistances(const std::string&, const std::vector<int>&);
|
||||
};
|
||||
|
||||
bool Solution::checkDistances(const std::string& s, const std::vector<int>& distance) {
|
||||
int pos[26]{};
|
||||
std::memset(pos, -1, sizeof pos);
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
int& p = pos[s[i] - 'a'];
|
||||
p = i + (p < 0 ? 1 : -p);
|
||||
}
|
||||
for (int i = 0; i < 26; ++i)
|
||||
if (pos[i] >= 0 && pos[i] != distance[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::checkDistances("abaccb", {
|
||||
1,3,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
struct Info {
|
||||
int cnt[26]{};
|
||||
bool has_value = false;
|
||||
bool is_bad = false;
|
||||
bool in_loop = false;
|
||||
|
||||
Info& operator&=(const Info& rhs) {
|
||||
for (int i = 0; i < 26; ++i)
|
||||
this->cnt[i] = std::max(this->cnt[i], rhs.cnt[i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int get() const {
|
||||
int ret = cnt[0];
|
||||
for (int i = 1; i < 26; ++i)
|
||||
ret = std::max(ret, cnt[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 1857. Largest Color Value in a Directed Graph
|
||||
*
|
||||
* There is a directed graph of n colored nodes and m edges. The nodes are numbered from 0 to n - 1.
|
||||
* You are given a string colors where colors[i] is a lowercase English letter representing the color of the ith node in this graph (0-indexed). You are also given a 2D array edges where edges[j] = [aj, bj] indicates that there is a directed edge from node aj to node bj.
|
||||
* A valid path in the graph is a sequence of nodes x1 -> x2 -> x3 -> ... -> xk such that there is a directed edge from xi to xi+1 for every 1 <= i < k. The color value of the path is the number of nodes that are colored the most frequently occurring color along that path.
|
||||
* Return the largest color value of any valid path in the given graph, or -1 if the graph contains a cycle.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int largestPathValue(const std::string&, const std::vector<std::vector<int>>&);
|
||||
};
|
||||
|
||||
int Solution::largestPathValue(const std::string& colors, const std::vector<std::vector<int>>& edges) {
|
||||
const int m = edges.size(), n = colors.length();
|
||||
std::vector<std::vector<int>> G(n);
|
||||
for (auto&& e : edges)
|
||||
G[e[0]].push_back(e[1]);
|
||||
std::vector<Info> dp(n);
|
||||
std::function<const Info&(int)> d = [&](int idx) -> const Info& {
|
||||
auto& ans = dp[idx];
|
||||
if (ans.has_value)
|
||||
return ans;
|
||||
if (ans.in_loop) {
|
||||
ans.is_bad = true;
|
||||
return ans;
|
||||
} else if (G[idx].empty()) {
|
||||
ans.cnt[colors[idx] - 'a'] = 1;
|
||||
ans.has_value = true;
|
||||
return ans;
|
||||
}
|
||||
ans.in_loop = true;
|
||||
for (int nx : G[idx]) {
|
||||
const auto& nxd = d(nx);
|
||||
if (nxd.is_bad) {
|
||||
ans.is_bad = true;
|
||||
return ans;
|
||||
}
|
||||
ans &= nxd;
|
||||
}
|
||||
++ans.cnt[colors[idx] - 'a'];
|
||||
ans.has_value = true;
|
||||
ans.in_loop = false;
|
||||
return ans;
|
||||
};
|
||||
int ans = -1;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const auto& c = d(i);
|
||||
if (c.is_bad)
|
||||
return -1;
|
||||
ans = std::max(ans, c.get());
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::largestPathValue("hhqhuqhqff", {
|
||||
{0,1},{0,2},{2,3},{3,4},{3,5},{5,6},{2,7},{6,7},{7,8},{3,8},{5,8},{8,9},{3,9},{6,9}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#include <vector>
|
||||
#include <queue>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode* next;
|
||||
|
||||
explicit ListNode(int x = 0, ListNode* next = nullptr) : val(x), next(next) {}
|
||||
};
|
||||
|
||||
ListNode* construct(int x) {
|
||||
return new ListNode(x);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
ListNode* construct(int x, Ts... xs) {
|
||||
return new ListNode(x, construct(xs...));
|
||||
}
|
||||
|
||||
/**
|
||||
* 1019. Next Greater Node In Linked List
|
||||
*
|
||||
* You are given the head of a linked list with n nodes.
|
||||
* For each node in the list, find the value of the next greater node. That is, for each node, find the value of the first node that is next to it and has a strictly larger value than it.
|
||||
* Return an integer array answer where answer[i] is the value of the next greater node of the ith node (1-indexed). If the ith node does not have a next greater node, set answer[i] = 0.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
template<typename T>
|
||||
using V = std::vector<T>;
|
||||
using VI = V<int>;
|
||||
using PII = std::pair<int, int>;
|
||||
|
||||
static VI nextLargerNodes(const ListNode*);
|
||||
};
|
||||
|
||||
Solution::VI Solution::nextLargerNodes(const ListNode* head) {
|
||||
VI ret;
|
||||
std::priority_queue<PII, V<PII>, std::greater<>> q;
|
||||
for (const ListNode* ptr = head; ptr; ptr = ptr->next) {
|
||||
q.emplace(ptr->val, ret.size());
|
||||
ret.push_back(0);
|
||||
for (; q.top().first < ptr->val; q.pop())
|
||||
ret[q.top().second] = ptr->val;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
|
||||
for (auto&& x : vec)
|
||||
os << x << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::nextLargerNodes(construct(2,7,4,3,5));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* 20. Valid Parentheses
|
||||
*
|
||||
* Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
|
||||
*
|
||||
* An input string is valid if:
|
||||
*
|
||||
* Open brackets must be closed by the same type of brackets.
|
||||
* Open brackets must be closed in the correct order.
|
||||
* Every close bracket has a corresponding open bracket of the same type.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool isValid(const std::string&);
|
||||
};
|
||||
|
||||
bool Solution::isValid(const std::string& s) {
|
||||
std::stack<char> sc;
|
||||
for (char ch : s) {
|
||||
switch (ch) {
|
||||
case '[':
|
||||
case '(':
|
||||
case '{':
|
||||
sc.push(ch);
|
||||
break;
|
||||
case ']':
|
||||
case ')':
|
||||
case '}':
|
||||
if (sc.empty() || sc.top() != (ch ^ (ch < 64 ? 1 : 6)))
|
||||
return false;
|
||||
sc.pop();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return sc.empty();
|
||||
}
|
||||
|
||||
int main() {
|
||||
Solution::isValid("()[]{}");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 1041. Robot Bounded In Circle
|
||||
*
|
||||
* On an infinite plane, a robot initially stands at (0, 0) and faces north. Note that:
|
||||
*
|
||||
* The north direction is the positive direction of the y-axis.
|
||||
* The south direction is the negative direction of the y-axis.
|
||||
* The east direction is the positive direction of the x-axis.
|
||||
* The west direction is the negative direction of the x-axis.
|
||||
* The robot can receive one of three instructions:
|
||||
*
|
||||
* "G": go straight 1 unit.
|
||||
* "L": turn 90 degrees to the left (i.e., anti-clockwise direction).
|
||||
* "R": turn 90 degrees to the right (i.e., clockwise direction).
|
||||
* The robot performs the instructions given in order, and repeats them forever.
|
||||
*
|
||||
* Return true if and only if there exists a circle in the plane such that the robot never leaves the circle.
|
||||
*
|
||||
* Refer: 220109.cpp
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
// N, W, S, E
|
||||
static const inline short dX[] = {0, -1, 0, 1};
|
||||
static const inline short dY[] = {1, 0, -1, 0};
|
||||
public:
|
||||
static bool isRobotBounded(const std::string&);
|
||||
};
|
||||
|
||||
bool Solution::isRobotBounded(const std::string& instructions) {
|
||||
const int n = instructions.size();
|
||||
short X = 0, Y = 0, D = 0;
|
||||
for (int i = 0; i < (n << 2); ++i) {
|
||||
if (char ch = instructions[i % n]; ch == 'G') {
|
||||
X += dX[D];
|
||||
Y += dY[D];
|
||||
} else D = (D + 1 + (ch & 3)) & 3;
|
||||
}
|
||||
return !(X | Y | D);
|
||||
}
|
||||
|
||||
int main() {
|
||||
Solution::isRobotBounded("LLGRL");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 2390. Removing Stars From a String
|
||||
*
|
||||
* You are given a string s, which contains stars *.
|
||||
*
|
||||
* In one operation, you can:
|
||||
*
|
||||
* Choose a star in s.
|
||||
* Remove the closest non-star character to its left, as well as remove the star itself.
|
||||
* Return the string after all stars have been removed.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The input will be generated such that the operation is always possible.
|
||||
* It can be shown that the resulting string will always be unique.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::string removeStars(const std::string&);
|
||||
};
|
||||
|
||||
std::string Solution::removeStars(const std::string& s) {
|
||||
std::string ret;
|
||||
for (char ch : s)
|
||||
if (ch != '*')
|
||||
ret.push_back(ch);
|
||||
else
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 1147. Longest Chunked Palindrome Decomposition
|
||||
*
|
||||
* You are given a string text. You should split it to k substrings (subtext[1], subtext[2], ..., subtext[k]) such that:
|
||||
*
|
||||
* subtext[i] is a non-empty string.
|
||||
* The concatenation of all the substrings is equal to text (i.e., subtext[1] + subtext[2] + ... + subtext[k] == text).
|
||||
* subtext[i] == subtext[k] - i + 1 for all valid values of i (i.e., 1 <= i <= k).
|
||||
* Return the largest possible value of k.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
int len;
|
||||
std::vector<int> d;
|
||||
int dp(int);
|
||||
const char* ptr;
|
||||
|
||||
public:
|
||||
int longestDecomposition(const std::string&);
|
||||
};
|
||||
|
||||
int Solution::longestDecomposition(const std::string& text) {
|
||||
len = text.size();
|
||||
d = std::vector<int>(len / 2 + 5);
|
||||
ptr = text.c_str();
|
||||
return dp(0);
|
||||
}
|
||||
|
||||
int Solution::dp(int p) {
|
||||
int& ans = d[p];
|
||||
if (ans)
|
||||
return ans;
|
||||
const int end = len - p, cnt = end - p;
|
||||
if (cnt < 2)
|
||||
return ans = cnt;
|
||||
for (int i = 1; i <= cnt / 2; ++i)
|
||||
if (!std::memcmp(ptr + p, ptr + end - i, i))
|
||||
return 2 + dp(p + i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Solution s;
|
||||
std::cout << s.longestDecomposition("antaprezatepzapreanta");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 71. Simplify Path
|
||||
* Given a string path, which is an absolute path (starting with a slash '/') to a file or directory in a Unix-style file system, convert it to the simplified canonical path.
|
||||
*
|
||||
* In a Unix-style file system, a period '.' refers to the current directory, a double period '..' refers to the directory up a level, and any multiple consecutive slashes (i.e. '//') are treated as a single slash '/'. For this problem, any other format of periods such as '...' are treated as file/directory names.
|
||||
*
|
||||
* The canonical path should have the following format:
|
||||
*
|
||||
* The path starts with a single slash '/'.
|
||||
* Any two directories are separated by a single slash '/'.
|
||||
* The path does not end with a trailing '/'.
|
||||
* The path only contains the directories on the path from the root directory to the target file or directory (i.e., no period '.' or double period '..')
|
||||
* Return the simplified canonical path.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::string simplifyPath(const std::string&);
|
||||
};
|
||||
|
||||
std::string Solution::simplifyPath(const std::string& path) {
|
||||
char buf[3072]{};
|
||||
int n = path.size(), ps = 0, pt = 1, prev = 0;
|
||||
const char* ptr = path.c_str();
|
||||
for (; pt <= n; ++pt) {
|
||||
if (ptr[pt] && ptr[pt] != '/')
|
||||
continue;
|
||||
if (int diff = pt - prev; diff == 3 && ptr[pt - 1] == '.' && ptr[pt - 2] == '.') {
|
||||
while (ps > 0 && buf[--ps] != '/');
|
||||
} else if (diff > 2 || (diff == 2 && ptr[prev + 1] != '.')) {
|
||||
buf[ps++] = '/';
|
||||
for (int i = prev + 1; i < pt; buf[ps++] = ptr[i++]);
|
||||
}
|
||||
prev = pt;
|
||||
}
|
||||
return ps ? std::string(buf, buf + ps) : "/";
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto r = Solution::simplifyPath("/a//b////c/d//././/..");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 2404. Most Frequent Even Element
|
||||
*
|
||||
* Given an integer array nums, return the most frequent even element.
|
||||
* If there is a tie, return the smallest one. If there is no such element, return -1.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
using LL = long long;
|
||||
public:
|
||||
static int mostFrequentEven(const std::vector<int>&);
|
||||
};
|
||||
|
||||
int Solution::mostFrequentEven(const std::vector<int>& n) {
|
||||
std::unordered_map<int, int> m;
|
||||
std::for_each(n.begin(), n.end(), [&](int x) { if (!(x & 1)) ++m[x]; });
|
||||
return m.empty() ? -1 : std::max_element(m.begin(), m.end(), [](auto&& x, auto&& y) {
|
||||
auto&& [xk, xs] = x;
|
||||
auto&& [yk, ys] = y;
|
||||
return (LL(xs) << 32) - xk < (LL(ys) << 32) - yk;
|
||||
})->first;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <bitset>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
/**
|
||||
* 946. Validate Stack Sequences
|
||||
*
|
||||
* Given two integer arrays pushed and popped each with distinct values, return true if this could have been the result of a sequence of push and pop operations on an initially empty stack, or false otherwise.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static bool validateStackSequences(const std::vector<int>&, const std::vector<int>&);
|
||||
};
|
||||
|
||||
bool Solution::validateStackSequences(const std::vector<int>& i, const std::vector<int>& o) {
|
||||
std::bitset<1024> pushed;
|
||||
std::stack<int> s;
|
||||
const int n = i.size();
|
||||
for (int pi = 0, po = 0; po < n; ++po, s.pop()) {
|
||||
for (; !pushed[o[po]]; pushed[i[pi++]] = true)
|
||||
s.push(i[pi]);
|
||||
if (s.empty() || s.top() != o[po])
|
||||
return false;
|
||||
}
|
||||
return s.empty();
|
||||
}
|
||||
|
||||
int main() {
|
||||
Solution::validateStackSequences({1,2,3,4,5},{4,3,5,1,2});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <iostream>
|
||||
#include <cctype>
|
||||
|
||||
/**
|
||||
* 1023. Camelcase Matching
|
||||
*
|
||||
* Given an array of strings queries and a string pattern, return a boolean array answer where answer[i] is true if queries[i] matches pattern, and false otherwise.
|
||||
* A query word queries[i] matches pattern if you can insert lowercase English letters pattern so that it equals the query. You may insert each character at any position and you may not insert any characters.
|
||||
*
|
||||
* Note: this solution (using regex) is VERY VERY slow
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
template<typename T>
|
||||
using V = std::vector<T>;
|
||||
using S = std::string;
|
||||
static constexpr inline bool is_lower(char c) { return c >= 'a' && c <= 'z'; }
|
||||
static V<bool> camelMatchAlt(const V<S>&, const S&);
|
||||
public:
|
||||
static V<bool> camelMatch(const V<S>&, const S&);
|
||||
};
|
||||
|
||||
std::vector<bool> Solution::camelMatch(const V<S>& queries, const S& pattern) {
|
||||
// return camelMatchAlt(queries, pattern);
|
||||
S regex_str = "[a-z]*";
|
||||
for (char ch : pattern) {
|
||||
regex_str += ch;
|
||||
regex_str += "[a-z]*";
|
||||
}
|
||||
std::regex matcher(regex_str, std::regex_constants::optimize);
|
||||
std::vector<bool> ret;
|
||||
for (auto&& q : queries)
|
||||
ret.push_back(std::regex_match(q, matcher));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<bool> Solution::camelMatchAlt(const V<S>& qs, const S& p) {
|
||||
std::vector<bool> ret;
|
||||
const int n = p.length();
|
||||
for (auto&& q : qs) {
|
||||
int pp = 0, pq = 0;
|
||||
const int m = q.length();
|
||||
for (; pq < m; ++pq)
|
||||
if (q[pq] == p[pp]) {
|
||||
if (++pp >= n) break;
|
||||
} else if (!std::islower(q[pq])) break;
|
||||
ret.push_back(pp >= n && std::all_of(q.begin() + ++pq, q.end(), [](char c) {
|
||||
return std::islower(c);
|
||||
}));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
|
||||
for (auto&& x : vec)
|
||||
os << x << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::camelMatch(
|
||||
{"FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"},
|
||||
"FB"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 516. Longest Palindromic Subsequence
|
||||
*
|
||||
* Given a string s, find the longest palindromic subsequence's length in s.
|
||||
* A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::string s;
|
||||
int ans[1001][1001]{};
|
||||
|
||||
int dp(int, int);
|
||||
|
||||
public:
|
||||
int longestPalindromeSubseq(std::string);
|
||||
};
|
||||
|
||||
int Solution::longestPalindromeSubseq(std::string str) {
|
||||
this->s = std::move(str);
|
||||
return dp(0, s.size() - 1);
|
||||
}
|
||||
|
||||
int Solution::dp(int x, int y) {
|
||||
int& a = ans[x][y];
|
||||
if (a)
|
||||
return a;
|
||||
if (x == y)
|
||||
return a = 1;
|
||||
if (1 == y - x)
|
||||
return a = 1 + (s[x] == s[y]);
|
||||
return a = std::max(
|
||||
(s[x] == s[y]) * 2 + dp(x + 1, y - 1),
|
||||
std::max(dp(x + 1, y), dp(x, y - 1))
|
||||
);
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto* s = new Solution;
|
||||
std::cout << s->longestPalindromeSubseq("cbbd");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* 2409. Count Days Spent Together
|
||||
*
|
||||
* Alice and Bob are traveling to Rome for separate business meetings.
|
||||
* You are given 4 strings arriveAlice, leaveAlice, arriveBob, and leaveBob. Alice will be in the city from the dates arriveAlice to leaveAlice (inclusive), while Bob will be in the city from the dates arriveBob to leaveBob (inclusive). Each will be a 5-character string in the format "MM-DD", corresponding to the month and day of the date.
|
||||
* Return the total number of days that Alice and Bob are in Rome together.
|
||||
* You can assume that all dates occur in the same calendar year, which is not a leap year. Note that the number of days per month can be represented as: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31].
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
using CSR = std::string const&;
|
||||
static int minus(CSR, CSR);
|
||||
static int ord(CSR);
|
||||
|
||||
public:
|
||||
static int countDaysTogether(CSR, CSR, CSR, CSR);
|
||||
};
|
||||
|
||||
int Solution::countDaysTogether(CSR arriveAlice, CSR leaveAlice, CSR arriveBob, CSR leaveBob) {
|
||||
if (leaveAlice < arriveBob || leaveBob < arriveAlice)
|
||||
return 0;
|
||||
return minus(std::min(leaveAlice, leaveBob), std::max(arriveAlice, arriveBob));
|
||||
}
|
||||
|
||||
int Solution::minus(CSR x, CSR y) {
|
||||
return ord(x) - ord(y) + 1;
|
||||
}
|
||||
|
||||
int Solution::ord(CSR x) {
|
||||
static const int f[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||||
return f[(x[0] - '0') * 10 + (x[1] - '0') - 1] + (x[3] - '0') * 10 + (x[4] - '0');
|
||||
}
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* 1431. Kids With the Greatest Number of Candies
|
||||
*
|
||||
* There are n kids with candies. You are given an integer array candies, where each candies[i] represents the number of candies the ith kid has, and an integer extraCandies, denoting the number of extra candies that you have.
|
||||
* Return a boolean array result of length n, where result[i] is true if, after giving the ith kid all the extraCandies, they will have the greatest number of candies among all the kids, or false otherwise.
|
||||
* Note that multiple kids can have the greatest number of candies.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static std::vector<bool> kidsWithCandies(const std::vector<int>&, int);
|
||||
};
|
||||
|
||||
std::vector<bool> Solution::kidsWithCandies(const std::vector<int>& c, int ec) {
|
||||
std::vector<bool> ret;
|
||||
int max = *std::max_element(c.begin(), c.end());
|
||||
std::transform(c.begin(), c.end(), std::back_inserter(ret), [&](int x) { return x + ec >= max; });
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1026. Maximum Difference Between Node and Ancestor
|
||||
*
|
||||
* Given the root of a binary tree, find the maximum value v for which there exist different nodes a and b where v = |a.val - b.val| and a is an ancestor of b.
|
||||
* A node a is an ancestor of b if either: any child of a is equal to b or any child of a is an ancestor of b.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
static inline constexpr int MAX(int x, int y) noexcept { return x > y ? x : y; }
|
||||
static inline constexpr int MIN(int x, int y) noexcept { return x < y ? x : y; }
|
||||
static inline constexpr int ABS(int x) noexcept { return x < 0 ? -x : x; }
|
||||
|
||||
static int dfs(TreeNode*, int, int) noexcept;
|
||||
public:
|
||||
static int maxAncestorDiff(TreeNode*) noexcept;
|
||||
};
|
||||
|
||||
int Solution::maxAncestorDiff(TreeNode* r) noexcept {
|
||||
return r ? dfs(r, r->val, r->val) : 0;
|
||||
}
|
||||
|
||||
int Solution::dfs(TreeNode* n, int min, int max) noexcept {
|
||||
int ret = MAX(ABS(n->val - min), ABS(n->val - max));
|
||||
const int min_ = MIN(min, n->val), max_ = MAX(max, n->val);
|
||||
if (n->left)
|
||||
ret = MAX(ret, dfs(n->left, min_, max_));
|
||||
if (n->right)
|
||||
ret = MAX(ret, dfs(n->right, min_, max_));
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 1768. Merge Strings Alternately
|
||||
*
|
||||
* You are given two strings word1 and word2. Merge the strings by adding letters in alternating order, starting with word1. If a string is longer than the other, append the additional letters onto the end of the merged string.
|
||||
* Return the merged string.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
using S = std::string;
|
||||
using CSR = S const&;
|
||||
public:
|
||||
static S mergeAlternately(CSR, CSR);
|
||||
};
|
||||
|
||||
std::string Solution::mergeAlternately(CSR s, CSR t) {
|
||||
const int m = s.length(), n = t.length(), k = std::min(m, n);
|
||||
std::string ret;
|
||||
for (int i = 0; i < k; ++i)
|
||||
ret.push_back(s[i]), ret.push_back(t[i]);
|
||||
for (int i = k; i < m; ++i)
|
||||
ret.push_back(s[i]);
|
||||
for (int i = k; i < n; ++i)
|
||||
ret.push_back(t[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::mergeAlternately("ab", "pqrs");
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1043. Partition Array for Maximum Sum
|
||||
*
|
||||
* Given an integer array arr, partition the array into (contiguous) subarrays of length at most k. After partitioning, each subarray has their values changed to become the maximum value of that subarray.
|
||||
* Return the largest sum of the given array after partitioning. Test cases are generated so that the answer fits in a 32-bit integer.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
int dp[512]{};
|
||||
const std::vector<int>* ptr = nullptr;
|
||||
int k = 0;
|
||||
|
||||
int d(int pos) noexcept;
|
||||
|
||||
public:
|
||||
int maxSumAfterPartitioning(const std::vector<int>&, int) noexcept;
|
||||
};
|
||||
|
||||
int Solution::maxSumAfterPartitioning(const std::vector<int>& arr, int k) noexcept {
|
||||
this->ptr = &arr;
|
||||
this->k = k;
|
||||
return d(0);
|
||||
}
|
||||
|
||||
int Solution::d(int pos) noexcept {
|
||||
if (pos >= ptr->size())
|
||||
return 0;
|
||||
auto& ans = dp[pos];
|
||||
if (ans)
|
||||
return ans;
|
||||
for (int i = 0, m = 0; i < k; ++i) {
|
||||
int c_pos = pos + i;
|
||||
if (c_pos >= ptr->size())
|
||||
break;
|
||||
m = std::max(m, ptr->operator[](i + pos));
|
||||
ans = std::max(ans, m * (i + 1) + d(pos + i + 1));
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Solution s;
|
||||
std::cout << s.maxSumAfterPartitioning(
|
||||
{1,15,7,9,2,5,10},
|
||||
3
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 1372. Longest ZigZag Path in a Binary Tree
|
||||
*
|
||||
* You are given the root of a binary tree.
|
||||
*
|
||||
* A ZigZag path for a binary tree is defined as follow:
|
||||
*
|
||||
* Choose any node in the binary tree and a direction (right or left).
|
||||
* If the current direction is right, move to the right child of the current node; otherwise, move to the left child.
|
||||
* Change the direction from right to left or from left to right.
|
||||
* Repeat the second and third steps until you can't move in the tree.
|
||||
* Zigzag length is defined as the number of nodes visited - 1. (A single node has a length of 0).
|
||||
*
|
||||
* Return the longest ZigZag path contained in that tree.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::pair<int, int> f(TreeNode* r) noexcept;
|
||||
|
||||
std::unordered_map<TreeNode*, std::pair<int, int>> m;
|
||||
|
||||
public:
|
||||
int longestZigZag(TreeNode* root) noexcept;
|
||||
};
|
||||
|
||||
int Solution::longestZigZag(TreeNode* root) noexcept {
|
||||
f(root);
|
||||
return std::transform_reduce(m.begin(), m.end(), 0, [](int x, int y) { return std::max(x, y); }, [](auto&& x) {
|
||||
return std::max(x.second.first, x.second.second);
|
||||
});
|
||||
}
|
||||
|
||||
std::pair<int, int> Solution::f(TreeNode* r) noexcept {
|
||||
if (m.count(r))
|
||||
return m[r];
|
||||
return m[r] = {
|
||||
r->left ? f(r->left).second + 1 : 0,
|
||||
r->right ? f(r->right).first + 1 : 0
|
||||
};
|
||||
}
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 1187. Make Array Strictly Increasing
|
||||
*
|
||||
* Given two integer arrays arr1 and arr2, return the minimum number of operations (possibly zero) needed to make arr1 strictly increasing.
|
||||
* In one operation, you can choose two indices 0 <= i < arr1.length and 0 <= j < arr2.length and do the assignment arr1[i] = arr2[j].
|
||||
* If there is no way to make arr1 strictly increasing, return -1.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int makeArrayIncreasing(const std::vector<int>&, std::vector<int>);
|
||||
};
|
||||
|
||||
int Solution::makeArrayIncreasing(const std::vector<int>& p, std::vector<int> q) {
|
||||
std::sort(q.begin(), q.end());
|
||||
std::unordered_map<int, int> ans[2048];
|
||||
std::function<int(int, int)> dp = [&](int pos, int prev) {
|
||||
if (pos >= p.size())
|
||||
return 0;
|
||||
if (ans[pos].count(prev))
|
||||
return ans[pos][prev];
|
||||
int ret = 0x7FFFFFFE;
|
||||
if (auto it = std::upper_bound(q.begin(), q.end(), prev); it != q.end())
|
||||
ret = std::min(ret, dp(pos + 1, *it) + 1);
|
||||
if (p[pos] > prev)
|
||||
ret = std::min(ret, dp(pos + 1, p[pos]));
|
||||
return ans[pos][prev] = ret;
|
||||
};
|
||||
return dp(0, -1) > 99999 ? -1 : dp(0, -1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << Solution::makeArrayIncreasing({1,5,3,6,7},{6,3,3,1});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <tuple>
|
||||
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
|
||||
explicit TreeNode(int x, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 662. Maximum Width of Binary Tree
|
||||
*
|
||||
* Given the root of a binary tree, return the maximum width of the given tree.
|
||||
* The maximum width of a tree is the maximum width among all levels.
|
||||
* The width of one level is defined as the length between the end-nodes (the leftmost and rightmost non-null nodes), where the null nodes between the end-nodes that would be present in a complete binary tree extending down to that level are also counted into the length calculation.
|
||||
* It is guaranteed that the answer will in the range of a 32-bit signed integer.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static int widthOfBinaryTree(const TreeNode* root);
|
||||
};
|
||||
|
||||
int Solution::widthOfBinaryTree(const TreeNode* root) {
|
||||
std::queue<std::tuple<const TreeNode*, int, unsigned long long>> q;
|
||||
q.emplace(root, 0, 1);
|
||||
int curLevel = -1;
|
||||
std::pair<unsigned long long, unsigned long long> ans = {0, 0};
|
||||
unsigned long long ret = 1;
|
||||
while (!q.empty()) {
|
||||
auto [node, level, id] = q.front();
|
||||
q.pop();
|
||||
if (curLevel != level) {
|
||||
curLevel = level;
|
||||
ret = std::max(ans.second - ans.first + 1, ret);
|
||||
ans = {id, id};
|
||||
}
|
||||
ans.first = std::min(id, ans.first);
|
||||
ans.second = std::max(id, ans.second);
|
||||
if (node->left)
|
||||
q.emplace(node->left, 1 + level, id << 1);
|
||||
if (node->right)
|
||||
q.emplace(node->right, 1 + level, 1 | (id << 1));
|
||||
}
|
||||
return std::max(ret, ans.second - ans.first + 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* 2413. Smallest Even Multiple
|
||||
*
|
||||
* Given a positive integer n, return the smallest positive integer that is a multiple of both 2 and n.
|
||||
*/
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
static constexpr int smallestEvenMultiple(int n) {
|
||||
return n << (n & 1);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
|
||||
PROJECT(2304)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 23)
|
||||
SET(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||
|
||||
ADD_EXECUTABLE(2304 230421-CN.cpp)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
|
||||
PROJECT(2305)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 23)
|
||||
SET(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||
|
||||
FILE(GLOB src *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(2305 ${src})
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1491. Average Salary Excluding the Minimum and Maximum Salary
|
||||
*
|
||||
* You are given an array of unique integers salary where salary[i] is the salary of the ith employee.
|
||||
* Return the average salary of employees excluding the minimum and maximum salary. Answers within 1e-5 of the actual answer will be accepted.
|
||||
*/
|
||||
|
||||
class LC230501 {
|
||||
public:
|
||||
static double average(const std::vector<int>&) noexcept;
|
||||
};
|
||||
|
||||
double LC230501::average(const std::vector<int>& salary) noexcept {
|
||||
return (
|
||||
std::reduce(salary.begin(), salary.end(), 0.0) -
|
||||
*std::min_element(salary.begin(), salary.end()) -
|
||||
*std::max_element(salary.begin(), salary.end())
|
||||
) / (salary.size() - 2);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <algorithm>
|
||||
#include <forward_list>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1376. Time Needed to Inform All Employees
|
||||
*
|
||||
* A company has n employees with a unique ID for each employee from 0 to n - 1. The head of the company is the one with headID.
|
||||
* Each employee has one direct manager given in the manager array where manager[i] is the direct manager of the i-th employee, manager[headID] = -1. Also, it is guaranteed that the subordination relationships have a tree structure.
|
||||
* The head of the company wants to inform all the company employees of an urgent piece of news. He will inform his direct subordinates, and they will inform their subordinates, and so on until all employees know about the urgent news.
|
||||
* The i-th employee needs informTime[i] minutes to inform all of his direct subordinates (i.e., After informTime[i] minutes, all his direct subordinates can start spreading the news).
|
||||
* Return the number of minutes needed to inform all the employees about the urgent news.
|
||||
*/
|
||||
|
||||
class LC230501CN {
|
||||
public:
|
||||
using CVIR = const std::vector<int>&;
|
||||
static int numOfMinutes(int, int, CVIR, CVIR);
|
||||
};
|
||||
|
||||
int LC230501CN::numOfMinutes(int n, int headID, CVIR manager, CVIR informTime) {
|
||||
std::vector<int> ans(n, -1);
|
||||
ans[headID] = 0;
|
||||
std::function<int(int)> dp = [&](int cur) {
|
||||
return ans[cur] >= 0 ? ans[cur] : ans[cur] = dp(manager[cur]) + informTime[manager[cur]];
|
||||
};
|
||||
int ret = 0;
|
||||
for (int i = 0; i < n; ++i)
|
||||
ret = std::max(ret, dp(i));
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 1822. Sign of the Product of an Array
|
||||
*
|
||||
* There is a function signFunc(x) that returns:
|
||||
*
|
||||
* 1 if x is positive.
|
||||
* -1 if x is negative.
|
||||
* 0 if x is equal to 0.
|
||||
* You are given an integer array nums. Let product be the product of all values in the array nums.
|
||||
*
|
||||
* Return signFunc(product).
|
||||
*/
|
||||
|
||||
class LC230502 {
|
||||
public:
|
||||
static int arraySign(const std::vector<int>&) noexcept;
|
||||
};
|
||||
|
||||
inline constexpr int sgn(int x) noexcept { return (x >> 31) | !!x; }
|
||||
|
||||
int LC230502::arraySign(const std::vector<int>& n) noexcept {
|
||||
return std::reduce(n.begin(), n.end(), 1, [](int x, int y) {
|
||||
return sgn(x) * sgn(y);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class LC230502CN {
|
||||
public:
|
||||
static std::vector<int> powerfulIntegers(int, int, int) noexcept;
|
||||
};
|
||||
|
||||
std::vector<int> LC230502CN::powerfulIntegers(int x, int y, int bound) noexcept {
|
||||
if (bound < 2)
|
||||
return {};
|
||||
if (x < y)
|
||||
std::swap(x, y);
|
||||
if (x <= 1)
|
||||
return {2};
|
||||
std::unordered_set<int> s { 2 };
|
||||
for (int ix = 1; ix + 1 <= bound; ix *= x) {
|
||||
s.insert(ix + 1);
|
||||
if (y <= 1)
|
||||
continue;
|
||||
for (int iy = 1; ix + iy <= bound; iy *= y)
|
||||
s.insert(ix + iy);
|
||||
}
|
||||
return {s.begin(), s.end()};
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
/**
|
||||
* 2215. Find the Difference of Two Arrays
|
||||
*
|
||||
* Given two 0-indexed integer arrays nums1 and nums2, return a list answer of size 2 where:
|
||||
* answer[0] is a list of all distinct integers in nums1 which are not present in nums2.
|
||||
* answer[1] is a list of all distinct integers in nums2 which are not present in nums1.
|
||||
* Note that the integers in the lists may be returned in any order.
|
||||
*/
|
||||
|
||||
class LC230503 {
|
||||
public:
|
||||
template<typename T>
|
||||
using V = std::vector<T>;
|
||||
using VVI = V<V<int>>;
|
||||
using CVIR = const V<int>&;
|
||||
|
||||
static VVI findDifference(CVIR, CVIR) noexcept;
|
||||
};
|
||||
|
||||
LC230503::VVI LC230503::findDifference(CVIR x, CVIR y) noexcept {
|
||||
using USI = std::unordered_set<int>;
|
||||
USI sx(x.begin(), x.end()), sy(y.begin(), y.end());
|
||||
auto proc = [&](const USI& p, const USI& q) {
|
||||
V<int> r;
|
||||
std::copy_if(p.begin(), p.end(), std::back_inserter(r), [&](int n) {
|
||||
return !q.count(n);
|
||||
});
|
||||
return r;
|
||||
};
|
||||
return {proc(sx, sy), proc(sy, sx)};
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <string>
|
||||
|
||||
/**
|
||||
* 1003. Check If Word Is Valid After Substitutions
|
||||
*
|
||||
* Given a string s, determine if it is valid.
|
||||
*
|
||||
* A string s is valid if, starting with an empty string t = "", you can transform t into s after performing the following operation any number of times:
|
||||
*
|
||||
* Insert string "abc" into any position in t. More formally, t becomes t[left] + "abc" + t[right], where t == t[left] + t[right]. Note that t[left] and t[right] may be empty.
|
||||
* Return true if s is a valid string, otherwise, return false.
|
||||
*/
|
||||
|
||||
|
||||
class LC230503CN {
|
||||
public:
|
||||
static bool isValid(const std::string&) noexcept;
|
||||
};
|
||||
|
||||
int matcher(const char* str) noexcept {
|
||||
auto* ptr = str;
|
||||
for (int i = 0; i < 3;) {
|
||||
if (i + 'a' == *str) {
|
||||
// Advance
|
||||
++str;
|
||||
++i;
|
||||
} else if ('a' == *str) {
|
||||
int adv = matcher(str);
|
||||
if (!adv)
|
||||
return 0;
|
||||
str += adv;
|
||||
} else return 0;
|
||||
}
|
||||
return str - ptr;
|
||||
}
|
||||
|
||||
bool LC230503CN::isValid(const std::string& s) noexcept {
|
||||
for (auto* ptr = s.c_str(); *ptr;)
|
||||
if (int adv = matcher(ptr); adv)
|
||||
ptr += adv;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue