leetcode hot 100

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

leetcode hot 100_第1张图片
本题要求我们将一个有序数组并且是升序的,构造成一个平衡二叉搜索树
二叉搜索树是:

  1. 若他的左子树不为空,则左子树上所有节点的值都小于根节点的值
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  3. 它的左右子树也分别是二叉搜索树
    平衡二叉搜索树:
  4. 左子树与右子树高度之差的绝对值不超过1
  5. 树的每个左子树和右子树都是AVL树
  6. 每一个节点都有一个平衡因子(balance factor),任一节点的平衡因子是-1、0、1(每一个节点的平衡因子 = 右子树高度 - 左子树高度)

所以,我们这个题目,不能直接构造成链式的二叉搜索树。那么这个数组是升序的,我们直接选取数组的中间节点当作根节点(数组是奇数还是偶数不影响,比如1,2,3,4/1,2,3,4,5)这里针对偶数选取2或者3作为根节点都是可以的!只不过是树的结构不同。

这题我们可以采用递归来做,

  1. 首先确定递归函数的传入参数以及返回值:我们需要返回一个TreeNode,然后传入数组nums[],左节点left以及右节点right。
  2. 然后确定递归结束条件:当我们这个划分的左右区间,出现left>right的时候,递归就应该结束了(我们选取的区间是左闭右闭的区间,因为如果区间内只有一个数,只能是左闭右闭)。
  3. 确定单层递归的逻辑:我们选出中间数据作为根节点root,然后构造左子树(用递归函数),再构造右子树(用递归函数)即可。
class Solution {
	public TreeNode sortedArrayToBST(int[] nums) {
		TreeNode root = traversal(nums, 0, nums.length - 1);
		return root;
	}

	// 左闭右闭区间[left, right]
	private TreeNode traversal(int[] nums, int left, int right) {
		if (left > right) return null;

		int mid = left + ((right - left) >> 1);
		TreeNode root = new TreeNode(nums[mid]);
		root.left = traversal(nums, left, mid - 1);
		root.right = traversal(nums, mid + 1, right);
		return root;
	}
}

注意:

  1. 为什么传入的数组一直都是nums[]就可以了呢,不需要传入左区间或者右区间?因为我们是根据left和right来进行划分区间的,这两个参数一直在变,我们划分的区间也就一直在变化,不需要管nums[]。
  2. left + ((right - left) >> 1) left + ((right -left) >> 1) == (left + right) /2

其作用是 二进制右移,举个例子: 1010 >> 1 == 0101。1010 十进制 10,0101 十进制 5。综上 >> 1 作用相当于除二
所以 left + ((right -left) >> 1) > left + ((right -left)/2)> left + right/2 -left/2 ==> left/2 + right/2 ==> (left + right) /2
问题 :为什么不直接用(left + right) /2 而用left + ((right -left) >> 1)
答: 是因为left + right 在某种情况下可能会超过基本类型所能容纳的最大值,而且 >> (位运算) 比 / 运算要快一点!

你可能感兴趣的:(leetcode,算法,数据结构)