Compare commits

..

131 Commits

Author SHA1 Message Date
Eatswap c920f9bfd4
add: 231015 2023-10-16 22:28:54 +08:00
Eatswap de11fa9dc3
add: 231014 2023-10-15 00:07:18 +08:00
Eatswap bde1ceb0c2
add: 230927 (3) 2023-09-27 21:16:44 +08:00
Eatswap 40036c20dc
add: 230927 2023-09-27 21:15:32 +08:00
Eatswap 9c9e1f4604
add: 230927 2023-09-27 21:06:12 +08:00
Eatswap 290cdd7b8e
add: 230829 2023-09-27 20:27:58 +08:00
Eatswap 7f8946ce7a
add: 230828 2023-08-28 23:58:03 +08:00
Eatswap 9860bb7a54
add: 230827 2023-08-28 03:05:31 +08:00
Eatswap cc60ceaceb
add: 230520 2023-05-20 23:28:02 +08:00
Eatswap 3a01c0e2a2
add: 230513-CN 2023-05-13 13:43:40 +08:00
Eatswap 0ec5b02f1f
add: 230513 2023-05-13 13:39:27 +08:00
Eatswap 5f1912bf21
add: 230512 2023-05-12 22:22:57 +08:00
Eatswap b84f583b51
add: 230511 2023-05-12 19:40:22 +08:00
Eatswap 50666fbdbd
add: 230511-CN 2023-05-12 18:45:08 +08:00
Eatswap 44c80466fa
add: 230510-CN 2023-05-10 23:19:17 +08:00
Eatswap 2c85f9fc4b
add: 230509 2023-05-09 10:31:48 +08:00
Eatswap 4dcff98da5
add: 230509-CN 2023-05-09 10:08:21 +08:00
Eatswap 615c8444a3
add: 230508-CN 2023-05-08 22:39:50 +08:00
Eatswap 6471f95007
add: 230508 2023-05-08 12:40:29 +08:00
Eatswap d4b780b2f0
add: 230507 2023-05-08 12:34:36 +08:00
Eatswap 6ee1746ac6
add: 230507-CN 2023-05-07 00:28:41 +08:00
Eatswap 062ec6091a
add: 230506-CN 2023-05-06 19:12:38 +08:00
Eatswap bce7fa8ad0
add: 230506 2023-05-06 18:41:05 +08:00
Eatswap 71fa620cd9
add: multiple 2023-05-06 11:56:54 +08:00
Eatswap bfa1062df6
add: 230503 2023-05-03 12:56:57 +08:00
Eatswap 78365bc52a
chore: move staled files 2023-05-03 11:57:16 +08:00
Eatswap 611beb5be6
add: 230503-CN 2023-05-03 11:44:22 +08:00
Eatswap 32f7bd3bd0
add: 230502 2023-05-02 14:12:01 +08:00
Eatswap 477e490bb4
add: ds 2023-05-02 09:54:01 +08:00
Eatswap dbb28499e4
add: 230502-CN 2023-05-02 09:51:35 +08:00
Eatswap e4093d32fd
chore: big refactor 2023-05-02 09:33:39 +08:00
Eatswap 586ed15310
add: 230501 2023-05-01 22:39:10 +08:00
Eatswap c3e72eb840
add: 230501-CN 2023-05-01 22:32:26 +08:00
Eatswap 111c4692c1
add: 230420 2023-04-21 18:27:07 +08:00
Eatswap 9b372dc10f
add: 230421-CN 2023-04-21 17:46:00 +08:00
Eatswap 06b1e482b1
add: 230419 2023-04-20 23:29:34 +08:00
Eatswap 85661e9df6
add: 230420-CN 2023-04-20 23:05:46 +08:00
Eatswap 3fbd7623d9
add: 230419-CN 2023-04-19 18:40:52 +08:00
Eatswap f9f7f6929f
add: noexcept 2023-04-19 12:05:37 +08:00
Eatswap 0ba5fb7cb8
add: 230418-CN 2023-04-19 01:25:52 +08:00
Eatswap 6b5ae005d9
add: 230418 2023-04-19 01:14:40 +08:00
Eatswap 2e711e443b
add: 230417-CN 2023-04-17 12:15:30 +08:00
Eatswap 036f3b7f5d
add: 230417 2023-04-17 11:34:05 +08:00
Eatswap 85fcd9e620
add: 230414 2023-04-14 17:47:13 +08:00
Eatswap aa6da656d3
add: 230414-CN 2023-04-14 04:41:43 +08:00
Eatswap 2deff47e80
add: 230413 2023-04-13 12:06:34 +08:00
Eatswap d77ba88558
add: 230413-CN 2023-04-13 11:51:14 +08:00
Eatswap 8be4d84d34
add: 230412-CN 2023-04-12 23:04:55 +08:00
Eatswap 5c584f805c
add: 230412 2023-04-12 18:24:50 +08:00
Eatswap 61cd797e28
add: 230411-CN 2023-04-11 19:12:26 +08:00
Eatswap dab70cedf8
add: 230411 2023-04-11 10:37:14 +08:00
Eatswap 873ac4de1e
add: 0943 2023-04-11 10:29:24 +08:00
Eatswap a9ff3c5bc0
add: 230410 2023-04-10 11:22:27 +08:00
Eatswap 1c281801e8
add: 230410-CN 2023-04-10 02:47:54 +08:00
Eatswap 6b86835c06
add: 230409 2023-04-10 00:10:23 +08:00
Eatswap 1ff4e631c2
add: 230409-CN 2023-04-09 13:43:07 +08:00
Eatswap 31043a54dc
add: 230408 2023-04-08 15:12:36 +08:00
Eatswap cc6c4312ea
add: 230408-CN 2023-04-08 14:50:32 +08:00
Eatswap 1b168df890
feat: optimise () 2023-04-07 15:55:56 +08:00
Eatswap 476514de0b
feat: optimise 2023-04-07 08:51:41 +08:00
Eatswap 4bfff21cdf
add: 230407 2023-04-07 08:49:39 +08:00
Eatswap dd230c20a5
add: 230406 2023-04-06 19:29:10 +08:00
Eatswap e5a7e1f172
add: 230406-CN 2023-04-06 14:51:57 +08:00
Eatswap a3d4cd6548
add: 230405 2023-04-05 15:08:04 +08:00
Eatswap 5d896a3452
add: 230405-CN 2023-04-05 14:50:26 +08:00
Eatswap c79ce48e37
add: 230404 2023-04-05 01:01:55 +08:00
Eatswap fe2a0b6707
add: 230404-CN 2023-04-04 23:30:23 +08:00
Eatswap c9be7ea9e7
add: 230403 2023-04-04 02:17:16 +08:00
Eatswap 599532847a
add: 230403-CN 2023-04-03 23:47:24 +08:00
Eatswap 169e6b33a2
add: 230402 2023-04-03 13:13:24 +08:00
Eatswap e2e4efacce
add: 230402-CN 2023-04-02 01:21:32 +08:00
Eatswap f8243bfdb3
add: 230401-CN 2023-04-01 15:48:12 +08:00
Eatswap aafc1b7c9f
add: 230401 2023-04-01 15:16:00 +08:00
Eatswap cec4f35834
add: 230330 2023-03-31 18:38:41 +08:00
Eatswap c16d1460c7
add: 230331-CN 2023-03-31 18:17:13 +08:00
Eatswap 60316eaccc
add: 230330-CN 2023-03-30 01:54:23 +08:00
Eatswap b2430377a0
add: 230329 2023-03-29 17:09:20 +08:00
Eatswap e057d343a7
add: 230329-CN 2023-03-29 16:50:55 +08:00
Eatswap 7b1e933924
add: 230328 2023-03-28 15:12:16 +08:00
Eatswap 0fee3db3b8
add: 230327 2023-03-27 23:02:54 +08:00
Eatswap c0825640b4
add: 230327-CN 2023-03-27 22:43:10 +08:00
Eatswap eedc44ba5c
add: 230326-CN 2023-03-26 18:40:00 +08:00
Eatswap 0bf2639257
add: 230325 2023-03-25 16:18:16 +08:00
Eatswap ba5d3bb409
add: 230325-CN 2023-03-25 15:59:20 +08:00
Eatswap bc2e434c78
feat: simplify 2023-03-24 23:53:37 +08:00
Eatswap 8066fae29f
add: 230324 2023-03-24 23:51:51 +08:00
Eatswap c5ff11cf9d
add: 230324-CN 2023-03-24 23:30:39 +08:00
Eatswap 5dd5ebe1c0
add: requires constraint 2023-03-24 00:03:37 +08:00
Eatswap 10d5427eb3
add: 230323 2023-03-23 18:37:25 +08:00
Eatswap 6b55e52a56
add: 230323-CN 2023-03-23 15:41:31 +08:00
Eatswap 76787b7d48
add: 230322 2023-03-23 00:35:37 +08:00
Eatswap 8a10e73747
add: 230322-CN 2023-03-23 00:15:48 +08:00
Eatswap 0bc79d6395
add: 230321 2023-03-21 23:54:03 +08:00
Eatswap 5fb0da597d
add: 230321-CN 2023-03-21 23:45:22 +08:00
Eatswap e785f9fff0
add: 230320 2023-03-20 11:19:26 +08:00
Eatswap f3af871281
add: 230319 2023-03-20 11:10:27 +08:00
Eatswap 069752dd3f
add: 230319-CN 2023-03-19 14:36:49 +08:00
Eatswap 0207e06a04
add: 230318 2023-03-19 02:10:32 +08:00
Eatswap 4ff7357336
add: 230318-CN 2023-03-19 01:56:20 +08:00
Eatswap ea38815e5c
add: 230317 2023-03-17 21:44:13 +08:00
Eatswap cb6cd0b214
add: 230317-CN 2023-03-17 21:14:50 +08:00
Eatswap 693d676aad
add: 230316 2023-03-16 22:27:25 +08:00
Eatswap b9564c775d
add: 230316-CN 2023-03-16 22:14:22 +08:00
Eatswap a5c848b17c
add: 230315-CN 2023-03-15 12:03:32 +08:00
Eatswap 66ac5f1bf2
add: 230315 2023-03-15 11:12:22 +08:00
Eatswap a8e062f2b6
add: 230314 2023-03-14 23:58:07 +08:00
Eatswap ccb2bb4385
add: 230314-CN 2023-03-14 23:46:40 +08:00
Eatswap bebbcb0aa5
add: 230313 2023-03-13 23:33:14 +08:00
Eatswap 56ed525c17
add: 230313-CN 2023-03-13 23:25:49 +08:00
Eatswap 6c5916645b
add: 230312 2023-03-13 01:09:13 +08:00
Eatswap 27593e9adf
add: 230311 2023-03-12 01:34:51 +08:00
Eatswap 4969678067
add: 230310 2023-03-10 10:07:50 +08:00
Eatswap 755c0c2800
add: 230303 2023-03-03 19:09:47 +08:00
Eatswap f76f1f9566
add: 230302 2023-03-02 14:50:59 +08:00
Eatswap e7bd890aa5
add: 230302-CN 2023-03-02 14:05:49 +08:00
Eatswap 57976e72fb
add: 230301-CN 2023-03-02 01:05:02 +08:00
Eatswap d14b269d11
add: const qualifier 2023-03-01 21:13:11 +08:00
Eatswap 63af3ba10d
add: 230228 2023-03-01 21:09:35 +08:00
Eatswap 7a0acbf6a3
add: 230301 2023-03-01 12:12:50 +08:00
Eatswap acd093331d
add: 0010 2023-02-28 21:11:40 +08:00
Eatswap e4d15ecf06
add: 230228-CN 2023-02-28 21:07:24 +08:00
Eatswap 2cc35c392a
add: 230227 2023-02-28 20:41:42 +08:00
Eatswap d38873562f
add: 230227-CN 2023-02-28 20:39:50 +08:00
Eatswap 431ced268f
add: 230221 2023-02-21 10:00:56 +08:00
Eatswap da5f92691c
add: 230221-CN 2023-02-21 09:16:45 +08:00
Eatswap 35f4170a85
add: 230220-CN 2023-02-20 11:11:35 +08:00
Eatswap 6fdf7e8391
add: 230220 2023-02-20 10:35:58 +08:00
Eatswap 692c3ba537
add: 230219 2023-02-19 22:27:12 +08:00
Eatswap b8916e9ab7
add: 230219-CN 2023-02-19 01:59:49 +08:00
Eatswap 9c89a0e22f
add: 230218-CN 2023-02-18 23:46:41 +08:00
Eatswap da93f6229e
add: 230218 2023-02-18 22:02:46 +08:00
159 changed files with 5693 additions and 4 deletions

69
cpp/2302/230218-CN.cpp Normal file
View File

@ -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;
}

21
cpp/2302/230218.cpp Normal file
View File

@ -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;
}
};

40
cpp/2302/230219-CN.cpp Normal file
View File

@ -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;
}

45
cpp/2302/230219.cpp Normal file
View File

@ -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;
}
};

37
cpp/2302/230220-CN.cpp Normal file
View File

@ -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";
}
};

16
cpp/2302/230220.cpp Normal file
View File

@ -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();
}
};

41
cpp/2302/230221-CN.cpp Normal file
View File

@ -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}));
}

28
cpp/2302/230221.cpp Normal file
View File

@ -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;
}

32
cpp/2302/230227-CN.cpp Normal file
View File

@ -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);
}
};

7
cpp/2302/230227.cpp Normal file
View File

@ -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
*/

30
cpp/2302/230228-CN.cpp Normal file
View File

@ -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;
}
};

56
cpp/2302/230228.cpp Normal file
View File

@ -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;
}

6
cpp/2302/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
PROJECT(2302)
SET(CMAKE_CXX_STANDARD 23)
ADD_EXECUTABLE(2302 230228.cpp)

28
cpp/2303/230301-CN.cpp Normal file
View File

@ -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;
}
};

31
cpp/2303/230301.cpp Normal file
View File

@ -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;
}

31
cpp/2303/230302-CN.cpp Normal file
View File

@ -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;
}

51
cpp/2303/230302.cpp Normal file
View File

@ -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;
}

33
cpp/2303/230303.cpp Normal file
View File

@ -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;
}

47
cpp/2303/230310.cpp Normal file
View File

@ -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()];
}
};

98
cpp/2303/230311.cpp Normal file
View File

@ -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;
}

65
cpp/2303/230312.cpp Normal file
View File

@ -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;
}

35
cpp/2303/230313-CN.cpp Normal file
View File

@ -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;
}

29
cpp/2303/230313.cpp Normal file
View File

@ -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);
}
};

37
cpp/2303/230314-CN.cpp Normal file
View File

@ -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;
}

46
cpp/2303/230314.cpp Normal file
View File

@ -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;
}
};

29
cpp/2303/230315-CN.cpp Normal file
View File

@ -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;
}
};

44
cpp/2303/230315.cpp Normal file
View File

@ -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;
}

44
cpp/2303/230316-CN.cpp Normal file
View File

@ -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;
}

42
cpp/2303/230316.cpp Normal file
View File

@ -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;
}

31
cpp/2303/230317-CN.cpp Normal file
View File

@ -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;
}

69
cpp/2303/230317.cpp Normal file
View File

@ -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;
}

95
cpp/2303/230318-CN.cpp Normal file
View File

@ -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;
}

43
cpp/2303/230318.cpp Normal file
View File

@ -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)];
}
};

60
cpp/2303/230319-CN.cpp Normal file
View File

@ -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);
}

69
cpp/2303/230319.cpp Normal file
View File

@ -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;
}

23
cpp/2303/230320.cpp Normal file
View File

@ -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;
}
};

16
cpp/2303/230321-CN.cpp Normal file
View File

@ -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};
}
};

34
cpp/2303/230321.cpp Normal file
View File

@ -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;
}

46
cpp/2303/230322-CN.cpp Normal file

File diff suppressed because one or more lines are too long

58
cpp/2303/230322.cpp Normal file
View File

@ -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;
}

110
cpp/2303/230323-CN.cpp Normal file
View File

@ -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");
}
}

47
cpp/2303/230323.cpp Normal file
View File

@ -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;
}
};

77
cpp/2303/230324-CN.cpp Normal file
View File

@ -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;
}

43
cpp/2303/230324.cpp Normal file
View File

@ -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;
}

49
cpp/2303/230325-CN.cpp Normal file
View File

@ -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;
}

52
cpp/2303/230325.cpp Normal file
View File

@ -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}
});
}

24
cpp/2303/230326-CN.cpp Normal file
View File

@ -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;
}
};

34
cpp/2303/230327-CN.cpp Normal file
View File

@ -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;
}
};

22
cpp/2303/230327.cpp Normal file
View File

@ -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];
}
};

46
cpp/2303/230328.cpp Normal file
View File

@ -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;
}

39
cpp/2303/230329-CN.cpp Normal file
View File

@ -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;
}

29
cpp/2303/230329.cpp Normal file
View File

@ -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;
}

25
cpp/2303/230330-CN.cpp Normal file
View File

@ -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;
}
};

54
cpp/2303/230330.cpp Normal file
View File

@ -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());
}
};

24
cpp/2303/230331-CN.cpp Normal file
View File

@ -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);
});
}
};

6
cpp/2303/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
PROJECT(2303)
SET(CMAKE_CXX_STANDARD 23)
ADD_EXECUTABLE(2303 230330.cpp)

66
cpp/2304/230401-CN.cpp Normal file
View File

@ -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);
}
};

17
cpp/2304/230401.cpp Normal file
View File

@ -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;
}
};

43
cpp/2304/230402-CN.cpp Normal file
View File

@ -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);
}
};

35
cpp/2304/230402.cpp Normal file
View File

@ -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;
}

28
cpp/2304/230403-CN.cpp Normal file
View File

@ -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;
}
};

47
cpp/2304/230403.cpp Normal file
View File

@ -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;
}

37
cpp/2304/230404-CN.cpp Normal file
View File

@ -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];
}
};

29
cpp/2304/230404.cpp Normal file
View File

@ -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;
}

25
cpp/2304/230405-CN.cpp Normal file
View File

@ -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;
}

34
cpp/2304/230405.cpp Normal file
View File

@ -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;
}

87
cpp/2304/230406-CN.cpp Normal file
View File

@ -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;
}

63
cpp/2304/230406.cpp Normal file
View File

@ -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;
}

58
cpp/2304/230407.cpp Normal file
View File

@ -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;
}

88
cpp/2304/230408-CN.cpp Normal file
View File

@ -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;
}

59
cpp/2304/230408.cpp Normal file
View File

@ -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;
}

36
cpp/2304/230409-CN.cpp Normal file
View File

@ -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
});
}

88
cpp/2304/230409.cpp Normal file
View File

@ -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;
}

62
cpp/2304/230410-CN.cpp Normal file
View File

@ -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;
}

47
cpp/2304/230410.cpp Normal file
View File

@ -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;
}

48
cpp/2304/230411-CN.cpp Normal file
View File

@ -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;
}

33
cpp/2304/230411.cpp Normal file
View File

@ -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;
}

53
cpp/2304/230412-CN.cpp Normal file
View File

@ -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;
}

44
cpp/2304/230412.cpp Normal file
View File

@ -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;
}

27
cpp/2304/230413-CN.cpp Normal file
View File

@ -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;
}

32
cpp/2304/230413.cpp Normal file
View File

@ -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;
}

70
cpp/2304/230414-CN.cpp Normal file
View File

@ -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;
}

46
cpp/2304/230414.cpp Normal file
View File

@ -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;
}

39
cpp/2304/230417-CN.cpp Normal file
View File

@ -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;
}

23
cpp/2304/230417.cpp Normal file
View File

@ -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;
}

39
cpp/2304/230418-CN.cpp Normal file
View File

@ -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;
}

35
cpp/2304/230418.cpp Normal file
View File

@ -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");
}

53
cpp/2304/230419-CN.cpp Normal file
View File

@ -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;
}

58
cpp/2304/230419.cpp Normal file
View File

@ -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;
}

41
cpp/2304/230420-CN.cpp Normal file
View File

@ -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;
}

53
cpp/2304/230420.cpp Normal file
View File

@ -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() {
;
}

12
cpp/2304/230421-CN.cpp Normal file
View File

@ -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);
}
};

7
cpp/2304/CMakeLists.txt Normal file
View File

@ -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)

9
cpp/2305/CMakeLists.txt Normal file
View File

@ -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})

23
cpp/2305/LC230501.cpp Normal file
View File

@ -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);
}

32
cpp/2305/LC230501CN.cpp Normal file
View File

@ -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;
}

28
cpp/2305/LC230502.cpp Normal file
View File

@ -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);
});
}

25
cpp/2305/LC230502CN.cpp Normal file
View File

@ -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()};
}

36
cpp/2305/LC230503.cpp Normal file
View File

@ -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)};
}

44
cpp/2305/LC230503CN.cpp Normal file
View File

@ -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