首页 > 其他分享 >《剑指Offer》-68-二叉树的最近公共祖先

《剑指Offer》-68-二叉树的最近公共祖先

时间:2023-09-04 13:44:47浏览次数:35  
标签:traverse return val Offer list 二叉树 68 TreeNode root

二叉搜索树

	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		// 如果p、q一定存在,那么root就一定不是空指针
		TreeNode* traverse = root;
		while (true) {
			if (p->val < traverse->val && q->val < traverse->val) traverse = traverse->left;
			else if (p->val > traverse->val && q->val > traverse->val) traverse = traverse->right;
			else if (p == traverse) return p;
			else if (q == traverse) return q;
			else return traverse;
		}
	}

二叉树

递归自底向上,返回每一个节点下面(包括)自己有没有目标节点之一

  • 有就返回子节点指针(最开始肯定是返回自己的指针)
  • 没有就返回空指针
  • 左右节点都各自包含一个就找到了
	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		if (!root) return nullptr;
		TreeNode* leftHas = lowestCommonAncestor(root->left, p, q);
		TreeNode* rightHas = lowestCommonAncestor(root->right, p, q);
		if ((leftHas && rightHas) || root == p || root == q) return root;
		if (leftHas) return leftHas;
		else return rightHas;
	}

任意树

由于 力扣 平台本身的限制,书中的最后一问没有体现出来——对于任意树

书中给出的思路是这样的:

  1. 遍历整棵树并构造出两条从根节点到目标节点的链表
  2. 查找链表的最后一个公共节点

对于 1 可以采用一种回溯的做法,另外就是这里不需要真的去构建一条链表,因为其实是从已经一一指向的路径中挑选一条就可以了,所以其实用数组也是可以的
对于 2 很简单,双指针

	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		vector<TreeNode*> list1, list2;
		findPath(list1, p,root);
		findPath(list2, q,root);
		TreeNode* res = nullptr;
		for (int i = 0; i < min(list1.size(), list2.size()); i++) {
			if (list1[i] == list2[i]) res = list1[i];
			else break;
		}
		return res;
	}

	bool findPath(vector<TreeNode*> &list, TreeNode* target,TreeNode* root) {
		if (!root) return false;
		list.push_back(root);
		if (list.back() == target) return true;
		if (findPath(list, target, root->left) || findPath(list, target, root->right)) {
			return true;
		}
		list.pop_back();
		return false;
	}

标签:traverse,return,val,Offer,list,二叉树,68,TreeNode,root
From: https://www.cnblogs.com/yaocy/p/17676586.html

相关文章

  • 剑指 Offer 58 - I. 翻转单词顺序
    剑指Offer58-I.翻转单词顺序解法一不用内置方法去除首尾空格和中间多余空格翻转所有字符翻转每个单词classSolution{publicStringreverseWords(Strings){//去除首尾空格和中间多余空格char[]ch=trim(s);//翻转所有字符re......
  • 剑指 Offer 59 - I. 滑动窗口的最大值
    剑指Offer59-I.滑动窗口的最大值单调队列在增删元素的过程中要求能返回当前最大元素,和155.最小栈类似。classSolution{publicint[]maxSlidingWindow(int[]nums,intk){intn=nums.length,p=0;int[]res=newint[n-k+1];......
  • 剑指 Offer 59 - II. 队列的最大值
    剑指Offer59-II.队列的最大值就是题目剑指Offer59-I.滑动窗口的最大值需要实现的数据结构。一个队列用于正常加入和删除数据,另一个队列用于维护最大值。classMaxQueue{Deque<Integer>q=newArrayDeque<>();Deque<Integer>q_max=newArrayDeque<>();......
  • 剑指 Offer 58 - II. 左旋转字符串
    剑指Offer58-II.左旋转字符串翻转前n个字符翻转其余字符翻转所有字符classSolution{publicStringreverseLeftWords(Strings,intn){char[]ch=s.toCharArray();reverse(ch,0,n-1);reverse(ch,n,ch.length-1);rever......
  • 剑指 Offer 64. 求1+2+…+n
    剑指Offer64.求1+2+…+n使用逻辑运算符的短路效应代替终止条件。classSolution{intres=0;publicintsumNums(intn){booleanx=n>1&&sumNums(n-1)>0;res+=n;returnres;}}......
  • 剑指 Offer 60. n个骰子的点数
    剑指Offer60.n个骰子的点数动态规划:已知n-1个骰子的所有情况,再增加一个骰子,可推出n个骰子的所有情况。增加的一个骰子的点数只有1-6种可能,与n-1个骰子对应点数相乘,可得到n个骰子点数的一种情况,遍历所有情况即可。classSolution{publicdouble[]dicesProbability(intn)......
  • 剑指 Offer 06. 从尾到头打印链表
    剑指Offer06.从尾到头打印链表方法一顺序添加,再翻转。classSolution{publicint[]reversePrint(ListNodehead){ListNodeh=head;List<Integer>res=newArrayList<>();while(h!=null){res.add(h.val);h=......
  • 剑指 Offer 03. 数组中重复的数字
    剑指Offer03.数组中重复的数字利用题目的限制条件:所有数字都在0~n-1的范围内通过交互让数字和下标一一对应,如果有多个数字对应同一个下标,那就找到了答案。classSolution{publicintfindRepeatNumber(int[]nums){intn=nums.length;inti=0;......
  • 剑指 Offer 62. 圆圈中最后剩下的数字(简单)
    题目:classSolution{public:intlastRemaining(intn,intm){intpos=0;for(inti=2;i<=n;i++){pos=(pos+m)%i;}returnpos;}};作者:想吃火锅的木易链接:https://leetcode.cn/problems/yuan-quan-zhong-z......
  • 剑指offer_20230803
    剑指Offer51.数组中的逆序对题目说明在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。解题思路1:暴力肯定是可行但是会超时的,就不用考虑了,但理论可行解题思路2:归并可以利用归并排序时的一个特性......