当前位置: 首页 > news >正文

687 最长同值路径——Leetcode 天天刷(2022.9.2)【DFS】

687 最长同值路径——Leetcode 天天刷(2022.9.2)【DFS】

文章目录

  • 687 最长同值路径——Leetcode 天天刷(2022.9.2)【DFS】
    • 前言
    • 题目描述
      • 示例
      • 提示信息
    • 本地调试运行
      • 输入格式
      • 输出格式
      • 输入样例
      • 输出样例
      • 层次遍历构造二叉树
    • 解法——DFS
      • 细节
      • 算法分析+解题效率
      • Code(C++)

前言

今天的题目emmm,怎么说呢,其实算法上比较简单,但是细节还是比较多的,也可以说是自己考虑的不够足够。

算法上采用的DFS,即深度优先搜索。

题目描述

题目传送门

简述一下:就是给你一个二叉树,需要返回 最长的 同值路径 的长度,就是路径上的每个节点都同值。

路径的长度用 边数 来表示。

示例

输入:root = [5,4,5,1,1,5]
输出:2
输入:root = [1,4,5,4,4,5]
输出:2

提示信息

  • 树的节点数的范围是 [0, 104]
  • -1000 <= Node.val <= 1000
  • 树的深度将不超过 1000

本地调试运行

说实话,树之类的构造,尤其是指针类型的树构建还是比较麻烦的,从样例来看就是输入用BFS顺序或者说是 层次遍历 的顺序来构建二叉树。

输入格式

我们还是可以假定多组输入,每组第一行输入整数n,然后第二行输入n个字符串,字符串直接用 空格 隔开,其中 null 表示空节点,数字 就是表示节点值。

输出格式

每行输出一个整数,表示最大同值路径长度。

输入样例

6
5 4 5 1 1 5

6
1 4 5 4 4 5


8
1 null 1 1 1 1 1 1

输出样例

2
2
4

层次遍历构造二叉树

其实就是创建二叉树的一种方式,大家如果看不懂最后的代码的构建二叉树的部分,可以看看下面的这篇的blog:

blog传送门

解法——DFS

首先,我们对于 节点路径长度,考虑的是以当前节点值作为数值的同值路径长度。因此,我们可以先递归计算以左右子节点的节点路径长度,然后根据左右子节点值和当前节点值的是否相同来计算当前节点的节点路径长度,同时需要返回当前的最大单侧节点路径长度

细节

  1. 首先是用边数来表示长度,所以对于长度的最小值为0,空节点返回-1。
  2. 如果子节点和当前节点值相同,我们可以将子节点的节点路径长度 + 1, 1表示当前当前节点和子节点的边。
  3. 返回路径长度的时候,如果是当前节点路径长度是两侧的,返回需要只返回单侧长度较大的。

算法分析+解题效率

时间复杂度 O ( n ) O(n) O(n),n为节点数量。

空间复杂度 O ( n ) O(n) O(n), DFS递归n层。

在这里插入图片描述

还行。

Code(C++)

#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<sstream>
using namespace std;

// 定义二叉树节点
struct TreeNode
{
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode() : val(0), left(nullptr), right(nullptr) {}
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
	TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};

// 构造一下二叉树
class BinaryTree
{
public:
	TreeNode* root;		// 根节点

	/// <summary>
	/// BFS——根据数组构建二叉树
	/// 数组中节点的顺序表示的就是BFS的顺序
	/// 所以使用BFS 完成搜索
	/// </summary>au
	/// <param name="nodes"></param>
	BinaryTree(vector<string> nodes)
	{
		// 下标索引
		int i = 0;
		// 数组尺寸
		int n = nodes.size();
		// 先判断根节点是否是空
		if (nodes[0] == "null" && n == 1)
		{
			root = nullptr;
			return;
		}
		// 非空则新建根节点
		stringstream ss;
		ss << nodes[0];
		int val;
		ss >> val;
		root = new TreeNode(val);
		i++;
		// 节点对列
		queue<TreeNode*> que;
		// 先将根结点入队
		que.push(root);
		// 当对列不空且未遍历完时
		while (!que.empty() && i < n)
		{
			// 获取节点并出队
			TreeNode* node = que.front();
			que.pop();
			// 然后给左右指针
			for (int j = 1; j <= 2 && i < n; ++j, ++i)
			{
				// 若空则置空
				if (nodes[i] == "null" && j == 1)
				{
					node->left == nullptr;
				}
				else if (nodes[i] == "null" && j == 2)
				{
					node->right = nullptr;
				}
				// 非空则生成节点并入队
				else if (j == 1)
				{
					node->left = new TreeNode(stoi(nodes[i]));
					que.push(node->left);
				}
				else
				{
					node->right = new TreeNode(stoi(nodes[i]));
					que.push(node->right);
				}
			}
		}
	}

	/// <summary>
	/// 展示树的结构
	/// 为了能够清晰展示,还是使用BFS
	/// </summary>
	void display()
	{
		// 若根节点为空
		if (root == nullptr)
		{
			return;
		}
		// 非空入队
		queue<TreeNode*> que;
		que.push(root);
		// 每一层节点的数量,包括空节点
		int t = 0, num = 1;
		while (!que.empty())
		{
			TreeNode* node = que.front();
			que.pop();
			cout << node->val << " ";
			num--;
			for (int i = 0; i < 2; ++i)
			{
				TreeNode* child;
				if (i == 0)
				{
					child = node->left;
				}
				else
				{
					child = node->right;
				}
				if (child != nullptr)
				{
					que.push(child);
					t++;
				}
			}
			// 当num = 0 时,说明当层遍历完,需要换行,进入下一层
			if (num == 0)
			{
				cout << endl;
				num = t;
				t = 0;
			}
		}
	}
};

class Solution
{
private:
	int len;
public:
	// DFS
	// 先计算出子树中以子节点的数值为路径的长度
	// 然后根据子节点数值和当前节点是否相同,若相同则加上对应长度
	// 最后每次递归和答案长度比较动态更新
	int longestUnivaluePath(TreeNode* root)
	{
		len = 0;
		dfs(root);
		return len;
	}

	int dfs(TreeNode* node)
	{
		// 空节点,返回-1
		if (!node)
		{
			return -1;
		}
		int l1, l2;					// 分别以左右子节点值为路径的长度
		int len0 = 0;				// 以当前节点值为路径的长度
		l1 = dfs(node->left);		// 计算左子树
		l2 = dfs(node->right);		// 计算右子树
		int len1 = 0, len2 = 0;		// 计算以当前节点的左右路径
		// 如果左节点同值,计算当前路径
		if (node->left && node->left->val == node->val)
		{
			len0 += l1 + 1;
			len1 = l1 + 1;
		}
		// 同理
		if (node->right && node->right->val == node->val)
		{
			len0 += l2 + 1;
			len2 = l2 + 1;
		}
		// 动态更新最大路径
		len = max(len, len0);
		return max(len1, len2);		// 返回单路径的最大值
	}
};


int main(int agrc, char** argv)
{
	int n;
	Solution * sol = new Solution();
	while (~scanf("%d", &n))
	{
		vector<string> nodes(n);
		for (int i = 0; i < n; ++i)
		{
			cin >> nodes[i];
		}
		BinaryTree* bt = new BinaryTree(nodes);
		printf("%d\n", sol->longestUnivaluePath(bt->root));
		delete bt;
	}
	
	delete sol;
	return 0;
}

相关文章:

  • 新店速递丨白玉兰(商务)酒店赣榆吾悦广场店 正式上线
  • Windows 10 安装 Redis
  • java基于springboot+vue+elementui的漫画投稿交流平台 前后端分离
  • Tomcat服务部署,虚拟主机配置,
  • 支持向量机
  • R Markdown 格式
  • Opncv 实现拍照、颜色识别和阈值选取
  • 计算机网络——网络协议
  • 对回调函数和消息机制的理解
  • 关于voreen编译的一些问题
  • 树莓派——9、IO操控代码编程
  • springboot+新冠疫苗预约管理系统 毕业设计-附源码241530
  • Dubbo注册中心
  • 【模型篇】01 记点脑子里还残存的关于模型分类的三种方式
  • Dubbo Data length too large与流式调用
  • Centos6.8 使用rpm安装mysql5.7
  • css的样式优先级
  • Druid 在有赞的实践
  • leetcode46 Permutation 排列组合
  • linux安装openssl、swoole等扩展的具体步骤
  • React组件设计模式(一)
  • Vue2.0 实现互斥
  • 大主子表关联的性能优化方法
  • 给初学者:JavaScript 中数组操作注意点
  • 基于游标的分页接口实现
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 小程序button引导用户授权
  • 一文看透浏览器架构
  • 由插件封装引出的一丢丢思考
  • Hibernate主键生成策略及选择
  • Java数据解析之JSON
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • #git 撤消对文件的更改
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (C语言)球球大作战
  • (poj1.3.2)1791(构造法模拟)
  • (三)模仿学习-Action数据的模仿
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .net mvc 获取url中controller和action
  • .net Stream篇(六)
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .Net面试题4
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • @AliasFor注解
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [ C++ ] 继承
  • [ 数据结构 - C++] AVL树原理及实现
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [20171106]配置客户端连接注意.txt