数据结构与算法--求1~n能组成的所有二叉搜索树的排列

给定一个整数n,生成并返回所有N个节点组成并且节点值从1到n互不相同的不同二叉树,可以按照任意顺序

  • 二叉树文章列表:

数据结构与算法–面试必问AVL树原理及实现

数据结构与算法–二叉树的深度问题

数据结构与算法–二叉堆(最大堆,最小堆)实现及原理

数据结构与算法–二叉查找树转顺序排列双向链表

数据结构与算法-- 二叉树中和为某一值的路径

数据结构与算法-- 二叉树后续遍历序列校验

数据结构与算法-- 广度优先打印二叉树

数据结构与算法–解决问题的方法- 二叉树的的镜像

数据结构与算法–重建二叉树

数据结构与算法–二叉查找树实现原理

数据结构与算法–二叉树实现原理

数据结构与算法–B树原理及实现

数据结构与算法–数字在排序数组中出现次数

数据结构与算法–死磕二叉树

数据结构与算法–二叉树第k个大的节点

数据结构与算法–求1~n能组成的所有二叉搜索树的排列

全排列问题

  • 排列组合的问题在之前的文中我们已经求解过:
    数据结构与算法–字符串的排列组合问题
    数据结构与算法–代码完整性案例分析

  • 在求数组全排列的过程中,我们将数组的每一位看成是独立的,接着每一位上分别排列1~9 的每一位树,一次对数组的n为进行递归,得到我们的全排列。

  • 现题中需要让1~n 组成n 个阶段的不同二叉树,也就是我们需要求解二叉树的全排列

方法一:转为数组全排列实现

  • 在构造二叉树时候,我们将比root 节点小的放左边,大的放右边,那么如果有 从1~n的数组依次对每一个节点构造二叉树的方式进行insert。那么我们能够得到一颗二叉树 T1

  • 如果我们修改数组的顺序,修改成 k…k-1, 1, k+1,…n-1, n,接着生成二叉树T2

  • 那么T1和 T2 大概率是不同的,特殊情况如下:

  • 情况一:3,1,2,4,5

请添加图片描述

  • 情况二:3,4,5,1,2

请添加图片描述

  • 如上两种情况,在中间节点是root节点时,大节点列表4,5 与小节点列表 1,2 分别在两侧,不管数组如何排列,生成的二叉树是相同的。

  • 经过如上分析,那么我们有如下的实现方案:

    • 生成一个1~n的数组,并且求数组的全排列
    • 每生成一个不同的数组排列,将该数组构建成一个二叉排序树,并且记录改二叉排序树的前序遍历生成的字符。并存储在数组 StrLIst中
    • 如果 StrList中存在 元素 k 与当前生成的二叉树的前序遍历字符一致,那么说明这种情况以及生成过
    • 如果StrList中不存在,那么我们将新构建的NewBinary添加到我们的二叉排序树数组 BinaryList中。
  • 如上分析有如下代码:

/*** 给定一个整数n,生成并返回所有N个节点组成并且节点值从1到n互不相同的不同二叉树,可以按照任意顺序* 解析:求解1~n能组成多少个不同的二叉搜索树* @author liaojiamin* @Date:Created in 10:15 2021/7/22*/
public class BuildGenerateTrees {public static void main(String[] args) {List<BinaryNode> binaryNodes = new ArrayList<>();List<String> middleSearch  = new ArrayList<>();binaryNodes = generateTrees(4);for (int i = 0; i < binaryNodes.size(); i++) {StringBuilder strBu = new StringBuilder();middleSearch.add(printTree(binaryNodes.get(i),strBu));}middleSearch.forEach(System.out::println);}/*** 方法一* 构造二叉树全排列:构造数组全排列,数组构造成二叉树,通过前序遍历值筛选二叉树* */public static List<BinaryNode> generateTrees(int n){List<BinaryNode> binaryNodes = new ArrayList<>();List<String> middleSearchStr = new ArrayList<>();int[] array = new int[n];for (int i = 1; i <= n; i++) {array[i-1] = i;}return buildGenerateTree(array, binaryNodes, 0, middleSearchStr);}/*** 生成数组的全排列,每种排列按顺序生成二叉树* */public static List<BinaryNode> buildGenerateTree(int[] array, List<BinaryNode> binaryNodes, int start, List<String> middleSearchStr){if(array == null || array.length <=1 || start == (array.length -1)){BinaryNode newNode = buildBinarySearchTree(array);StringBuilder str = new StringBuilder();String middleStr = printTree(newNode, str );if(!middleSearchStr.contains(middleStr)){middleSearchStr.add(middleStr);binaryNodes.add(newNode);}}for (int i = start; i < array.length; i++) {int temp = array[i];array[i] = array[start];array[start] = temp;buildGenerateTree(array, binaryNodes, start+1, middleSearchStr);temp = array[i];array[i] = array[start];array[start] = temp;}return binaryNodes;}/*** 前序遍历字符集合* */public static String printTree(BinaryNode t, StringBuilder strbu) {if (t == null || t.getElement() == null) {return strbu.toString();}for (int i = 0; i < t.getCount(); i++) {strbu.append(t.getElement() + ":" + t.getHeight()+" ");}printTree(t.getLeft(), strbu);printTree(t.getRight(), strbu);return strbu.toString();}/*** 根据数组构造二叉树* */public static BinaryNode buildBinarySearchTree(int[] array){if(array == null || array.length <= 0){return null;}BinaryNode node = new BinaryNode(null, null, null);for (int i = 0; i < array.length; i++) {node = insertNode(node, array[i]);}return node;}/*** 插入节点构造二叉搜索树* */public static BinaryNode insertNode(BinaryNode node, Integer k){if(k == null){return node;}if(node == null || node.getElement() == null){node = new BinaryNode(k, null, null);}int validateK = node.compareTo(k);if(validateK > 0){node.setLeft(insertNode(node.getLeft(), k));}else if (validateK < 0){node.setRight(insertNode(node.getRight(), k));}return node;}
}
  • 如上实现方案时间复杂度在O(n2), 空间复杂度存在两部分,一部分二叉搜索树数组,这部分取决于节点数量,数量不同排列的个数不同,另一部分在于存储二叉排序树的前序遍历字符串,因此空间复杂度也不会小。

方法二:分治法

  • 方案一的时间复杂度,空间复杂度都不是太理想,第一想法实现方案往往题目没有这么简单,在方法一中我们实现我们是受到之前文章中思路的影响,将之前的排列组合的思路套用在 二叉搜索树的排列上,但是因为两种数据结构本身复杂度就相差很大,导致二叉搜索树的排列问题异常复杂。
  • 我们换一种思路,这个也是看到别的思路,看到后就茅塞顿开,因为一旦思路被固定住,要想跳出来还是比较困难的,就和写小说的作者肯定不会去看别人写的小说是一个道理。
  • 我们直接将数组全排列思想用到二叉树搜索树中:
    • 在1~n中每个数字都有可能是根节点,确定根节点后 k,k 之前的数据 1 ~ k就是左子树,在k ~ n中每一个就是右子树
    • 那么我们遍历1 ~ n中每一位,让每个数都构造成不同根的 一棵二叉搜索树
    • 接着处理左子树 1 ~ k,同样,1~k中的左子树也是一棵二叉搜索树,依然套用以上逻辑,右子树同理。分别记录为leftList, rightLIst
    • 那么构造完左右子树后,我们只需要在左子树 leftList,rightList进行组合(双循环构造每种排列方式),就得到了整个二叉树的排列
      -如下图,列举其中一种情况:

请添加图片描述

请添加图片描述
请添加图片描述

请添加图片描述
请添加图片描述

  • 经如上分析有如下代码:
/*** 给定一个整数n,生成并返回所有N个节点组成并且节点值从1到n互不相同的不同二叉树,可以按照任意顺序* 解析:求解1~n能组成多少个不同的二叉搜索树* @author liaojiamin* @Date:Created in 10:15 2021/7/22*/
public class BuildGenerateTrees {public static void main(String[] args) {List<BinaryNode> binaryNodes = generateTreesBinary(1, 4);BinarySearchTree binarySearchTree = new BinarySearchTree();for (BinaryNode binaryNode : binaryNodes) {binarySearchTree.printTree(binaryNode);}}/*** 方法二* 分治法* */public static List<BinaryNode>generateTreesBinary(int start, int end){List<BinaryNode> binaryNodes = new LinkedList<>();if(start > end){binaryNodes.add(null);return binaryNodes;}for (int i=start;i<=end;i++){List<BinaryNode> leftNode = generateTreesBinary(start, i-1);List<BinaryNode> rightNode = generateTreesBinary(i+1, end);for (BinaryNode left : leftNode) {for (BinaryNode right : rightNode) {binaryNodes.add(new BinaryNode(i, left, right));}}}return binaryNodes;}
}
  • 以上思路理解起来更清晰,代码实现方式也更简单,时间复杂度还是取决于n的大小,假设n个阶段能构建Cn棵二叉搜索树,那么时间复杂度一棵树生成需要O(n),Cn棵树O(n*Cn)
  • 空间复杂度,每一棵树都有n个阶段,有Cn棵树,总空间复杂度O(n*Cn)

上一篇:数据结构与算法–二叉树第k个大的节点
下一篇:数据结构与算法一篇帮助你吃下KMP算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java语法基础50题训练(下)

题目1: HashMap集合存储学生对象并遍历。 需求: 创建一个HashMap集合&#xff0c;键是学生对象(Student)&#xff0c;值是居住地(String)。存储多个键值对象&#xff0c;并遍历。 要求: 保证键的唯一性&#xff1a;如果学生对象的成员变量值相同&#xff0c;我们就认为是同一…

用long类型让我出了次生产事故,写代码还是要小心点

昨天发现线上试跑期的一个程序挂了&#xff0c;平时都跑的好好的&#xff0c;查了下日志是因为昨天运营跑了一家美妆top级淘品牌店&#xff0c;会员量近千万&#xff0c;一下子就把128G的内存给爆了&#xff0c;当时并行跑了二个任务&#xff0c;没辙先速写一段代码限流&#x…

Mongodb查询分析器解析

Mongodb查询分析器 动态相关项目中涉及到数据量大和吞吐量的接口&#xff0c;例如关注页面动态&#xff0c;附近动态&#xff0c;这部分数据都是存储在mongodb中&#xff0c;在线上数据中分类两个mongodb集合存储其中关注动态基于扩散写的设计&#xff0c;数据量已经快到 8 亿…

[Java基础]Collections概述和使用

代码如下: package CollectionDemo01;import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List;public class CollectionDemo01 {public static void main(String[] args){List<Integer> list new ArrayList&l…

链路追踪在ERP系统中的应用实践

源宝导读&#xff1a;随着ERP的部署架构越来越复杂&#xff0c;对运维监控、问题排查等工作增加了难度&#xff0c;本文将介绍通过引入链路追踪技术&#xff0c;提高ERP系统问题排查效率&#xff0c;支撑更全面监控系统运行情况的实践过程。一、导读随着ERP的部署架构越来越复杂…

[Java基础]File基础

File类概述和构造方法: 代码如下: package FileStudyPack;import java.io.File;public class FileDemo01 {public static void main(String[] args){File f1 new File("D:\\JavaDemo\\java.txt");System.out.println(f1);File f2 new File("D:\\JavaDemo&quo…

java 日志乱码_【开发者成长】JAVA 线上故障排查完整套路!

云栖号资讯&#xff1a;【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01;线上故障主要会包括 CPU、磁盘、内存以及网络问题&#xff0c;而大多数故障可能会包含不止一个层面的问题&#xff0c;所以进行…

谈谈登录密码传输这件小事

背景 大大小小的系统其实都离不开登录这个小小的功能&#xff0c;前段时间老黄在审查公司部分系统代码时&#xff0c;发现不少系统的登录还是很粗暴的&#xff0c;粗暴到让人不敢说话的那种。说到登录&#xff0c;结合标题&#xff0c;其实大部分人应该都猜到那个粗暴到让人不敢…

技术分享杂七杂八技术

技术分享 听花谷 距离名宿 6~7 公里左右&#xff0c;丽江网红基地&#xff0c;有举办婚礼的地方听花谷&#xff0c;坐落于玉龙雪山脚下&#xff0c;前有玉龙雪山&#xff0c;后有原始森林。园内共有三处白色空间&#xff0c;第一处共有三层&#xff0c;婚礼举行&#xff0c;发…

java 操作日志设计_日志系统新贵 Loki,确实比笨重的ELK轻

本文同步Java知音社区&#xff0c;专注于Java作者&#xff1a;linkt1234http://blog.csdn.net/Linkthaha/article/details/100575278最近&#xff0c;在对公司容器云的日志方案进行设计的时候&#xff0c;发现主流的ELK或者EFK比较重&#xff0c;再加上现阶段对于ES复杂的搜索功…

Istio1.5 Envoy 数据面 WASM 实践

Istio 1.5 回归单体架构&#xff0c;并抛却原有的 out-of-process 的数据面扩展方式&#xff0c;转而拥抱基于 WASM 的 in-proxy 扩展&#xff0c;以期获得更好的性能。本文基于网易杭州研究院轻舟云原生团队的调研与探索&#xff0c;介绍 WASM 的社区发展与实践。超简单版解释…

elasticSearch -- (文档,类型,索引)

问题:大规模数据如何检索 当系统数据量达到10亿&#xff0c;100亿级别的时候&#xff0c;我们系统该如何去解决这种问题。 数据库选择—mysql&#xff0c; sybase&#xff0c;oracle&#xff0c;mongodb&#xff0c;hbase…单点故障如何解决—lvs&#xff0c; F5&#xff0c;…

asp后台调用产品数据_后台产品经理,需掌握这些数据交互知识

人们每天都在接收信息和发送信息&#xff0c;在传递信息的过程中&#xff0c;明白对方要表达的意思。数据也是如此&#xff0c;在系统交换数据的过程中&#xff0c;就伴随着数据交互。本篇文章将为大家具体分析前端和后台的数据交互与协议。本文所说的”数据交换” 是指在计算机…

使用c# .net core开发国标gb28181 sip +流媒体服务完成视频监控实例教程 亲身完美体验过程...

目前使用C# .net core 来实现国标gb28181标准的摄像头播放、ptz云台控制、视频回放等视频监控功能&#xff0c;项目可运行于linux/docker/.net core环境&#xff0c;也是当前非常罕有的能做到毫秒级国标gb28181公网视频传送案例&#xff0c;也是少有的能同时具有播放、ptz云台控…

[Java基础]字节流读数据

代码如下: package InstreamPack;import java.io.FileInputStream; import java.io.IOException;public class FileInputStreamDemo01 {public static void main(String[] args) throws IOException {FileInputStream fis new FileInputStream("D:\\JavaDemo\\java.txt&…

丁可以组什么词_有哪些量词可以用来描述生意经?

分别有&#xff1a;本&#xff0c; 一(本)生意经。笔&#xff0c; 一(笔)生意经。次&#xff0c;一(次)生意量词用名量词&#xff1a;表示事物的计量单位。基本定义&#xff1a;通常用来表示人、事物或动作的数量单位的词&#xff0c;叫做量词。量词 lingc&#xff0c;与代表可…

硬核技能k8s初体验

&#xff0c;Kubernetes 是一个软件系统&#xff0c;使你在数以万计的电脑节点上运行软件时就像所有节点是以单个大节点一样&#xff0c; 它将底层基础设施抽象&#xff0c;这样做同时简化了应用开发、部署&#xff0c;以及对开发和运维团队的管理。Kubernetes集群架构Kubernet…

线上问题排查流程

问题排查 针对各种常见的线上问题&#xff0c;梳理下排查思路。 业务问题 线上问题大多数时候都是业务问题引发的问题&#xff0c;当线上环境绝大多数请求都是正常&#xff0c;当有部分或者某一个用户有问题&#xff0c;此时怎么针对性的排查在当前微服务体系下&#xff0c;…