堆和树的相关问题
1.堆
1.1 求数组中第K大的元素
使用堆结构寻找数组中第K大的元素的实现思路如下:
构建最小堆:首先,我们可以将待处理的数组元素构造成一个最小堆。在最小堆中,父节点的值总是小于或等于其子节点的值,这意味着堆顶元素始终是最小的。
删除前K-1个元素:由于我们要找的是第K大的元素,因此我们从堆顶开始,连续删除(交换堆顶元素与最后一个元素并缩小堆大小)K-1次最小元素。这样,在删除了K-1个最小元素后,堆顶的元素就是原数组中的第K大元素。
具体步骤如下:
初始化一个大小为k的小顶堆,并从数组中选取前k个元素放入堆中。
对这个小顶堆进行调整,确保满足堆性质。
然后,循环k-1次:
弹出堆顶元素(即当前最小元素),并将堆大小减一。
将堆外的下一个元素(即当前堆大小位置的数组元素)入堆,并重新调整堆。
当循环结束后,堆顶元素即为数组中第K大的元素。
这种方法的时间复杂度主要取决于堆的构造和K-1次删除操作,总体时间复杂度为O(n + klogk),其中n是数组长度,当k相对于n较小的时候,这种方法效率较高/* * 小顶堆 * */ public class MinHeapFindK { public static void main(String[] args) { MinHeapFindK minHeapFindK = new MinHeapFindK(); /* int k = minHeapFindK.findK(new int[]{3, 2, 1, 5, 6, 4}, 2); System.out.println(k); int k1 = minHeapFindK.findK(new int[]{3, 2, 3,1, 2,4,5,5, 6}, 4); System.out.println(k1); */ // int k1 = minHeapFindK.findK(new int[]{3, 2, 1, 5, 6, 4}, 2); int k2 = minHeapFindK.findK(new int[]{3, 2, 3, 1, 2, 4, 5, 5, 6}, 4); } private int findK(int[] arr, int k) { MinHeapFindK minHeapFindK = new MinHeapFindK(new int[k]); //将前k个元素放入小顶堆 for (int i = 0; i < k; i++) { minHeapFindK.offered(arr[i]); } /* *小于对顶元素跳过,大于堆顶元素则替换堆顶元素,重新执行下潜 * 从k开始循环到最后(arr.length-1) */ for (int i = k; i < arr.length ; i++) { //保留前K大的元素 if (arr[i] >= minHeapFindK.peek()) { minHeapFindK.replace(arr[i]); } } return minHeapFindK.peek(); } int[] array; int size; public MinHeapFindK(int[] array) { this.array = array; this.size = 0; heapify(); } public MinHeapFindK() { } /* * 建堆: * 找到第一个非叶子结点 * 执行下潜,直到没有子节点 * */ private void heapify() { //最后一个非叶子结点 size/2-1 for (int i = size / 2 - 1; i >= 0; i--) { down(i); } } //执行下潜 parent 为需要下潜的索引,下潜到没有孩子,或者孩子都小于当前节点 private void down(int parent) { //左child索引 int leftChild = parent * 2 + 1; //右child索引 int rightChild = leftChild + 1; int min = parent; if (leftChild < size && array[min] > array[leftChild]) min = leftChild; if (rightChild < size && array[min] > array[rightChild]) min = rightChild; if (min != parent) { //下潜并再次调用 swap(parent, min); down(min); } } /* * 上浮操作 * */ public void up(int offered) { int child = size; //子元素索引等于0则到达了堆顶 while (child > 0) { int parent = (child - 1) / 2; if (offered < array[parent]) { array[child] = array[parent]; } else { break; } child = parent; } array[child] = offered; } //交换两个元素 private void swap(int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } public int peek() { return array[0]; } /* * 从第一个位置移除元素,交换头尾,在移除最后一个 * */ public int poll() { int temp = array[0]; //交换首位 swap(0, size - 1); size--; down(0); return temp; } /* * 从指定位置移除元素,交换指定位置和尾,在移除最后一个 * */ public int poll(int index) { int temp = array[index]; //交换首位 swap(index, size - 1); size--; down(index); return temp; } /* * 替换堆顶部元素 * 1.替换堆顶元素 * 2.执行下潜,直到符合堆的特性 * */ public void replace(int replaced) { array[0] = replaced; down(0); } /* * 堆尾部添加元素 * */ public boolean offered(int offered) { if (size == array.length) { return false; } up(offered); size++; return true; } }
1.2 求数据流中第K大的元素
比起数组,数据流是会改变的
/* * 小顶堆 * */ public class MinHeapFindK2 { private MinHeapFindK minHeapFindK; public MinHeapFindK2(int k,int[]arr) { minHeapFindK = new MinHeapFindK(k); for (int i : arr) { add(i); } } public int add(int val) { if (minHeapFindK.size < minHeapFindK.array.length) { minHeapFindK.offered(val); } else if (val > minHeapFindK.peek()) { minHeapFindK.replace(val); } return minHeapFindK.peek(); } public static void main(String[] args) { MinHeapFindK2 minHeapFindK2=new MinHeapFindK2(3,new int[]{4,5,8,2}); int add = minHeapFindK2.add(3); int add1 = minHeapFindK2.add(5); int add2 = minHeapFindK2.add(10); int add3 = minHeapFindK2.add(9); int add4 = minHeapFindK2.add(4); } }
1.3 求数据流中的中位数
在数据流中求中位数,可以使用一个大小为2的堆结构来实现,其中一个为小顶堆(存储较大的一半元素),另一个为大顶堆(存储较小的一半元素)。这样,小顶堆的堆顶元素总是小于或等于大顶堆的堆顶元素,并且两个堆的元素数量之差最多为1。当这两个条件满足时,大顶堆的堆顶元素就是当前流中的中位数。
具体步骤如下:
初始化两个堆,一个大顶堆和一个小顶堆。开始时,将第一个数据元素放入任意一个堆中。
每当有新的数据元素进入时:
将新元素添加到小顶堆中。
如果此时小顶堆的元素个数大于大顶堆的元素个数+1,则从小顶堆取出堆顶元素(即当前最小值)并将其插入到大顶堆中,保持两个堆的元素数量平衡。
调整大顶堆使其满足大顶堆性质。
当需要查询中位数时,直接返回大顶堆的堆顶元素即可。如果两个堆的大小相等,则这个元素就是准确的中位数;如果大顶堆比小顶堆多一个元素,则该元素也是中位数,因为所有小于它的元素都在小顶堆中,所有大于它的元素都在大顶堆中。通过这种方式,可以在O(log k)的时间复杂度内处理每个新来的数据点(k通常为堆的大小,即数据流中已处理的数据量的一半左右),从而实现实时计算数据流的中位数。
/* * 小顶堆 * */ public class MinHeapFindMiddle { private MinHeapFindK rightHeap; private MaxHeap leftHeap; public MinHeapFindMiddle(int capacity) { rightHeap=new MinHeapFindK(); rightHeap.array=new int[capacity]; leftHeap=new MaxHeap(); leftHeap.array=new int[capacity]; } public void addNum(int val) { if(leftHeap.size==rightHeap.size){ //如果相同就加到大顶堆,并将大顶堆最小的加到小顶堆 leftHeap.offered(val); rightHeap.offered(leftHeap.poll()); }else{ //否则相反 rightHeap.offered(val); leftHeap.offered(rightHeap.poll()); } } /* * 右侧元素个数只会大于等于左侧个数 * 两边元素一样多,取两个堆顶求平均 * 否则取右侧堆顶元素 * */ public BigDecimal findMiddle(){ if(leftHeap.size==rightHeap.size){ BigDecimal res = new BigDecimal(leftHeap.peek() + rightHeap.peek()); BigDecimal divide = res.divide(BigDecimal.valueOf(2)); return divide; }else{ return BigDecimal.valueOf(rightHeap.peek()); } } public static void main(String[] args) { MinHeapFindMiddle minHeapFindK2=new MinHeapFindMiddle(10); minHeapFindK2.addNum(1); BigDecimal middle1 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(2); BigDecimal middle2 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(3); BigDecimal middle3 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(7); BigDecimal middle4 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(8); BigDecimal middle5 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(9); BigDecimal middle6 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(10); BigDecimal middle7 = minHeapFindK2.findMiddle(); minHeapFindK2.addNum(11); BigDecimal middle8 = minHeapFindK2.findMiddle(); } }
也可以用java自带的PriorityQueue
2.树
2.1 二叉树
2.1.1 对称二叉树
public class symmetryBinaryTree { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(new TreeNode(4), 2, null), 1, new TreeNode(new TreeNode(5), 3, new TreeNode(6))); TreeNode tree2 = new TreeNode( new TreeNode(new TreeNode(3), 2, new TreeNode(4)), 1, new TreeNode(new TreeNode(4), 2, new TreeNode(3))); boolean sysmmetry1 = isSysmmetry(tree1); boolean sysmmetry2 = isSysmmetry(tree2); } static public boolean isSysmmetry(TreeNode treeNode) { return check(treeNode.left, treeNode.right); } private static boolean check(TreeNode left, TreeNode right) { if (left == null && right == null) { return true; } /*if((left !=null&&right==null) || (left ==null&&right!=null)){ return false; }*/ // left 和right 不会同时为null,所以left和right 不同时为null,但是有1个为null,那么他们两个不可能相等 if (right == null || left == null) { return false; } //同时不为null,值不相等 if (left.val != right.val) { return false; } return check(left.left,right.right)&& check(left.right,right.left); } }
2.1.2 二叉树的最大深度
2.1.2.1 递归解
//最大深度,递归解 public class binaryTreeDepth { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(2), 1, new TreeNode(3)); TreeNode tree2 = new TreeNode( new TreeNode(2), 1, new TreeNode(null, 3, new TreeNode(4))); TreeNode tree3 = new TreeNode(1); int maxDepth1=maxDepth(tree1); int maxDepth2=maxDepth(tree2); int maxDepth3=maxDepth(tree3); } static public int maxDepth(TreeNode treeNode) { if (treeNode == null) { return 0; } //可以不加 /*if (treeNode.left == null && treeNode.right == null) { return 1; }*/ int leftDepth = maxDepth(treeNode.left); int rightDepth = maxDepth(treeNode.right); return Integer.max(leftDepth, rightDepth) + 1; } }
2.1.2.2 非递归解
//最大深度,非递归解 public class binaryTreeDepth2 { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(2), 1, new TreeNode(3)); TreeNode tree2 = new TreeNode( new TreeNode(2), 1, new TreeNode(null, 3, new TreeNode(4))); TreeNode tree3 = new TreeNode(1); int maxDepth1 = maxDepth(tree1); int maxDepth2 = maxDepth(tree2); int maxDepth3 = maxDepth(tree3); } static public int maxDepth(TreeNode treeNode) { LinkedList<TreeNode> stack = new LinkedList<>(); //当前节点 TreeNode curr = treeNode; //最后弹栈的节点 TreeNode pop = null; int max=0; while (curr != null || !stack.isEmpty()) { if (curr != null) { stack.push(curr); int size= stack.size(); if(size>max){ max=size; } curr = curr.left; }else{ TreeNode peek = stack.peek(); //弹栈元素右子树等于上次弹栈的元素,说明左右都已经处理 if(peek.right==null||peek.right==pop){ pop=stack.pop(); }else{ curr=peek.right; } } } return max; } }
2.1.2.3 层序遍历
//最大深度,层序遍历 public class binaryTreeDepth3 { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(2), 1, new TreeNode(3)); TreeNode tree2 = new TreeNode( new TreeNode(2), 1, new TreeNode(null, 3, new TreeNode(4))); TreeNode tree3 = new TreeNode(1); int maxDepth1 = maxDepth(tree1); int maxDepth2 = maxDepth(tree2); int maxDepth3 = maxDepth(tree3); } static public int maxDepth(TreeNode treeNode) { if(treeNode==null){ return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(treeNode); int max=queue.size(); int maxDepth=0; while (!queue.isEmpty()) { for (int i = 0; i < max; i++) { TreeNode poll = queue.poll(); System.out.print(poll.val+"\t"); if (poll.left != null) { queue.offer(poll.left); } if (poll.right != null) { queue.offer(poll.right); } } max = queue.size(); System.out.println(); maxDepth++; } return maxDepth; } }
2.1.3 二叉树最小深度
2.1.3.1 递归解
//最小深度,递归解 public class binaryTreeDepth4 { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(2), 1, new TreeNode(3)); TreeNode tree2 = new TreeNode( new TreeNode(2), 1, new TreeNode(null, 3, new TreeNode(4))); TreeNode tree3 = new TreeNode(1); int minDepth1 = minDepth(tree1); int minDepth2 = minDepth(tree2); int minDepth3 = minDepth(tree3); } static public int minDepth(TreeNode treeNode) { if (treeNode == null) { return 0; } int leftDepth = minDepth(treeNode.left); int rightDepth = minDepth(treeNode.right); if (rightDepth == 0) { return leftDepth + 1; } if (leftDepth == 0) { return rightDepth + 1; } return Integer.min(leftDepth, rightDepth) + 1; } }
2.1.3.2 层序遍历解
//最小深度,层序遍历解,第一个叶子结点就是最小深度 public class binaryTreeDepth5 { public static void main(String[] args) { TreeNode tree1 = new TreeNode( new TreeNode(2), 1, new TreeNode(3)); TreeNode tree2 = new TreeNode( new TreeNode(2), 1, new TreeNode(null, 3, new TreeNode(4))); TreeNode tree3 = new TreeNode(1); int minDepth1 = minDepth(tree1); int minDepth2 = minDepth(tree2); int minDepth3 = minDepth(tree3); } static public int minDepth(TreeNode treeNode) { if(treeNode==null){ return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(treeNode); int min=queue.size(); int minDepth=0; while (!queue.isEmpty()) { min = queue.size(); System.out.println(); minDepth++; for (int i = 0; i < min; i++) { TreeNode poll = queue.poll(); if(poll.left==null && poll.right==null){ return minDepth; } if (poll.left != null) { queue.offer(poll.left); } if (poll.right != null) { queue.offer(poll.right); } } } return minDepth; } }
2.1.4 翻转二叉树
//翻转二叉树 public class binaryTreeInvert { static public TreeNode invertTree(TreeNode treeNode) { invert(treeNode); return treeNode; } static void invert(TreeNode node){ if (node==null)return; TreeNode temp=node.left; node.left=node.right; node.right=temp; invert(node.left); invert(node.right); } }
2.1.5 根据后缀表达式构造表达式树
public class expressionTree { public static void main(String[] args) { String[]strings1={"1","2","-","3","*"}; TreeNode treeNode = expressionToTree(strings1); postOrder(treeNode); } public static TreeNode expressionToTree(String[] tokens) { LinkedList<TreeNode>stack=new LinkedList<>(); for (String token : tokens) { switch (token) { case "+": innerStack( stack, token); break; case "-": innerStack( stack, token); break; case "*": innerStack( stack, token); break; case "/": innerStack( stack, token); break; default: stack.push(new TreeNode(token)); } } return stack.peek(); } private static void innerStack(LinkedList<TreeNode> stack,String token){ TreeNode right = stack.pop(); TreeNode left = stack.pop(); TreeNode<String> parent = new TreeNode<>(left,token,right); stack.push(parent); } /* * 后序遍历 左子树=》右子树 =》根节点 * */ static void postOrder(TreeNode treeNode){ if(treeNode==null){ return; } postOrder(treeNode.left);//左子树 postOrder(treeNode.right);//右子树 System.out.print(treeNode.val+"\t");//根节点 } }
2.1.6 根据前序,中序结果还原二叉树
//根据前序 中序结果还原二叉树 public class restoreTree { private TreeNode buildTree(int[] proOrder,int[]inOrder){ if(proOrder.length==0||inOrder.length==0){ return null; } //根元素值 int rootVal = proOrder[0]; TreeNode root=new TreeNode(rootVal); //根据根节点区分左右子树 for (int i = 0; i < inOrder.length; i++) { if (inOrder[i]==rootVal){ //0~i是左子树 int[] inOrderLeft = Arrays.copyOfRange(inOrder, 0, i + 1); // i+1~inOrder.length-1是右子树 int[] inOrderRight = Arrays.copyOfRange(inOrder, i+1, inOrder.length); int[] proOrderLeft = Arrays.copyOfRange(proOrder, 1, i + 1); int[] proOrderRight= Arrays.copyOfRange(proOrder, i + 1, inOrder.length); root.left = buildTree(proOrderLeft, inOrderLeft); root.right= buildTree(proOrderRight, inOrderRight); break; } } return root; } }
2.1.7 根据中序,后续结果还原二叉树
//根据中序 后序结果还原二叉树 public class restoreTree2 { private TreeNode buildTree(int[]inOrder,int[] postOrder){ if(postOrder.length==0||inOrder.length==0){ return null; } //根元素值 int rootVal = postOrder[postOrder.length-1]; TreeNode root=new TreeNode(rootVal); //根据根节点区分左右子树 for (int i = 0; i < inOrder.length; i++) { if (inOrder[i]==rootVal){ //0~i是左子树 int[] inOrderLeft = Arrays.copyOfRange(inOrder, 0, i + 1); // i+1~inOrder.length-1是右子树 int[] inOrderRight = Arrays.copyOfRange(inOrder, i+1, inOrder.length); int[] postOrderLeft = Arrays.copyOfRange(postOrder, 0, i); int[] postOrderRight= Arrays.copyOfRange(postOrder, i , postOrder.length); root.left = buildTree(inOrderLeft,postOrderLeft); root.right= buildTree(inOrderRight,postOrderRight); break; } } return root; } }
2.2 二叉搜索树
2.2.1 验证合法二叉搜索树
左子树必须小于根节点,右子树必须大于根节点,所有的子节点也必须符合这条规则。
可以利用中序遍历,由小到大排序,若是符合条件就是一个合法的二叉搜索树。
2.2.1.1 非递归
//非递归 public class ValidityBSTree1 { public boolean isValidty(TreeNode node){ TreeNode p=node; Integer prev=null;//上一个值 LinkedList<TreeNode> stack=new LinkedList(); while (p!=null || !stack.isEmpty()){ if(p!=null){ p=p.left; }else{ TreeNode pop = stack.pop(); // System.out.println(pop.val); //处理操作 if(prev!=null&&prev>= pop.val){ return false; } prev=pop.val; p=pop.right; } } return true; } public ValidityBSTree1(TreeNode root) { this.root = root; } public ValidityBSTree1() { } TreeNode root; static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.1.2 递归
package org.alogorithm.tree.binarySearchTree; import java.util.LinkedList; //递归 public class ValidityBSTree2 { Integer prev = null; public boolean isValidty(TreeNode node) { if (node == null) { return true; } boolean validtyLeft = isValidty(node.left); if(!validtyLeft)return false; //处理值 //上一个值必须小于等于当前值 if (prev != null && prev >= node.val) { return false; } prev = node.val; boolean validtyRight = isValidty(node.right); //左右子树全部合法 return validtyRight && validtyLeft; } public ValidityBSTree2(TreeNode root) { this.root = root; } public ValidityBSTree2() { } TreeNode root; static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.1.3 判断上下界
package org.alogorithm.tree.binarySearchTree; //递归 public class ValidityBSTree3 { Integer prev = null; public boolean isValidty(TreeNode node) { return isValidty(node,null,null); } //节点必须大于min小于max public boolean isValidty(TreeNode node,Integer min,Integer max) { if(node==null){ return true; } if((min!=null&&node.val<=min)||(max!=null&&node.val>=max)){ return false; } boolean validtyLeft = isValidty(node.left, min, node.val); if(!validtyLeft)return false; boolean validtyRight = isValidty(node.right, node.val, max); return validtyRight && validtyLeft; } public ValidityBSTree3(TreeNode root) { this.root = root; } public ValidityBSTree3() { } TreeNode root; static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.2 范围求和
2.2.2.1 循环范围求和
package org.alogorithm.tree.binarySearchTree; import java.util.LinkedList; public class SumBSTree1 { Integer prev = null; //节点必须大于min小于max public Integer sum(TreeNode node, Integer min, Integer max) { int sum = 0; TreeNode p = node; LinkedList<TreeNode> stock = new LinkedList(); while (p != null || !stock.isEmpty()) { if (p != null) { stock.push(p); p = p.left; } else { p = stock.pop(); //如果pop.val已经大于上限,则不需要遍历右子树 if(p.val>max){ break; } if (p.val >= min && p.val <= max) { sum += p.val; } p = p.right; } } return sum; } public SumBSTree1(TreeNode root) { this.root = root; } public SumBSTree1() { } TreeNode root; static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.2.2 上下限递归
import java.util.LinkedList; public class SumBSTree1 { Integer prev = null; //节点必须大于min小于max public Integer sum(TreeNode node, Integer min, Integer max) { int sum = 0; TreeNode p = node; LinkedList<TreeNode> stock = new LinkedList(); while (p != null || !stock.isEmpty()) { if (p != null) { stock.push(p); p = p.left; } else { p = stock.pop(); //如果pop.val已经大于上限,则不需要遍历右子树 if(p.val>max){ break; } if (p.val >= min && p.val <= max) { sum += p.val; } p = p.right; } } return sum; } public SumBSTree1(TreeNode root) { this.root = root; } public SumBSTree1() { } TreeNode root; static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.3 根据前序遍历还原二叉搜索树
2.2.3.1 递归插入
public class BstFromPreorder1 { TreeNode root; public BstFromPreorder1(TreeNode root) { this.root = root; } public BstFromPreorder1(int[] arr) { //索引0为根节点 TreeNode treeNode = new TreeNode(arr[0]); for (int i = 1; i < arr.length; i++) { int val = arr[i]; this.root = insert(root, val); } } private TreeNode insert(TreeNode node,int val) { if (node == null) { return new TreeNode(val); } if(val < node.val){ //如果插入值小于当前节点值,则递归插入到左子树 node.left=insert(node.left,val); }else if(val>node.val){ //如果插入值大于当前节点值,则递归插入到右子树 node.right=insert(node.right,val); } return node; } static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
2.2.3.2 上限法
public class BstFromPreorder2 { TreeNode root; public BstFromPreorder2(TreeNode root) { this.root = root; } public BstFromPreorder2(int[] arr) { this.root= insert(arr,Integer.MAX_VALUE); } /* 上限法5,1,7,10,12 1.遍历数组中每一个值,根据值创建节点 -每个节点若成功创建都有左孩子上限,右孩子上限 2.处理下一个值时,如果超过此上限,那么 -将 null 作为上个节点的孩子 -不能创建节点对象 -直到不超过上限为止 3.重复1.2.两步 */ int index = 0; private TreeNode insert(int[] arr, int max) { if (index == arr.length) { return null; } int val = arr[index]; //如果大于上限返回null作为上一个节点的孩子 if (val > max) { return null; } //如果创建了节点 TreeNode treeNode = new TreeNode(val); index++; //如果左右都满了就返回该节点 //左孩子上限就是本身的val treeNode.left = insert(arr, val); //右孩子上限还是max treeNode.right = insert(arr, max); return treeNode; } static class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } public TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } }
1