厦门优秀的网站设计/制作网页多少钱
题目
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3/ \9 20/ \15 7
题目分析
根据一棵树的前序遍历和中序遍历情况画出该树,是离散数学和数据结构课程中都讲过的内容。前序遍历的顺序是:根->左子树->右子树。而中序遍历的顺序是:左子树->根->右子树。因此,我们先看中序遍历的情况,比如第一个元素是3,这就是根,而它的左子树和右子树的情况可以看中序遍历的情况,以3为分界,左侧的值即为左子树,右侧的值即为右子树。那么怎么确认子树的根节点是哪一个呢?这个也很简单,比如我们看3的右子树,在前序遍历中,{15,20,7}中最先出现的是20,因此20就是右子树的根节点,即root.right为20。掌握了这个方法,我们就可以通过递归的思路解决这个问题。
代码
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode root;public int findIndex(int[] array, int target) {for (int i = 0; i < array.length; i++) {if (target == array[i])return i;}return -1;}public boolean contains(int[] array, int target) {for (int i = 0; i < array.length; i++) {if (target == array[i])return true;}return false;}public void buildTree(TreeNode root, int[] curArray, int[] preorder) {int index = findIndex(curArray, root.val);int[] leftArray = Arrays.copyOfRange(curArray, 0, index);int[] rightArray = Arrays.copyOfRange(curArray, index + 1, curArray.length);TreeNode leftNode = null;TreeNode rightNode = null;if (leftArray.length > 0) {for (int i : preorder) {if (contains(leftArray, i)) {leftNode = new TreeNode(i);break;}}root.left = leftNode;buildTree(leftNode, leftArray, preorder);}if (rightArray.length > 0) {for (int i : preorder) {if (contains(rightArray, i)) {rightNode = new TreeNode(i);break;}}root.right = rightNode;buildTree(rightNode, rightArray, preorder);}}public TreeNode buildTree(int[] preorder, int[] inorder) {if(preorder.length==0)return null;root = new TreeNode(preorder[0]);buildTree(root, inorder, preorder);return root;}
}
这个代码跑了2000多ms,效率极低,我们对其做一个小小的优化。在上述代码中,寻找某一棵子树最先出现的节点的时候,始终使用的是原先的前序遍历的数组。事实上,一旦确定了某个根节点,这个根节点之后是绝对不会再使用了,因此我们可以使用arraylist存储,不断删除这些已经确定的根节点,从而提高效率。
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/
class Solution {public TreeNode root;public int findIndex(int[] array, int target) {for (int i = 0; i < array.length; i++) {if (target == array[i])return i;}return -1;}public boolean contains(int[] array, int target) {for (int i = 0; i < array.length; i++) {if (target == array[i])return true;}return false;}public void buildTree(TreeNode root, int[] curArray, ArrayList<Integer> preorder) {int index = findIndex(curArray, root.val);int[] leftArray = Arrays.copyOfRange(curArray, 0, index);int[] rightArray = Arrays.copyOfRange(curArray, index + 1, curArray.length);TreeNode leftNode = null;TreeNode rightNode = null;if (leftArray.length > 0) {for (int i : preorder) {if (contains(leftArray, i)) {leftNode = new TreeNode(i);break;}}root.left = leftNode;preorder.remove(preorder.indexOf(leftNode.val));buildTree(leftNode, leftArray, preorder);}if (rightArray.length > 0) {for (int i : preorder) {if (contains(rightArray, i)) {rightNode = new TreeNode(i);break;}}root.right = rightNode;preorder.remove(preorder.indexOf(rightNode.val));buildTree(rightNode, rightArray, preorder);}}public TreeNode buildTree(int[] preorder, int[] inorder) {ArrayList<Integer> pre = new ArrayList<Integer>();for(int i:preorder)pre.add(i);if(preorder.length==0)return null;root = new TreeNode(preorder[0]);buildTree(root, inorder, pre);return root;}
}
优化后的代码运行完毕仅需要27ms,这说明我们要时时刻刻注意代码的优化,有时候几行的优化可能会代码效率百倍计的提升。