Leetcode 108. 将有序数组转换为二叉搜索树
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
1、题目📑
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
实例1:
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:
实例2:
输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。
限制:
0 <= 节点个数 <= 1000
2、思路🧠
方法一:递归栈
二叉搜索树的中序遍历是升序序列,观察题目中的数组是按照升序排序的有序数组,因此可以确保数组是二叉搜索树的中序遍历序列。
如果给定二叉搜索树的中序遍历,能否唯一地确定一颗二叉搜索树?答案是否定的。因为如果没有限制二叉搜索树的高度平衡,所以任何一个数字都可以作为二叉搜索树的根节点,可以绘制的二叉搜索树有多个。
5 0 5 -3
/ \ / \ / \ / \
0 9 -3 5 -3 9 -10 5
/ / \ / \ / \
-3 -10 9 -10 0 0 9
/
-10
那如果给了限定条件平衡,可以确定唯一的的二叉搜索树
0 0 0 0
/ \ / \ / \ / \
-10 5 -3 9 -3 5 -10 9
\ \ / / / \ \ /
-3 9 -10 5 -10 9 -3 5
采用中序遍历,选择中间的位置作为根节点,进行根节点左边数字进行遍历,根节点右边的数字进行遍历。
- 当
l > r时,平衡二叉搜索树为空。 - 递归根节点左树,右树。
- 返回根节点。
废话少说~~~~~上代码!
3、代码👨💻
第一次commit AC
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return middle(nums, 0, nums.length - 1);
}
public TreeNode middle(int [] nums, int l, int r) {
if (l > r) return null;
int m = l + (r - l) / 2;
TreeNode node = new TreeNode(nums[m]);
node.left = middle(nums, l, m - 1);
node.right = middle(nums, m + 1, r);
return node;
}
}
时间复杂度:O(N ) 其中 N 是数组的长度。每个数字只访问一次。
空间复杂度:O(log N) 递归栈的深度是 O(log N)。
4、总结
该题目的是对二叉树的对称结构进行判断,在树的过程中递归操作十分常见需要特别熟练,需要掌握先序、中序、后序的基本概念以及遍历。
树的先序、中序、后序模板:
package com.cz.Tree;
import java.util.Stack;
/**
* @ProjectName: Data_structure
* @Package: com.cz.Tree
* @ClassName: UnRecursiveTraversalTree
* @Author: 张晟睿
* @Date: 2022/3/20 16:06
* @Version: 1.0
*/
public class UnRecursiveTraversalTree {
public static void main(String[] args) {
Node1 head = new Node1(1);
head.left = new Node1(2);
head.right = new Node1(3);
head.left.left = new Node1(4);
head.left.right = new Node1(5);
head.right.left = new Node1(6);
head.right.right = new Node1(7);
pre(head);
System.out.println("========");
middle(head);
System.out.println("========");
post(head);
System.out.println("========");
}
public static class Node1 {
public int value;
public Node1 left;
public Node1 right;
public Node1(int val) {
value = val;
}
}
public static void pre(Node1 head) {
System.out.println("先序遍历:");
Stack<Node1> s = new Stack<>();
if(head != null) {
s.push(head);
while(!s.isEmpty()) {
Node1 node = s.pop();
System.out.print(node.value + " ");
if(node.right != null) s.push(node.right);
if(node.left != null) s.push(node.left);
}
}
System.out.println();
}
public static void middle(Node1 head){
System.out.println("中序遍历:");
if (head != null) {
Stack<Node1> s = new Stack<>();
while(!s.isEmpty() || head != null) {
//步骤1:如果头结点不为空的话,一直向左边执行
if (head != null) {
s.push(head);
head = head.left;
}else {//根节点打印后,来到右树,继续执行步骤1
head = s.pop();
System.out.print(head.value + " ");
head = head.right;
}
}
System.out.println();
}
}
public static void post(Node1 head){
System.out.println("后序遍历:");
if(head != null) {
Stack<Node1> s = new Stack<>();
s.push(head);
Node1 c = null; //指向栈顶的某个元素的位置
while(!s.isEmpty()) {
c = s.peek();
//判断c左孩子 是否已经处理过
if(c.left != null && head != c.left && head != c.right) {
s.push(c.left);
//判断c右孩子 是否已经处理过
}else if(c.right != null && head != c.right) {
s.push(c.right);
}else {
System.out.print(s.pop().value+" ");
head = c; //head用来记录上次打印的内容
}
}
System.out.println();
}
}
}
❤️来自专栏《LeetCode基础算法题》欢迎订阅❤️
厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。
对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!