diff --git "a/exercise/LC3397_\351\203\221\346\235\203\345\263\260.cpp" "b/exercise/LC3397_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..d70d95bbf2aeaa6ea7de59c36cefd2ad7b86541b --- /dev/null +++ "b/exercise/LC3397_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,67 @@ +#include +using namespace std; + +// 【题目】LC3397.执行操作后不同元素的最大数量 +// 【难度】中等 +// 【提交】2025.10.19 https://leetcode.cn/problems/maximum-number-of-distinct-elements-after-operations/submissions/671555088 +// 【标签】贪心、数组、排序、第429场周赛 + +// 方法1:(执行用时:142ms | 击败:30.20%) +class Solution { +public: + int maxDistinctElements(vector& nums, int k) { + int n = nums.size(); + ranges::sort(nums); + int pre = INT_MIN; + int cnt = 0; + for(int num : nums){ + int cur = min(max(pre + 1, num - k), num + k); + if(cur > pre){ + pre = cur; + cnt++; + } + } + return cnt; + } +}; + +// 方法2:clamp函数优化 (执行用时:121ms | 击败:76.73%) +class Solution { +public: + int maxDistinctElements(vector& nums, int k) { + int n = nums.size(); + ranges::sort(nums); + int pre = INT_MIN; + int cnt = 0; + + for(int num : nums){ + int cur = clamp(num - k, pre + 1, num + k); + if(cur > pre){ + pre = cur; + cnt++; + } + } + return cnt; + } +}; + +// 方法3:初始判断优化 (执行用时:104ms | 击败:94.55%) +class Solution { +public: + int maxDistinctElements(vector& nums, int k) { + int n = nums.size(); + if(2 * k + 1 >= n) return n; // 当 2k+1≥n 时,可以让所有元素互不相同。 + ranges::sort(nums); + int pre = INT_MIN; + int cnt = 0; + + for(int num : nums){ + int cur = clamp(num - k, pre + 1, num + k); + if(cur > pre){ + pre = cur; + cnt++; + } + } + return cnt; + } +}; diff --git "a/topic04/submit/LC1080_\351\203\221\346\235\203\345\263\260.cpp" "b/topic04/submit/LC1080_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..0ab56da4944e3017225f7259721346d074465fa4 --- /dev/null +++ "b/topic04/submit/LC1080_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,73 @@ +#include +using namespace std; + +// 【题目】LC1080.根到叶路径上的不足节点 +// 【难度】中等 (难度分:1804) +// 【提交】2025.10.19 https://leetcode.cn/problems/insufficient-nodes-in-root-to-leaf-paths/submissions/671712459 +// 【标签】树、深度优先搜索、二叉树、第140场周赛 + +// 方法1:(执行时间:2ms | 击败:17.19%) +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + bool checSufficientLeaf(TreeNode* node, int sum, int limit){ + if(!node) return false; + + if(node -> left == nullptr && node -> right == nullptr){ + return node -> val + sum >= limit; + } + + bool haveSufficient_Left = checSufficientLeaf(node -> left, sum + node -> val, limit); + bool haveSufficient_Right = checSufficientLeaf(node -> right, sum + node -> val, limit); + + if(!haveSufficient_Left){ + node -> left = nullptr; + } + if(!haveSufficient_Right){ + node -> right = nullptr; + } + return haveSufficient_Left || haveSufficient_Right; + } + + TreeNode* sufficientSubset(TreeNode* root, int limit) { + bool haveSufficient = checSufficientLeaf(root, 0, limit); + return haveSufficient ? root : nullptr; + } +}; + +// 方法2:直接递归调用自身 (执行时间:0ms | 击败:100.00%) +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + TreeNode* sufficientSubset(TreeNode* root, int limit) { + limit -= root -> val; + if(root -> left == nullptr && root -> right == nullptr){ + return limit > 0 ? nullptr : root; + } + + if(root -> left) root -> left = sufficientSubset(root -> left, limit); + if(root -> right) root -> right = sufficientSubset(root -> right, limit); + + return root -> left || root -> right ? root : nullptr; + } +}; diff --git "a/topic04/submit/LC1766_\351\203\221\346\235\203\345\263\260.cpp" "b/topic04/submit/LC1766_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..097ffc793ae3c4c540032e194ea21e782184dbc1 --- /dev/null +++ "b/topic04/submit/LC1766_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,118 @@ +#include +using namespace std; + +// 【题目】LC1766.互质数 +// 【难度】困难 +// 【提交】2025.10.19 https://leetcode.cn/problems/tree-of-coprimes/submissions/671657077 +// 【标签】树、深度优先搜索、数组、数学、数论、第46场双周赛 + +// 方法1:(执行时间:276ms | 击败:35.00%) +class Solution { +public: + vector getCoprimes(vector& nums, vector>& edges) { + auto gcd = [](int a, int b){ + while(b != 0){ + int temp = b; + b = a % b; + a = temp; + } + return a; + }; + + int n = nums.size(); + vector> g(n); + vector> gcds(51); + vector> ancestors(51); + vector dep(n, -1); + vector res(n, -1); + + for(auto edge : edges){ + g[edge[0]].emplace_back(edge[1]); + g[edge[1]].emplace_back(edge[0]); + } + + auto dfs = [&](this auto&& dfs, int cur, int depth) -> void { + dep[cur] = depth; + for(int x : gcds[nums[cur]]){ + if(ancestors[x].empty()) continue; + int last = ancestors[x].back(); + if(res[cur] == -1 || dep[last] > dep[res[cur]]){ + res[cur] = last; + } + } + ancestors[nums[cur]].emplace_back(cur); + + for(int x : g[cur]){ + if(dep[x] != -1) continue; + dfs(x, depth + 1); + } + ancestors[nums[cur]].pop_back(); + }; + + for(int i = 1; i <= 50; i++){ + for(int j = 1; j <= 50;j++){ + if(gcd(i, j) == 1){ + gcds[i].emplace_back(j); + } + } + } + dfs(0, 0); + return res; + } +}; + +// 方法2:(执行时间:147ms | 击败:86.67%) +const int MX = 51; +vector coprime[MX]; + +auto init = [] { // lambda表达式,而且会自行启动一次 + for(int i = 1;i < MX;i++){ + for(int j = 1;j < MX;j++){ + if(gcd(i, j) == 1){ + coprime[i].emplace_back(j); + } + } + } + return 0; +}(); + +class Solution { + vector> g; + vector ans; + pair val_depth_id[MX]; + + void dfs(int x, int fa, int depth, vector& nums){ + int val = nums[x]; + int max_depth = 0; + for(int j : coprime[val]){ + auto [depth, id] = val_depth_id[j]; + if(depth > max_depth){ + max_depth = depth; + ans[x] = id; + } + } + + auto temp = val_depth_id[val]; + val_depth_id[val] = {depth, x}; + for(int y : g[x]){ + if(y == fa) continue; + dfs(y, x, depth + 1, nums); + } + val_depth_id[val] = temp; + } + +public: + vector getCoprimes(vector& nums, vector>& edges) { + int n = nums.size(); + g.resize(n); + for(auto& e : edges){ + int x = e[0], y = e[1]; + g[x].emplace_back(y); + g[y].emplace_back(x); + } + + ans.resize(n, -1); + dfs(0, -1, 1, nums); + return ans; + } +}; diff --git "a/topic04/submit/LC2467_\351\203\221\346\235\203\345\263\260.cpp" "b/topic04/submit/LC2467_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..6682e2a9b68ac6183f00d75a825be2b4f3a4cbf0 --- /dev/null +++ "b/topic04/submit/LC2467_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,59 @@ +#include +using namespace std; + +// 【题目】LC2467.树上最大得分路径和 +// 【难度】中等 +// 【提交】2025.10.19 https://leetcode.cn/problems/most-profitable-path-in-a-tree/submissions/671601326 +// 【标签】树、深度优先搜索、广度优先搜索、图、数组、第91场双周赛 + +class Solution { +public: + int mostProfitablePath(vector>& edges, int bob, vector& amount) { + int n = edges.size() + 1; + vector> g(n); + for(auto edge : edges){ + g[edge[0]].emplace_back(edge[1]); + g[edge[1]].emplace_back(edge[0]); + } + + vector time_Bob(n, n); + auto dfs_Bob = [&](this auto&& dfs_Bob, int cur, int p, int t) -> bool { + if(cur == 0){ + time_Bob[cur] = t; + return true; + } + for(int x : g[cur]){ + if(x == p) continue; + if(dfs_Bob(x, cur, t + 1)){ + time_Bob[cur] = t; + return true; + } + } + return false; + }; + dfs_Bob(bob, -1, 0); + + int res = INT_MIN; + g[0].emplace_back(-1); + auto DFS = [&](this auto&& DFS, int cur, int p, int active_time, int total) -> void { + if(active_time < time_Bob[cur]){ + total += amount[cur]; + } else if (active_time == time_Bob[cur]){ + total += amount[cur] / 2; + } + + if(g[cur].size() == 1){ + res = max(res, total); + return; + } + + for(int x : g[cur]){ + if(x == p) continue; + DFS(x, cur, active_time + 1, total); + } + }; + + DFS(0, -1, 0, 0); + return res; + } +}; diff --git "a/topic04/submit/LC3067_\351\203\221\346\235\203\345\263\260.cpp" "b/topic04/submit/LC3067_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..bcf0095d428f2bef6e442ad1af6669301a394141 --- /dev/null +++ "b/topic04/submit/LC3067_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,44 @@ +#include +using namespace std; + +// 【题目】LC3067.在带权树状网络中统计可连接服务器对数目 +// 【难度】中等 +// 【提交】2025.10.19 https://leetcode.cn/problems/count-pairs-of-connectable-servers-in-a-weighted-tree-network/submissions/671549960 +// 【标签】树、深度优先搜索、数组、第125场双周赛 + +class Solution { +public: + vector countPairsOfConnectableServers(vector>& edges, int signalSpeed) { + int n = edges.size() + 1; + vector>> g(n); + for(auto edge : edges){ + g[edge[0]].emplace_back(edge[1], edge[2]); + g[edge[1]].emplace_back(edge[0], edge[2]); + } + + auto dfs = [&](this auto&& dfs, int cur, int parent, int Mod) -> int { + int res = 0; + if(Mod == 0) res++; + + for(auto [x, weight] : g[cur]){ + if(x == parent) continue; + res += dfs(x, cur, (Mod + weight) % signalSpeed); + } + return res; + }; + + vector res; + for(int i = 0; i < n; i++){ + if(g[i].size() == 1) {res.emplace_back(0); continue;} + int ans = 0; + int pre = 0; + for(auto [x, weight] : g[i]){ + int tmp = dfs(x, i, weight % signalSpeed); + ans += tmp * pre; + pre += tmp; + } + res.emplace_back(ans); + } + return res; + } +}; diff --git "a/topic04/submit/LC3249_\351\203\221\346\235\203\345\263\260.cpp" "b/topic04/submit/LC3249_\351\203\221\346\235\203\345\263\260.cpp" new file mode 100644 index 0000000000000000000000000000000000000000..b18aa5a3788a226c97aa12a1d1c75c4ed64a4d31 --- /dev/null +++ "b/topic04/submit/LC3249_\351\203\221\346\235\203\345\263\260.cpp" @@ -0,0 +1,49 @@ +#include +using namespace std; + +// 【题目】LC3249.统计好节点的数目 +// 【难度】中等 (难度分:1565) +// 【提交】2025.10.19 https://leetcode.cn/problems/count-the-number-of-good-nodes/submissions/671687343 +// 【标签】树、深度优先搜索 + +// 方法1: 【完全自己做AC】(执行时间:333ms | 击败:77.61%) +class Solution { +public: + int countGoodNodes(vector>& edges) { + int n = edges.size() + 1; + vector> g(n); + for(auto& e : edges){ + int x = e[0], y = e[1]; + g[x].emplace_back(y); + g[y].emplace_back(x); + } + + g[0].emplace_back(-1); + int ans = 0; + + auto dfs = [&](this auto&& dfs, int cur, int p) -> int { + if(g[cur].size() == 1) { + ans++; + return 1; + } + int cur_size = 1; + int flag = true; + + int pre = 0; + for(int x : g[cur]){ + if(x == p) continue; + + int sub = dfs(x, cur); + cur_size += sub; + if(sub != pre && pre != 0) flag = false; + pre = sub; + } + + if(flag) ans++; + return cur_size;; + }; + + dfs(0, -1); + return ans; + } +};