Skip to content

Commit

Permalink
feat&bugfix: find real leetcode_235
Browse files Browse the repository at this point in the history
Signed-off-by: Certseeds <[email protected]>
  • Loading branch information
Certseeds committed Feb 25, 2024
1 parent 0aa479c commit 661ccd3
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 129 deletions.
2 changes: 1 addition & 1 deletion algorithm/tree/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
103 changes: 86 additions & 17 deletions algorithm/tree/leetcode_235.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <unordered_map>

// 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<int32_t> 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<TreeNode*, int32_t> 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 <q->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<TreeNode *, uint8_t> &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<TreeNode *, uint8_t> 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;
}

}
51 changes: 41 additions & 10 deletions algorithm/tree/leetcode_235_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -21,21 +20,53 @@ Copyright (C) 2020-2023 nanoseeds
namespace leetcode_235 {

using TreeNode = TREE_NODE::TreeNode<int32_t>;

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<int32_t>;
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
59 changes: 0 additions & 59 deletions algorithm/tree/leetcode_236.cpp

This file was deleted.

42 changes: 0 additions & 42 deletions algorithm/tree/leetcode_236_test.hpp

This file was deleted.

30 changes: 30 additions & 0 deletions algorithm/tree/leetcode_unknown.cpp
Original file line number Diff line number Diff line change
@@ -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_unknown::findTarget(TreeNode *root, int k) {
vector<int32_t> 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;
}
}
41 changes: 41 additions & 0 deletions algorithm/tree/leetcode_unknown_test.hpp
Original file line number Diff line number Diff line change
@@ -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 <catch_main.hpp>
#include <cstdint>
#include <cstddef>
#include <tree/treenode.hpp>
#include <tree/treenode_link.hpp>
#include <vector>

namespace leetcode_unknown {

using TreeNode = TREE_NODE::TreeNode<int32_t>;

struct leetcode_unknown {
static bool findTarget(TreeNode *root, int k);
};

using TreeNodeLink = TREE_NODE::TreeNodeLink<int32_t>;

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

0 comments on commit 661ccd3

Please sign in to comment.