牛客题解 | 二叉树的下一个结点
1.牛客题解 | N皇后问题2.牛客题解 | 三数之和3.牛客题解 | 三角形最小路径和4.牛客题解 | 不同路径的数目(一)5.牛客题解 | 不用加减乘除做加法6.牛客题解 | 丑数7.牛客题解 | 两个链表的第一个公共结点8.牛客题解 | 两个链表的第一个公共结点_19.牛客题解 | 两数之和10.牛客题解 | 主持人调度(二)11.牛客题解 | 买卖股票的最好时机(一)12.牛客题解 | 买卖股票的最好时机(三)13.牛客题解 | 买卖股票的最好时机(二)14.牛客题解 | 二分查找-I15.牛客题解 | 二叉搜索树与双向链表16.牛客题解 | 二叉搜索树的后序遍历序列17.牛客题解 | 二叉搜索树的最近公共祖先18.牛客题解 | 二叉搜索树的第k个节点19.牛客题解 | 二叉树中和为某一值的路径(一)20.牛客题解 | 二叉树中和为某一值的路径(三)21.牛客题解 | 二叉树中和为某一值的路径(二)
22.牛客题解 | 二叉树的下一个结点
23.牛客题解 | 二叉树的中序遍历24.牛客题解 | 二叉树的前序遍历25.牛客题解 | 二叉树的后序遍历26.牛客题解 | 二叉树的最大深度27.牛客题解 | 二叉树的深度28.牛客题解 | 二叉树的镜像29.牛客题解 | 二维数组中的查找30.牛客题解 | 二维数组中的查找_131.牛客题解 | 二进制中1的个数32.牛客题解 | 从上往下打印二叉树33.牛客题解 | 从中序与后序遍历序列构造二叉树34.牛客题解 | 从尾到头打印链表35.牛客题解 | 兑换零钱(一)36.牛客题解 | 分糖果问题37.牛客题解 | 删除有序链表中重复的元素-I38.牛客题解 | 删除有序链表中重复的元素-II39.牛客题解 | 删除链表中重复的结点40.牛客题解 | 删除链表中重复的结点41.牛客题解 | 删除链表的倒数第n个节点42.牛客题解 | 删除链表的节点43.牛客题解 | 判断一个链表是否为回文结构44.牛客题解 | 判断是不是二叉搜索树45.牛客题解 | 判断是不是完全二叉树46.牛客题解 | 判断是不是平衡二叉树47.牛客题解 | 判断是不是平衡二叉树_148.牛客题解 | 判断是否为回文字符串49.牛客题解 | 判断链表中是否有环50.牛客题解 | 剪绳子51.牛客题解 | 剪绳子(进阶版)52.牛客题解 | 包含min函数的栈53.牛客题解 | 包含min函数的栈_154.牛客题解 | 单链表的排序55.牛客题解 | 反转字符串56.牛客题解 | 反转链表57.牛客题解 | 反转链表_158.牛客题解 | 反转链表_259.牛客题解 | 合并k个已排序的链表60.牛客题解 | 合并两个排序的链表61.牛客题解 | 合并两个排序的链表_162.牛客题解 | 合并两个有序的数组63.牛客题解 | 合并二叉树64.牛客题解 | 合并区间65.牛客题解 | 和为S的两个数字66.牛客题解 | 和为S的连续正数序列67.牛客题解 | 在二叉树中找到两个节点的最近公共祖先68.牛客题解 | 复杂链表的复制69.牛客题解 | 多数组中位数70.牛客题解 | 多数组第 K 小数71.牛客题解 | 大数加法72.牛客题解 | 字符串变形73.牛客题解 | 字符串的排列74.牛客题解 | 字符串的排列_175.牛客题解 | 字符流中第一个不重复的字符76.牛客题解 | 孩子们的游戏(圆圈中最后剩下的数)77.牛客题解 | 实现二叉树先序,中序和后序遍历78.牛客题解 | 对称的二叉树79.牛客题解 | 对称的二叉树_180.牛客题解 | 寻找峰值81.牛客题解 | 寻找第K大82.牛客题解 | 小米Git83.牛客题解 | 岛屿数量84.牛客题解 | 接雨水问题85.牛客题解 | 数值的整数次方86.牛客题解 | 数字在升序数组中出现的次数87.牛客题解 | 数字字符串转化成IP地址88.牛客题解 | 数字序列中某一位的数字89.牛客题解 | 数据流中的中位数90.牛客题解 | 数据流中的中位数_191.牛客题解 | 数组中出现次数超过一半的数字92.牛客题解 | 数组中出现次数超过一半的数字_193.牛客题解 | 数组中只出现一次的两个数字94.牛客题解 | 数组中的逆序对95.牛客题解 | 数组中的逆序对_196.牛客题解 | 数组中重复的数字97.牛客题解 | 整数中1出现的次数(从1到n整数中1出现的次数)98.牛客题解 | 斐波那契数列99.牛客题解 | 斐波那契数列_1100.牛客题解 | 旋转数组题目
题目的主要信息:
- 题目给出我们一棵树的其中的某一个结点指针
- 我们需要返回这棵树按照中序遍历的该节点的下一个顺序结点指针
- 树的每个节点都有三个指针,指向左子节点、右子节点、父节点
举一反三:
学习完本题的思路你可以解决如下题目:
方法一:中序遍历递归(推荐使用)
知识点:二叉树递归
递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此递归过程,最重要的就是查看能不能讲原本的问题分解为更小的子问题,这是使用递归的关键。
而二叉树的递归,则是将某个节点的左子树、右子树看成一颗完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数不断进入子树。
思路:
我们首先要根据给定输入中的结点指针向父级进行迭代,直到找到该树的根节点;然后根据根节点进行中序遍历,当遍历到和给定树节点相同的节点时,下一个节点就是我们的目标返回节点
具体做法:
- step 1:首先先根据当前给出的结点找到根节点
- step 2:然后根节点调用中序遍历
- step 3:将中序遍历结果存储下来
- step 4:最终拿当前结点匹配是否有符合要求的下一个结点
Java实现代码:
import java.util.*;
public class Solution {
ArrayList<TreeLinkNode> nodes = new ArrayList<>();
public TreeLinkNode GetNext(TreeLinkNode pNode) {
// 获取根节点
TreeLinkNode root = pNode;
while(root.next != null) root = root.next;
// 中序遍历打造nodes
InOrder(root);
// 进行匹配
int n = nodes.size();
for(int i = 0; i < n - 1; i++) {
TreeLinkNode cur = nodes.get(i);
if(pNode == cur) {
return nodes.get(i+1);
}
}
return null;
}
// 中序遍历
void InOrder(TreeLinkNode root) {
if(root != null) {
InOrder(root.left);
nodes.add(root);
InOrder(root.right);
}
}
}
C++实现代码:
class Solution {
public:
vector<TreeLinkNode*> nodes;
TreeLinkNode* GetNext(TreeLinkNode* pNode) {
TreeLinkNode* root = pNode;
// 获取根节点
while(root->next) root = root->next;
// 中序遍历用nodes储存所有节点指针
InOrder(root);
int n = nodes.size();
for(int i = 0; i < n - 1; i++) {
TreeLinkNode* cur = nodes[i];
// 将结点进行匹配
if(pNode == cur) {
// 如果有匹配到给出的结点,则下一个结点即返回结果
return nodes[i+1];
}
}
// 否则如果没有下一个结点则返回NULL
return NULL;
}
// 中序遍历
void InOrder(TreeLinkNode* root) {
if(root == NULL) return;
InOrder(root->left);
nodes.push_back(root);
InOrder(root->right);
}
};
python实现代码:
class Solution:
nodes = []
def GetNext(self, pNode):
# 查找根节点
root = pNode
while root.next:
root = root.next
# 中序遍历打造nodes
self.InOrder(root)
# 匹配节点
for i in range(len(self.nodes) - 1):
cur = self.nodes[i]
if pNode == cur:
return self.nodes[i+1]
return None
# 中序遍历
def InOrder(self, root):
if root == None:
return
self.InOrder(root.left)
self.nodes.append(root)
self.InOrder(root.right)
复杂度分析:
- 时间复杂度:,因为遍历了树中的所有节点
- 空间复杂度:,因为引入了存储所有节点的空间
方法二:分类直接寻找
思路:
直接寻找分为三种情况
- 如果给出的结点有右子节点,则最终要返回的下一个结点即右子树的最左下的结点
- 如果给出的结点无右子节点,且当前结点是其父节点的左子节点,则返回其父节点
- 如果给出的结点无右子节点,且当前结点是其父节点的右子节点,则先要沿着左上方父节点爬树,一直爬到当前结点是其父节点的左子节点为止,返回的就是这个父节点;或者没有满足上述情况的则返回为NULL
具体做法:
- step 1:判断该节点是否符合思路中第一点,则一直找到右子树的左下节点为返回值
- step 2:判断该节点是否符合思路中第二点,则返回当前节点的父亲节点
- step 3:判断该节点是否符合思路中第三点,则迭代向上找父节点,直到迭代的当前节点是父节点的左孩子节点为止,返回该父节点;如果不满足上述情况返回NULL
图示:
Java实现代码:
import java.util.*;
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
// 情况一
if(pNode.right != null) {
TreeLinkNode rchild = pNode.right;
// 一直找到右子树的最左下的结点为返回值
while(rchild.left != null) rchild = rchild.left;
return rchild;
}
// 情况二
if(pNode.next != null && pNode.next.left == pNode) {
return pNode.next;
}
// 情况三
if(pNode.next != null) {
TreeLinkNode ppar = pNode.next;
// 沿着左上一直爬树,爬到当前结点是其父节点的左自己结点为止
while(ppar.next != null && ppar.next.right == ppar) ppar = ppar.next;
return ppar.next;
}
return null;
}
}
C++实现代码:
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode) {
// 如果有右子树
if(pNode->right) {
TreeLinkNode* rchild = pNode->right;
// 一直找到右子树的最左下的结点为返回值
while(rchild->left) rchild = rchild->left;
return rchild;
}
// 如果无右子树且当前结点是其父节点的左子结点
if(pNode->next && pNode->next->left == pNode) {
// 返回当前结点的父节点
return pNode->next;
}
// 如果无右子树且当前结点是其父节点的右子节点
if(pNode->next) {
TreeLinkNode* ppar = pNode->next;
// 沿着左上一直爬树,爬到当前结点是其父节点的左自己结点为止
while(ppar->next && ppar->next->right == ppar) ppar = ppar->next;
// 返回当前结点的父节点
return ppar->next;
}
return NULL;
}
};
python实现代码:
class Solution:
def GetNext(self, pNode):
# 情况一
if pNode.right:
rchild = pNode.right
# 一直找到右子树的最左下的结点为返回值
while(rchild.left):
rchild = rchild.left
return rchild
# 情况二
# 如果无右子树且当前结点是其父节点的左子结点
if pNode.next and pNode.next.left == pNode:
return pNode.next
# 情况三
if pNode.next:
ppar = pNode.next
# 沿着左上一直爬树,爬到当前结点是其父节点的左自己结点为止
while(ppar.next and ppar.next.right == ppar):
ppar = ppar.next
return ppar.next
return None
复杂度分析:
- 时间复杂度:,最大代价是当树退化成一个只包含右子节点的链表,当给定节点是中序遍历最后一个节点时,会进入情况三的分析部分,在向左上方向一直迭代直到根节点,才会发现应该返回NULL,即无下一个节点,此时代价最大。
- 空间复杂度:,无额外空间的借用
合集:
牛客面试高频题单题解
分类:
牛客面试高频题单题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程