Leetcode 108. 将有序数组转换为二叉搜索树

157 阅读3分钟

Leetcode 108. 将有序数组转换为二叉搜索树

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

1、题目📑

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

实例1

img

输入:nums = [-10,-3,0,5,9]

输出:[0,-3,9,-10,null,5]

解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

img

实例2

img

输入: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

采用中序遍历,选择中间的位置作为根节点,进行根节点左边数字进行遍历,根节点右边的数字进行遍历。

  1. l > r 时,平衡二叉搜索树为空。
  2. 递归根节点左树,右树。
  3. 返回根节点。

废话少说~~~~~上代码!

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)。

image-20220413211803405

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基础算法题》欢迎订阅❤️‍

厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。

对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!

原题链接:108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode) (leetcode-cn.com)