From cd55d110e88a0872a0686968ba5c961b5f6fe723 Mon Sep 17 00:00:00 2001 From: Certseeds <51754303+Certseeds@users.noreply.github.com> Date: Sun, 25 Feb 2024 07:23:02 +0000 Subject: [PATCH] feat&bugfix: find real leetcode_235 Signed-off-by: Certseeds <51754303+Certseeds@users.noreply.github.com> --- algorithm/tree/CMakeLists.txt | 2 +- algorithm/tree/leetcode_235.cpp | 103 +++++++++++++++++++---- algorithm/tree/leetcode_235_test.hpp | 51 ++++++++--- algorithm/tree/leetcode_236.cpp | 59 ------------- algorithm/tree/leetcode_236_test.hpp | 42 --------- algorithm/tree/leetcode_unknown.cpp | 30 +++++++ algorithm/tree/leetcode_unknown_test.hpp | 41 +++++++++ 7 files changed, 199 insertions(+), 129 deletions(-) delete mode 100644 algorithm/tree/leetcode_236.cpp delete mode 100644 algorithm/tree/leetcode_236_test.hpp create mode 100644 algorithm/tree/leetcode_unknown.cpp create mode 100644 algorithm/tree/leetcode_unknown_test.hpp diff --git a/algorithm/tree/CMakeLists.txt b/algorithm/tree/CMakeLists.txt index 7612cc9d..8c68f091 100644 --- a/algorithm/tree/CMakeLists.txt +++ b/algorithm/tree/CMakeLists.txt @@ -13,7 +13,7 @@ LIST(APPEND leetcode_order 590 617 654 669 700) LIST(APPEND leetcode_order 701 144 145 102 101) LIST(APPEND leetcode_order 112 235 653 so_32 so_26) LIST(APPEND leetcode_order 113 426 so_54 114 230) -LIST(APPEND leetcode_order 236 543 199 814 872) +LIST(APPEND leetcode_order unknown 543 199 814 872) LIST(APPEND leetcode_order 894 897 938 965 993) LIST(APPEND leetcode_order 1008 1022 1038 1104 1261) LIST(APPEND leetcode_order 1302 1315 1325 1367 1372) diff --git a/algorithm/tree/leetcode_235.cpp b/algorithm/tree/leetcode_235.cpp index 2368ab90..50d1ee02 100644 --- a/algorithm/tree/leetcode_235.cpp +++ b/algorithm/tree/leetcode_235.cpp @@ -2,29 +2,98 @@ /* CS203_DSAA_template -Copyright (C) 2020-2023 nanoseeds +Copyright (C) 2020-2024 nanoseeds */ #include "leetcode_235_test.hpp" -#include "traverse.cpp" +#include +// in cn, it is https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree +// in us, it same with cn. it is https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree +// why it's named _236 and where did the origin 235 come from ? namespace leetcode_235 { -using namespace Tree_Traverse; - -bool leetcode_235::findTarget(TreeNode *root, int k) { - vector targets{}; - const auto func = [&targets](const TreeNode *tn) -> void { targets.push_back(tn->val); }; - iter::in(root, func); - for (size_t ll{0}, rr{targets.size() - 1}; ll < rr;) { - const auto sum = targets[ll] + targets[rr]; - if (sum == k) { - return true; - } else if (sum > k) { - --rr; - } else if (sum < k) { - ++ll; +using std::unordered_map; + +const TreeNode *leetcode_235::lowestCommonAncestorV2(TreeNode *root, + TreeNode *p, TreeNode *q) { + // first, visit the p node, find it's parent-link + // then, visit the q node and match it's parents one by one. + if (root->val == p->val || root->val == q->val){ + return root; + } + unordered_map node_to_depth{}; + int32_t depth{1}; + for(TreeNode* base{root};base != nullptr && base->val != p->val;depth++ ) { + node_to_depth[base] = depth; + if (base->val > p->val) { + base = base->left; + } else if (base->val < p->val) { + base = base->right; + } + } + node_to_depth[p] = depth; + TreeNode* will_return{nullptr}; + depth = 0; + for(TreeNode* base{root};base != nullptr && base->val != q->val;) { + if (node_to_depth.count(base) != 0 && node_to_depth[base] > depth) { + will_return = base; + depth = node_to_depth[base]; + } + if (base->val > q->val) { + base = base->left; + } else if (base->val val) { + base = base->right; } } - return false; + if (node_to_depth.count(q) != 0 && node_to_depth[q] > depth) { + will_return = q; + } + return will_return; } + +bool nodeHadValue(unordered_map &umap, TreeNode *base, int32_t value) { + if (base == nullptr) { + return false; + } + if (umap.count(base) != 0) { + return umap.at(base); + } + if (base->val == value) { + umap[base] = true; + return true; + } + const auto will_return = nodeHadValue(umap, base->left, value) || nodeHadValue(umap, base->right, value); + umap[base] = will_return; + return will_return; +} + +const TreeNode * +leetcode_235::lowestCommonAncestor(const TreeNode *root, const TreeNode *const p, const TreeNode *const q) { + if (root == nullptr) { + return nullptr; + } + for (unordered_map pmap, qmap; root != nullptr;) { + if (root->val == p->val) { + return p; + } else if (root->val == q->val) { + return q; + } + const auto pleft = nodeHadValue(pmap, root->left, p->val); + const auto pright = nodeHadValue(pmap, root->right, p->val); + + const auto qleft = nodeHadValue(qmap, root->left, q->val); + const auto qright = nodeHadValue(qmap, root->right, q->val); + if (pleft && qright) { + return root; + } else if (pright && qleft) { + return root; + } else if (pleft && qleft) { + root = root->left; + } else { + root = root->right; + } + } + return nullptr; +} + } diff --git a/algorithm/tree/leetcode_235_test.hpp b/algorithm/tree/leetcode_235_test.hpp index f312f55c..1dcea547 100644 --- a/algorithm/tree/leetcode_235_test.hpp +++ b/algorithm/tree/leetcode_235_test.hpp @@ -7,7 +7,6 @@ Copyright (C) 2020-2023 nanoseeds */ //@Tag tree //@Tag 树 -//@Plan 数据结构入门 Day14 #ifndef CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_235_TEST_HPP #define CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_235_TEST_HPP @@ -21,21 +20,53 @@ Copyright (C) 2020-2023 nanoseeds namespace leetcode_235 { using TreeNode = TREE_NODE::TreeNode; - -struct leetcode_235 { - static bool findTarget(TreeNode *root, int k); +namespace leetcode_235 { + const TreeNode *lowestCommonAncestor(const TreeNode *root, const TreeNode *p, const TreeNode *q); + const TreeNode *lowestCommonAncestorV2(TreeNode *root, TreeNode *p, TreeNode *q); }; + using TreeNodeLink = TREE_NODE::TreeNodeLink; +using TREE_NODE::numToTree; TEST_CASE("test_case 1 [test_235]", "[test_235]") { + const TreeNodeLink input{6, + 2, 8, + 0, 4, 7, 9, + TreeNode::No, TreeNode::No, 3, 5}; + const TreeNode p{2}, q{8}; + static constexpr const auto result{6}; + CHECK(result == leetcode_235::lowestCommonAncestor(input[0], &p, &q)->val); + CHECK(result == leetcode_235::lowestCommonAncestorV2(input[0], input[1], input[2])->val); +} +TEST_CASE("test_case 2 [test_235]", "[test_235]") { + const TreeNodeLink input{2, + 1}; + const TreeNode p{1}, q{2}; + static constexpr const auto result{2}; + CHECK(result == leetcode_235::lowestCommonAncestor(input[0], &p, &q)->val); + CHECK(result == leetcode_235::lowestCommonAncestorV2(input[0], input[0], input[1])->val); +} + +TEST_CASE("test_case 3 [test_235]", "[test_235]") { + const TreeNodeLink input{6, + 2, 8, + 0, 4, 7, 9, + TreeNode::No, TreeNode::No, 3, 5}; + TreeNode p{2}, q{4}; + static constexpr const auto result{2}; + CHECK(result == leetcode_235::lowestCommonAncestor(input[0], &p, &q)->val); + CHECK(result == leetcode_235::lowestCommonAncestorV2(input[0], input[1], input[4])->val); +} +TEST_CASE("test_case 4 [test_235]", "[test_235]") { const TreeNodeLink input{5, - 3, 6, - 2, 4, TreeNode::No, 7, - TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, - TreeNode::No, TreeNode::No}; - static constexpr const auto target{9}; - CHECK(leetcode_235::findTarget(input[0], target)); + 3, 6, + 2, 4,TreeNode::No, TreeNode::No, + 1}; + TreeNode p{1}, q{3}; + static constexpr const auto result{3}; + CHECK(result == leetcode_235::lowestCommonAncestor(input[0], &p, &q)->val); + CHECK(result == leetcode_235::lowestCommonAncestorV2(input[0], input[7], input[1])->val); } } #endif //CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_235_TEST_HPP diff --git a/algorithm/tree/leetcode_236.cpp b/algorithm/tree/leetcode_236.cpp deleted file mode 100644 index 20ea71bf..00000000 --- a/algorithm/tree/leetcode_236.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-or-later -/* -CS203_DSAA_template - -Copyright (C) 2020-2023 nanoseeds - -*/ -#include "leetcode_236_test.hpp" -#include - -namespace leetcode_236 { -using std::unordered_map; - -bool nodeHadValue(unordered_map &umap, TreeNode *base, int32_t value) { - if (base == nullptr) { - return false; - } - if (umap.count(base) != 0) { - return umap.at(base); - } - if (base->val == value) { - umap[base] = true; - return true; - } - const auto will_return = nodeHadValue(umap, base->left, value) || nodeHadValue(umap, base->right, value); - umap[base] = will_return; - return will_return; -} - -const TreeNode * -leetcode_236::lowestCommonAncestor(const TreeNode *root, const TreeNode *const p, const TreeNode *const q) { - if (root == nullptr) { - return nullptr; - } - for (unordered_map pmap, qmap; root != nullptr;) { - if (root->val == p->val) { - return p; - } else if (root->val == q->val) { - return q; - } - const auto pleft = nodeHadValue(pmap, root->left, p->val); - const auto pright = nodeHadValue(pmap, root->right, p->val); - - const auto qleft = nodeHadValue(qmap, root->left, q->val); - const auto qright = nodeHadValue(qmap, root->right, q->val); - if (pleft && qright) { - return root; - } else if (pright && qleft) { - return root; - } else if (pleft && qleft) { - root = root->left; - } else { - root = root->right; - } - } - return nullptr; -} - -} diff --git a/algorithm/tree/leetcode_236_test.hpp b/algorithm/tree/leetcode_236_test.hpp deleted file mode 100644 index 9a4037e2..00000000 --- a/algorithm/tree/leetcode_236_test.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-or-later -/* -CS203_DSAA_template - -Copyright (C) 2020-2023 nanoseeds - -*/ -//@Tag tree -//@Tag 树 -#ifndef CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_236_TEST_HPP -#define CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_236_TEST_HPP - -#include -#include -#include -#include -#include -#include - -namespace leetcode_236 { - -using TreeNode = TREE_NODE::TreeNode; - -struct leetcode_236 { - static const TreeNode *lowestCommonAncestor(const TreeNode *root, const TreeNode *p, const TreeNode *q); -}; - - -using TreeNodeLink = TREE_NODE::TreeNodeLink; -using TREE_NODE::numToTree; - -TEST_CASE("test_case 1 [test_236]", "[test_236]") { - const TreeNodeLink input{3, - 5, 1, - 6, 2, 0, 8, - TreeNode::No, TreeNode::No, 7, 4}; - const TreeNode p{5}, q{1}; - static constexpr const auto result{3}; - CHECK(result == leetcode_236::lowestCommonAncestor(input[0], &p, &q)->val); -} -} -#endif //CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_236_TEST_HPP diff --git a/algorithm/tree/leetcode_unknown.cpp b/algorithm/tree/leetcode_unknown.cpp new file mode 100644 index 00000000..c2fe8f38 --- /dev/null +++ b/algorithm/tree/leetcode_unknown.cpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +/* +CS203_DSAA_template + +Copyright (C) 2020-2023 nanoseeds + +*/ +#include "leetcode_unknown_test.hpp" +#include "traverse.cpp" + +namespace leetcode_unknown { +using namespace Tree_Traverse; + +bool leetcode_235::findTarget(TreeNode *root, int k) { + vector targets{}; + const auto func = [&targets](const TreeNode *tn) -> void { targets.push_back(tn->val); }; + iter::in(root, func); + for (size_t ll{0}, rr{targets.size() - 1}; ll < rr;) { + const auto sum = targets[ll] + targets[rr]; + if (sum == k) { + return true; + } else if (sum > k) { + --rr; + } else if (sum < k) { + ++ll; + } + } + return false; +} +} diff --git a/algorithm/tree/leetcode_unknown_test.hpp b/algorithm/tree/leetcode_unknown_test.hpp new file mode 100644 index 00000000..c7cc0e2a --- /dev/null +++ b/algorithm/tree/leetcode_unknown_test.hpp @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +/* +CS203_DSAA_template + +Copyright (C) 2020-2023 nanoseeds + +*/ +//@Tag tree +//@Tag 树 +//@Plan 数据结构入门 Day14 +#ifndef CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_UNKNOWN_TEST_HPP +#define CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_UNKNOWN_TEST_HPP + +#include +#include +#include +#include +#include +#include + +namespace leetcode_unknown { + +using TreeNode = TREE_NODE::TreeNode; + +struct leetcode_unknown { + static bool findTarget(TreeNode *root, int k); +}; + +using TreeNodeLink = TREE_NODE::TreeNodeLink; + +TEST_CASE("test_case 1 [test_235]", "[test_235]") { + const TreeNodeLink input{5, + 3, 6, + 2, 4, TreeNode::No, 7, + TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, TreeNode::No, + TreeNode::No, TreeNode::No}; + static constexpr const auto target{9}; + CHECK(leetcode_unknown::findTarget(input[0], target)); +} +} +#endif //CS203_DSAA_TEMPLATE_ALGORITHM_TREE_LEETCODE_UNKNOWN_TEST_HPP