目录
(2)python(29/31,时间超限了但算法正确性是可以保证的)
(1)C++(不提交,因为不想补全力扣给的入口函数,但是能保证算法正确性)
又是一个复习的算法题目,下面直接看题吧。
236. 二叉树的最近公共祖先 - 力扣(Leetcode)
有两种方法可解。
假设给定两个节点p,q,那么我们应该找出两条路径并存起来,路径是从根节点到给定节点,怎么找呢?利用栈进行递归查找即可。
为什么倍增法可行,因为一个整型数永远可以化成一个二进制数(二进制转十进制)。


顺便也复习了一下怎么建树。
- #include
- #include
- #include
- #include
- using namespace std;
-
- ///**
- // * Definition for a binary tree node.
- // */
- struct TreeNode {
- int val;
- TreeNode *left;
- TreeNode *right;
- TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- };
-
- class Solution {
- int* nums;
- public:
- Solution(){
- nums=new int[11];
- int n[]={3,5,1,6,2,0,8,-1,-1,7,4};
- for(int i=0;i<11;++i)
- nums[i]=n[i];
-
- // for(int i=0;i<11;++i)
- // cout<
- // cout<
- }
-
- void display(TreeNode* node){
- if(node){
- display(node->left);
- cout<
val< - display(node->right);
- }
- }
-
- TreeNode* createTree(int idx){
- if(idx>10)
- return NULL;
- //cout<
- int num=nums[idx];
- TreeNode* t;
- if(num==-1){
- t = NULL;
- }else{
- t=new TreeNode(num);
- t->left=createTree(2*idx+1);
- t->right=createTree(2*idx+2);
- }
- return t;
- }
-
- void dfs_search(TreeNode* node,TreeNode* target,vector
&stack,vector &path) { - if(node==NULL)
- return;
- stack.push_back(node);
- // cout<
val< - if(node->val==target->val){
- // path=stack;
- path.assign(stack.begin(),stack.end());
- return;
- }
- // cout<<"2"<
- dfs_search(node->left,target,stack,path);
- dfs_search(node->right,target,stack,path);
- stack.pop_back();
- }
-
- //朴素法 用时击败16.68%,内存击败7.59%
- TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
- vector
p_path; - vector
q_path; - vector
stack; -
- dfs_search(root,p,stack,p_path);
- stack.clear();
- dfs_search(root,q,stack,q_path);
- //
- // for(int i=0;i
- // cout<
val<<" "; - // cout<
- // for(int i=0;i
- // cout<
val<<" "; - // cout<
-
- TreeNode* common;
- int i=0;
- while(i
size() && isize()){ - if(p_path[i]==q_path[i]){
- common=p_path[i];
- }
- i++;
- }
- return common;
- }
- };
-
- int main(){
- Solution Tree;
- TreeNode* root=Tree.createTree(0);
- // Tree.display(root);
- int p,q;
- cin>>p>>q;
- TreeNode* pp=new TreeNode(p);
- TreeNode* qq=new TreeNode(q);
-
- TreeNode* ans=Tree.lowestCommonAncestor(root,pp,qq);
- cout<
val< -
- return 0;
- }
(2)python(29/31,时间超限了但算法正确性是可以保证的)
- import copy
-
- class TreeNode(): # python 没有结构体,但可以用类实现相同效果
- def __init__(self,val:int,left=None,right=None):
- self.val=val
- self.left=left
- self.right=right
-
- def Create_Tree(node,vals,idx):
- if idx>10:
- return node
- if vals[idx]=='#':
- node=None
- else:
- node=TreeNode(int(vals[idx]))
- node.left=Create_Tree(node.left,vals,2*idx+1)
- node.right=Create_Tree(node.right,vals,2*idx+2)
- return node
-
- def display(root):
- if root:
- display(root.left)
- print(root.val)
- display(root.right)
-
- class Solution:
- def __init__(self):
- self.p_path=[]
- self.q_path=[]
- self.stack=[]
-
- def dfs_search(self,node:'TreeNode',target:'TreeNode',flg):
- if node==None:
- return
- self.stack.append(node)
- if node.val == target.val:
- if flg==0:
- self.p_path=copy.deepcopy(self.stack)
- else:
- self.q_path=copy.deepcopy(self.stack)
- return
- self.dfs_search(node.left,target,flg)
- self.dfs_search(node.right,target,flg)
- self.stack.pop()
-
- def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
- self.dfs_search(root,p,0)
- self.stack.clear()
- self.dfs_search(root,q,1)
-
- common=TreeNode(None);
- i=0
- while i<len(self.p_path) and i<len(self.q_path):
- if self.p_path[i].val==self.q_path[i].val:
- common=copy.deepcopy(self.p_path[i])
- i+=1
- return common
-
-
- if __name__=='__main__':
- node=None
- vals=list("3516208##74")
- root=Create_Tree(node,vals,0)
- ## display(root)
- n1,n2=map(int,input().split())
- p=TreeNode(n1)
- q=TreeNode(n2)
-
- sol=Solution()
- ans=sol.lowestCommonAncestor(root,p,q)
- print(ans.val)
-
-
-
4、LCA倍增法
(1)C++(不提交,因为不想补全力扣给的入口函数,但是能保证算法正确性)
- #include
- #include
- #include
- using namespace std;
-
- const int N=10010;
- int n,m,cnt=1;
- struct Edge{
- int to,w,next;
- }edge[N];
- int head[N],dep[N],fa[N][N];
-
- void Add(int u,int v){
- edge[cnt].to=v;
- edge[cnt].next=head[u];
- // edge[cnt].w=w;
- head[u]=cnt;
- // cout<<"对于"<
- cnt++;
- }
-
- //int k=0;
- void dfs(int v,int father){ //填深度表和跳步表
- dep[v]=dep[father]+1;
- fa[v][0]=father;
- for(int i=1;i<=19;++i)
- fa[v][i]=fa[fa[v][i-1]][i-1];
-
- for(int i=head[v];i;i=edge[i].next){
- int p=edge[i].to;
- // cout<
- // k++;
- if(p!=father)
- dfs(p,v);
- }
- }
-
- int lca(int x,int y){
- // cout<
- if(dep[x]
- swap(x,y);
- for(int i=19;i>=0;i--) //先跳到同一层
- if(dep[fa[x][i]]>=dep[y]){
- x=fa[x][i];
- // cout<<"* "<
- }
-
- // cout<<"11"<
- if(x==y)
- return y;
- // cout<<"22"<
- for(int i=19;i>=0;i--){ //再跳到lca的下一层
- if(fa[x][i]!=fa[y][i]){
- x=fa[x][i],y=fa[y][i];
- }
- }
- return fa[x][0];
- }
-
-
- struct TreeNode {
- int val;
- TreeNode *left;
- TreeNode *right;
- TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- };
-
- class Tree{
- public:
- int nums[11] = {3,5,1,6,2,9,8,-1,-1,7,4}; //因为样例中有一个节点的值为0,导致dep[0]被更改了,所以调试了很久,这个样例我把0换成了9
- // int nums[2]={1,2};
- TreeNode* createTree(int idx){
- if(idx>10)
- return NULL;
- TreeNode* t;
- if(nums[idx]==-1){
- t=NULL;
- return t;
- }else{
- t=new TreeNode(nums[idx]);
- t->left= createTree(2*idx+1);
- t->right=createTree(2*idx+2);
- }
- return t;
- }
- void display(TreeNode* node){
- if(node){
- display(node->left);
- cout<
val< - display(node->right);
- }
- }
- void add_edge(TreeNode* node){ //链式前向星加边,当然也可以根据数组下标加边,这里建树再加边的操作略显复杂
- if(node->left!=NULL){
- Add(node->val,node->left->val);
- Add(node->left->val,node->val);
- add_edge(node->left);
- }
- if(node->right!=NULL){
- Add(node->val,node->right->val);
- Add(node->right->val,node->val);
- add_edge(node->right);
- }
- }
- };
-
-
- int main(){
- Tree* t=new Tree();
- TreeNode* root=t->createTree(0);
- // t->display(root);
- t->add_edge(root);
- // cout<
val< - // cout<<"dep[0]: "<
- dfs(root->val,0);
- int x,y;
- cin>>x>>y;
- int ans=lca(x,y);
- cout<
-
- return 0;
- }
5、其他递归法
- class Solution {
- public:
- TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
- if(root == NULL)
- return NULL;
- if(root == p || root == q)
- return root;
-
- TreeNode* left = lowestCommonAncestor(root->left, p, q);
- TreeNode* right = lowestCommonAncestor(root->right, p, q);
-
- if(left == NULL)
- return right;
- if(right == NULL)
- return left;
- if(left && right) // p和q在两侧
- return root;
-
- return NULL; // 必须有返回值
- }
- };
三、题二:【模板】最近公共祖先(LCA)
1、上链接
P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
2、基本思路
为倍增法量身定做的一道题,下面用链式前向星+倍增法搞定。
3、倍增法代码
(1)C++ (AC)
- #include
- #include
- #include
- using namespace std;
-
- int n,m,s; //树的结点个数、询问次数、树根节点的序号
- int x,y; //x和y之间有一条直接连接的边
- int a,b; //表示询问a和b的最近公共祖先
-
- const int N=5000100;
- int cnt=1,head[N];
- struct Edge{
- int to,next;
- } e[N];
-
- int dep[N],fa[N][22];
-
- void Add(int x,int y){
- e[cnt].to=y;
- e[cnt].next=head[x];
- head[x]=cnt++;
- }
-
- void dfs(int u,int father){ //填深度表和跳步表
- dep[u]=dep[father]+1;
- fa[u][0]=father;
- for(int i=1;i<=19;++i)
- fa[u][i]=fa[fa[u][i-1]][i-1];
-
- for(int i=head[u];i;i=e[i].next){
- int p=e[i].to;
- if(p!=father)
- dfs(p,u);
- }
- }
-
- int lca(int x,int y){
- if(dep[x]
- swap(x,y);
- for(int i=19;i>=0;i--) //跳到同一层
- if(dep[fa[x][i]]>=dep[y])
- x=fa[x][i];
-
- if(x==y)
- return y;
-
- for(int i=19;i>=0;i--)
- if(fa[x][i]!=fa[y][i])
- x=fa[x][i],y=fa[y][i];
-
- return fa[x][0];
-
- }
-
- int main(){
- cin>>n>>m>>s;
- for(int i=0;i
-1;++i){ - cin>>x>>y;
- Add(x,y);
- Add(y,x);
- }
- dfs(s,0);
- // cout<
- for(int i=0;i
- cin>>a>>b;
- cout<<lca(a,b)<
- }
- return 0;
- }
(2)python(70分)
- N=500010
- # 没办法,N=5000010会全部时间超限
- cnt=1
- head=[0]*N
- next=[0]*N
- to=[0]*N
-
- dep=[0]*N
- fa=[[0]*20 for _ in range(N)]
-
- def Add(a,b):
- global cnt
- to[cnt]=b
- next[cnt]=head[a]
- head[a]=cnt
- cnt+=1
-
- def dfs(u:int,father:int): # 填深度表和跳步表
- dep[u]=dep[father]+1
- fa[u][0]=father
- for i in range(1,20):
- fa[u][i]=fa[fa[u][i-1]][i-1]
-
- i=head[u]
- while i:
- p=to[i]
- if p!=father:
- dfs(p,u)
- i=next[i]
-
- def lca(x,y)->int:
- if dep[x]
- x,y=y,x
- for i in range(19,-1,-1): # 先跳到同一层
- if dep[fa[x][i]]>=dep[y]:
- x=fa[x][i]
- if x==y:
- return y
- for i in range(19,-1,-1):
- if fa[x][i]!=fa[y][i]:
- x,y=fa[x][i],fa[y][i]
- return fa[x][0]
-
- n,m,s=map(int,input().split())
- for i in range(n-1):
- x,y=map(int,input().split())
- Add(x,y)
- Add(y,x)
- dfs(s,0)
- for i in range(m):
- a,b=map(int,input().split())
- print(lca(a,b))
以上,最近公共祖先
祝好
-
相关阅读:
SveletJs学习——事件
(STM32)从零开始的RT-Thread之旅--SPI驱动ST7735(2)
Vue脚手架④
第七章 树与森林
spring aop 初探
8月25日计算机视觉理论学习笔记——FCN、DeepLab
Java实现Excel数据导入数据库
C++核心编程:P19->STL----常用算法(下)
利用Proxifier配置多级代理
springboot教室实验室预约系统在线视频点播系统毕业设计毕设作品开题报告开题答辩PPT
-
原文地址:https://blog.csdn.net/m0_52711790/article/details/127928596