当前位置:网站首页>Returns the lowest common ancestor of two nodes in a binary tree
Returns the lowest common ancestor of two nodes in a binary tree
2022-07-05 02:34:00 【Bright morning light】
1、 subject
Given the root node of a binary tree root, And two other nodes a and b, return a and b The lowest common ancestor of .
2、 analysis
The lowest common ancestor : Two nodes go up , To which node , This node is the lowest common ancestor . For a node is the root , The other node is the node on its subtree , The root node is the lowest common ancestor .
Method 1 : Traversing the binary tree , Use a hash table to record the parent node of each node , The nodes a All nodes along the way to the root node are put into a set , Then find from b Start along the way to the root node. What nodes are in the collection , Then it is the lowest common ancestor .
Method 2 : Binary tree recursive routine .
- The goal is : Given a and b node , stay x For the root of this binary tree , find a and b The node that converges at the beginning . If there is no convergence , It returns null , Otherwise, return to the converged node .
- possibility : Did you find a node , Did you find b node .
There are two kinds of :- Convergence point and x irrelevant (x Not the lowest convergence point )
① a and b Gathered on the left tree ;
② a and b Gathered on the right tree ;
③ a and b Incomplete , That is, there is only one node in the tree or there is no . - Convergence point and x of (x Is the lowest convergence point )
① Zuoshu found a and b One of them , Right tree found another , They are x Convergence at ;
② x Itself is a node , Then I found it in the left tree or the right tree b node ;
③ x Itself is b node , Then I found it in the left tree or the right tree a node ;
- Convergence point and x irrelevant (x Not the lowest convergence point )
In conclusion , The information to be collected from the left tree and the right tree :(1) Did you find it in the tree a;(2) Did you find it in the tree b;(3)a and b The lowest common ancestor of convergence .
Collect the information of the left tree and the right tree , Then update the information of the current node , So that's one After the sequence traversal , Time complexity O ( n ) O(n) O(n).
3、 Realization
C++ edition
/************************************************************************* > File Name: 040. Returns the lowest common ancestor of the two nodes of the binary tree .cpp > Author: Maureen > Mail: [email protected] > Created Time: One 7/ 4 13:42:23 2022 ************************************************************************/
#include <iostream>
#include <ctime>
#include <unordered_map>
#include <set>
#include <vector>
using namespace std;
class TreeNode {
public:
int value;
TreeNode *left;
TreeNode *right;
TreeNode(int data) : value(data) {
}
};
// Method 1 : Create a table to save the parent node information
void fillParentMap(TreeNode *root, unordered_map<TreeNode*, TreeNode*> &parentMap) {
if (root->left != nullptr) {
parentMap[root->left] = root;
fillParentMap(root->left, parentMap);
}
if (root->right != nullptr) {
parentMap[root->right] = root;
fillParentMap(root->right, parentMap);
}
}
TreeNode *lowestAncestor1(TreeNode *root, TreeNode *o1, TreeNode *o2) {
if (root == nullptr) return nullptr;
unordered_map<TreeNode*, TreeNode*> parentMap;
parentMap[root] = nullptr;
fillParentMap(root, parentMap);// Save the parent node of each node
set<TreeNode*> o1set;
TreeNode *cur = o1;
//o1 All nodes along the way to the root node are put into o1set in
while (cur != nullptr) {
o1set.insert(cur);
cur = parentMap[cur];
}
cur = o2;
while (!o1set.count(cur)) {
cur = parentMap[cur];
}
return cur;
}
// Method 2 : Binary tree recursive routine
class Info {
public:
bool existA;
bool existB;
TreeNode *ancestor;
Info(bool a, bool b, TreeNode *node) : existA(a), existB(b), ancestor(node) {
}
};
Info *process(TreeNode *x, TreeNode *a, TreeNode *b) {
if (x == nullptr) {
return new Info(false, false, nullptr);
}
Info *leftInfo = process(x->left, a, b);
Info *rightInfo = process(x->right, a, b);
bool existA = (x == a) || leftInfo->existA || rightInfo->existA;
bool existB = (x == b) || leftInfo->existB || rightInfo->existB;
TreeNode *ancestor = nullptr;
if (leftInfo->ancestor != nullptr) {
ancestor = leftInfo->ancestor;
} else if(rightInfo->ancestor != nullptr) {
ancestor = rightInfo->ancestor;
} else {
if (existA && existB) ancestor = x;
}
return new Info(existA, existB, ancestor);
}
TreeNode *lowestAncestor2(TreeNode *root, TreeNode *a, TreeNode *b) {
return process(root, a, b)->ancestor;
}
//for test
//for test
TreeNode *generate(int level, int maxl, int maxv) {
if (level > maxl || (rand() % 100 / (double)101) < 0.5)
return nullptr;
TreeNode *root = new TreeNode(rand() % maxv);
root->left = generate(level + 1, maxl, maxv);
root->right = generate(level + 1, maxl, maxv);
return root;
}
TreeNode *generateRandomBST(int level, int value) {
return generate(1, level, value);
}
void fillPrelist(TreeNode *root, vector<TreeNode*> &arr) {
if (root == nullptr) return ;
arr.push_back(root);
fillPrelist(root->left, arr);
fillPrelist(root->right, arr);
}
TreeNode *pickRandomOne(TreeNode *root) {
if (root == nullptr) return nullptr;
vector<TreeNode*> arr;
fillPrelist(root, arr);
int randInd = rand() % arr.size();
return arr[randInd];
}
int main() {
srand(time(0));
int maxLevel = 4;
int maxValue = 100;
int testTimes = 1000001;
cout << "Test begin:" << endl;
for (int i = 0; i < testTimes; i++) {
TreeNode *root = generateRandomBST(maxLevel, maxValue);
TreeNode *a = pickRandomOne(root);
TreeNode *b = pickRandomOne(root);
if (lowestAncestor1(root, a, b) != lowestAncestor2(root, a, b)) {
cout << "Failed!" << endl;
return 0;
}
if (i && i % 1000 == 0) cout << i << " cases passed!" << endl;
}
cout << "Success!!" << endl;
return 0;
}
Java edition
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class LowestAncestor{
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
// Method 1 : Build table , Save parent node information
public static Node lowestAncestor1(Node head, Node o1, Node o2) {
if (head == null) {
return null;
}
// key The parent of is value
HashMap<Node, Node> parentMap = new HashMap<>();
parentMap.put(head, null);
fillParentMap(head, parentMap);
HashSet<Node> o1Set = new HashSet<>();
Node cur = o1;
o1Set.add(cur);
while (parentMap.get(cur) != null) {
cur = parentMap.get(cur);
o1Set.add(cur);
}
cur = o2;
while (!o1Set.contains(cur)) {
cur = parentMap.get(cur);
}
return cur;
}
public static void fillParentMap(Node head, HashMap<Node, Node> parentMap) {
if (head.left != null) {
parentMap.put(head.left, head);
fillParentMap(head.left, parentMap);
}
if (head.right != null) {
parentMap.put(head.right, head);
fillParentMap(head.right, parentMap);
}
}
// Method 2 : Binary tree recursive routine
public static Node lowestAncestor2(Node head, Node a, Node b) {
return process(head, a, b).ans;
}
public static class Info {
public boolean findA; // Whether to find a
public boolean findB; // Whether to find b
public Node ans; // Find the convergence point
public Info(boolean fa, boolean fb, Node an) {
findA = fa;
findB = fb;
ans = an;
}
}
public static Info process(Node x, Node a, Node b) {
if (x == null) {
// Set empty tree
return new Info(false, false, null);
}
Info leftInfo = process(x.left, a, b);
Info rightInfo = process(x.right, a, b);
// Find out a and b
boolean findA = (x == a) || leftInfo.findA || rightInfo.findA;
boolean findB = (x == b) || leftInfo.findB || rightInfo.findB;
Node ans = null;
if (leftInfo.ans != null) {
// Find the initial convergence point on the left tree
ans = leftInfo.ans;
} else if (rightInfo.ans != null) {
// Find the initial convergence point on the right tree
ans = rightInfo.ans;
} else {
// Neither the left tree nor the right tree can find the convergence point
if (findA && findB) {
// If you find out a and b, Then the convergence point must be x
ans = x;
}
}
return new Info(findA, findB, ans);
}
// for test
public static Node generateRandomBST(int maxLevel, int maxValue) {
return generate(1, maxLevel, maxValue);
}
// for test
public static Node generate(int level, int maxLevel, int maxValue) {
if (level > maxLevel || Math.random() < 0.5) {
return null;
}
Node head = new Node((int) (Math.random() * maxValue));
head.left = generate(level + 1, maxLevel, maxValue);
head.right = generate(level + 1, maxLevel, maxValue);
return head;
}
// for test
public static Node pickRandomOne(Node head) {
if (head == null) {
return null;
}
ArrayList<Node> arr = new ArrayList<>();
fillPrelist(head, arr);
int randomIndex = (int) (Math.random() * arr.size());
return arr.get(randomIndex);
}
// for test
public static void fillPrelist(Node head, ArrayList<Node> arr) {
if (head == null) {
return;
}
arr.add(head);
fillPrelist(head.left, arr);
fillPrelist(head.right, arr);
}
public static void main(String[] args) {
int maxLevel = 4;
int maxValue = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
Node head = generateRandomBST(maxLevel, maxValue);
Node o1 = pickRandomOne(head);
Node o2 = pickRandomOne(head);
if (lowestAncestor1(head, o1, o2) != lowestAncestor2(head, o1, o2)) {
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
边栏推荐
- Design of kindergarten real-time monitoring and control system
- [机缘参悟-38]:鬼谷子-第五飞箝篇 - 警示之一:有一种杀称为“捧杀”
- STL container
- Scientific research: are women better than men?
- Pytest (4) - test case execution sequence
- Leetcode takes out the least number of magic beans
- Application and Optimization Practice of redis in vivo push platform
- The most powerful new household god card of Bank of communications. Apply to earn 2100 yuan. Hurry up if you haven't applied!
- Character painting, I use characters to draw a Bing Dwen Dwen
- Variables in postman
猜你喜欢

The MySQL team development specifications used by various factories are too detailed. It is recommended to collect them!

Cut! 39 year old Ali P9, saved 150million

Yolov5 model training and detection

Introduce reflow & repaint, and how to optimize it?

Day_ 17 IO stream file class

Video display and hiding of imitation tudou.com

Unpool(nn.MaxUnpool2d)

Application and Optimization Practice of redis in vivo push platform

STM32 series - serial port UART software pin internal pull-up or external resistance pull-up - cause problem search

Icu4c 70 source code download and compilation (win10, vs2022)
随机推荐
Some query constructors in laravel (2)
How to find hot projects in 2022? Dena community project progress follow-up, there is always a dish for you (1)
Scientific research: are women better than men?
He was laid off.. 39 year old Ali P9, saved 150million
Write a thread pool by hand, and take you to learn the implementation principle of ThreadPoolExecutor thread pool
[uc/os-iii] chapter 1.2.3.4 understanding RTOS
Open source SPL optimized report application coping endlessly
tuple and point
Tucson will lose more than $400million in the next year
RichView TRVUnits 图像显示单位
100 basic multiple choice questions of C language (with answers) 04
8. Commodity management - commodity classification
Chinese natural language processing, medical, legal and other public data sets, sorting and sharing
2022/02/13
ELK日志分析系统
低度酒赛道进入洗牌期,新品牌如何破局三大难题?
Learn game model 3D characters, come out to find a job?
spoon插入更新oracle数据库,插了一部分提示报错Assertion botch: negative time
使用druid连接MySQL数据库报类型错误
Last week's hot review (2.7-2.13)