「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。
题目
链接:leetcode-cn.com/problems/co…
给你一个整数数组 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,3] 和 [3,1] 都是高度平衡二叉搜索树。
提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums按 严格递增 顺序排列
思路
先简单说说常规解法,因为数组是严格的升序数组,然后根据BST的特性,我们只要将数组以中间索引为界划分成左,右两个数组分别对应着当前节点的left和right,中间索引的值为当前节点的值。
接下来让题目升级一下,如果数组是无序的(不含重复元素),我们该如何建立这个BBST。如果没学习过AVL树(BBST)的小伙伴可以看一看,下面给出BBST的代码。核心是树节点的旋转。
详细看代码注释:
代码
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {number[]} nums
* @return {TreeNode}
*/
var sortedArrayToBST = function(nums) {
if(nums.length == 0) return null;
let index = Math.floor(nums.length / 2),
node = new TreeNode(nums[index]);
node.left = sortedArrayToBST(nums.slice(0, index));
node.right = sortedArrayToBST(nums.slice(index + 1));
return node;
};
function arrayToBBST(nums){
let avlTree = new AVLTree();
for(let i = 0; i < nums.length; i++){
avlTree.insert(nums[i]);
}
return avlTree.root;
}
// AVL树节点
class AVLTreeNode {
constructor(val){
this.val = val;
this.left = this.right = null;
this.height = 1;
}
}
// 平衡状态
const BLANCE_STATE = {
UNBALANCE_LEFT: 2,
UNBALANCE_RIGHT: -2,
SLIGHT_UNBALANCE_LEFT: 1,
SLIGHT_UNBALANCE_RIGHT: -1,
BALANCE: 0
}
// AVLTree
class AVLTree {
constructor(){
this.root = null;
}
_getHeight(node){
return node != null ? node.height : 0;
}
// 有节点发生位置变化的都要更新Height(旋转)
_updateHeigh(node){
node.height = Math.max(this._getHeight(node.left), this._getHeight(node.right)) + 1;
return node;
}
_getBalanceState(node){
return this._getHeight(node.left) - this._getHeight(node.right);
}
// 返回值的高度也变化了,但是返回值统一在blance中改变
_leftRotate(node){
let res = node.right;
node.right = res.left;
res.left = this._updateHeigh(node);
return res;
}
// 返回值的高度也变化了,但是返回值统一在blance中改变
_rightRotate(node){
let res = node.left;
node.left = res.right;
res.right = this._updateHeigh(node);
return res;
}
// 返回值的高度也变化了,但是返回值统一在blance中改变
_leftRightRotate(node){
node.left = this._updateHeigh(this._leftRotate(node.left));
return this._rightRotate(node);
}
// 返回值的高度也变化了,但是返回值统一在blance中改变
_rightLeftRotate(node){
node.right = this._updateHeigh(this._rightRotate(node.right));
return this._leftRotate(node);
}
insert(val){
this.root = this._insertNode(this.root, val);
}
_insertNode(node, val){
if(node == null) return new AVLTreeNode(val);
if(node.val == val) return node;
if(node.val < val){
node.right = this._insertNode(node.right, val);
}else if(node.val > val){
node.left = this._insertNode(node.left, val);
}
// 判断是否需要平衡,并进行平衡
return this._doBalance(node);
}
search(val){
let node = this.root;
while(node){
if(node.val == val) return node;
else if(node.val < val) node = node.right;
else if(node.val > val) node = node.left;
}
return null;
}
getPre(val){
let res = null,
node = this.root;
while(node){
if(node.val >= val) node = node.left;
else if(node.val < val){
res = node;
node = node.right;
}
}
return res;
}
getNext(val){
let res = null,
node = this.root;
while(node){
if(node.val <= val) node = node.right;
else if(node.val > val){
res = node;
node = node.left;
}
}
return res;
}
remove(val){
let node = this.search(val);
if(node == null) return false;
this.root = this._removeNode(this.root, val);
return true;
}
_removeNode(node, val){
if(node.val > val) node.left = this._removeNode(node.left, val);
else if(node.val < val) node.right = this._removeNode(node.right, val);
else if(node.val == val){
if (node.left == null) return node.right;
else if(node.right == null) return node.left;
else{
let next = this.getNext(val);
node.val = next.val;
// 转为删除next节点
node.right = this._removeNode(node.right, node.val);
}
}
return this._doBalance(node);
}
_doBalance(node){
if(node == null) return null;
const balanceState = this._getBalanceState(node);
// 左侧偏重
if(balanceState == BLANCE_STATE.UNBALANCE_LEFT){
// 判断是否需要二次旋转
const leftNodeBalanceState = this._getBalanceState(node.left);
if(leftNodeBalanceState == BLANCE_STATE.SLIGHT_UNBALANCE_RIGHT){
return this._updateHeigh(this._leftRightRotate(node))
}else{
return this._updateHeigh(this._rightRotate(node));
}
// 右侧偏重
}else if(balanceState == BLANCE_STATE.UNBALANCE_RIGHT){
// 判断是否需要二次旋转
const rightNodeBalanceState = this._getBalanceState(node.right);
if(rightNodeBalanceState == BLANCE_STATE.SLIGHT_UNBALANCE_LEFT){
return this._updateHeigh(this._rightLeftRotate(node));
}else{
return this._updateHeigh(this._leftRotate(node));
}
}
return this._updateHeigh(node);
}
}