@今日份每日一题:BST节点距离
解题思路
该题的思路总的来说可以分为 建树+LCA
但是值得注意的是,建树有两种方案
- 直接按照节点建树
- 可以用数组代替树,可参考堆结构。
但是目前存在的问题是,题设条件无法知道数据状况,因为数据的输入状况可能导致树转换为链表的形式,这就可能造成数据的大小需要 2 n 2^n 2n,可能会爆内存。更加好的按照数组建树的方法,我还没有想出来,有感兴趣的小伙伴可以想一想。写出来请踢我一下,谢谢!
1. LCA思路
各位请参考 lec236 LCA;
稍微有点不同的地方都在代码里边啦!
2. 代码
#include<vector>
#include<iostream>
using namespace std;
class Solution {
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v = 0, TreeNode* l = nullptr, TreeNode* r = nullptr) :val(v), left(l), right(r) {}
TreeNode(TreeNode &&root) noexcept{
val = root.val;
left = root.left;
right = root.right;
}
~TreeNode() {
if (left) {
delete left;
}
if (right) {
delete right;
}
}
};
class Tree : public TreeNode
{
TreeNode* root;
typedef pair<int, int> pii;
/*
key : -1,0,1
-1: 未找到
0: 找到了一个
1: 两个都找到了
value: 表示找到的节点距离当前节点的长度
*/
pii LCA(TreeNode* cur, int v1, int v2) {
if (nullptr == cur) {
return make_pair(-1, -1);
}
bool flag = false;
if (cur->val == v1 || cur->val == v2) {
flag = true;
}
pii left = LCA(cur->left, v1, v2);
pii right = LCA(cur->right, v1, v2);
if (flag) {
// 1. 当前节点就是需要寻找的某一个节点
// 1.1 如果左右找到了另外一个节点,距离就是左右距离当前节点的距离+1
if (left.first == 0) {
return make_pair(1, left.second + 1);
}
if (right.first == 0) {
return make_pair(1, right.second + 1);
}
// 1.2 如果左右都没有,那就相当于在这个节点找到了其中的某一个节点
return make_pair(0, 0);
}
else {
// 2. 当前节点不是需要寻找的节点
// 2.1 如果左右节点已经可以返回, 直接返回就好
if (left.first == 1) {
return make_pair(1, left.second);
}
if (right.first == 1) {
return make_pair(1, right.second);
}
// 2.2 如果左右节点都找到了
if (left.first == 0 && right.first == 0) {
return make_pair(1, right.second + left.second + 2);
}
// 如果左右有一个找到了
if (left.first == 0) {
return make_pair(0, left.second + 1);
}
if (right.first == 0) {
return make_pair(0, right.second + 1);
}
}
// 3. 啥玩意没有,直接返回没找到
return make_pair(-1, -1);
}
public:
Tree(int val):root(std::move(new TreeNode(val))){
}
~Tree() {
delete root;
}
void insert(int val) {
TreeNode* cur = root;
while (1) {
if (cur->val > val) {
if (nullptr == cur->left) {
cur->left = new TreeNode(val);
break;
}
cur = cur->left;
}
else if (cur->val < val) {
if (nullptr == cur->right) {
cur->right = new TreeNode(val);
break;
}
cur = cur->right;
}
else {
break;
}
}
}
int LCA(int v1, int v2) {
pii ans = LCA(this->root, v1, v2);
return ans.first != 1 ? -1 : ans.second;
}
};
public:
/**
* @param numbers: the given list
* @param node1: the given node1
* @param node2: the given node2
* @return: the distance between two nodes
*/
int bstDistance(vector<int>& numbers, int node1, int node2) {
// Write your code here
// 暴力解法:建树+LCA
/*
1.因为BST插入节点总是插入到空位置,所以就简单建树就好了
- 但是注意,建树后的数组长度可不是原来的长度,按照最坏的打算,应该是2^n (暂时拿树来模拟)
2.LCA算法
*/
int n = numbers.size();
if (n < 2) {
return -1;
}
Tree t(numbers[0]);
for (int i = 1; i < n; ++i) {
t.insert(numbers[i]);
}
return t.LCA(node1, node2);
}
};
int main()
{
vector<int> nums = { 10,18,12,16,19,13,20,3,1,7,14 };
Solution s;
s.bstDistance(nums, 18, 7);
return 0;
}