最近在Leetcode刷題,發現遇到不少二叉樹類型的題目,題目會定義好樹節點TreeNode的數據結構。
1 public class TreeNode { 2 int val; 3 TreeNode left; 4 TreeNode right; 5 TreeNode() {} 6 TreeNode(int val) { this.val = val; } 7 TreeNode(int val, TreeNode left, TreeNode right) { 8 this.val = val; 9 this.left = left; 10 this.right = right; 11 } 12 }
在題目的示例中,二叉樹的輸入都是一個一維數組,表示這個二叉樹結構。
例如:
輸入:root = [3,1,4,3,null,1,5]
表示的二叉樹為:
因此在IDE里面編碼調試時,需要一個轉化方法方便自己編寫並運行測試用例。
簡單分析數組和二叉樹之間的關系:
輸入:root = [1,2,3,4,5,6,7,8,9]
第i個節點的左子節點為第2*i個節點,右子節點為第2*i+1個節點。因此用簡單的遞歸就可以實現。
1 public class TreeNodeUtil { 2 public static TreeNode createTreeNode(Integer[] array){ 3 TreeNode root = createTreeNode(array, 1); 4 return root; 5 } 6 7 private static TreeNode createTreeNode(Integer[] array, int index) { 8 if(index > array.length){ 9 return null; 10 } 11 Integer value = array[index - 1]; 12 if(value == null){ 13 return null; 14 } 15 TreeNode node = new TreeNode(value); 16 node.left = createTreeNode(array, index * 2); 17 node.right = createTreeNode(array, index * 2 + 1); 18 return node; 19 } 20 }
但是這個方法對於一些情況卻轉化錯誤。因為這個一維數組是優化后的。
例如:
按照上面方法,輸入應該為:
輸入:root = [2,null,4,null,null,9,8,null,null,null,null,null,null,4]
空子節點下沒有子節點,因此不需要這么多冗余數據。
因此輸入應該為:
輸入:root = [2,null,4,9,8,null,null,4]
再次分析數組和二叉樹之間的關系,發現數組中的數據順序是按照二叉樹的層級排列的,這時可以使用隊列的數據結構,數組中的節點按順序進隊,每次節點出隊,如果不是空節點,那么緊跟着是該節點的左子節點和右子節點。
1 public class TreeNodeUtil { 2 public static TreeNode arrayToTreeNode(Integer[] array){ 3 if(array.length == 0){ 4 return null; 5 } 6 TreeNode root = new TreeNode(array[0]); 7 Queue<TreeNode> queue = new LinkedList<>(); 8 queue.add(root); 9 boolean isLeft = true; 10 for(int i = 1; i < array.length; i++){ 11 TreeNode node = queue.peek(); 12 if(isLeft){ 13 if(array[i] != null){ 14 node.left = new TreeNode(array[i]); 15 queue.offer(node.left); 16 } 17 isLeft = false; 18 }else { 19 if(array[i] != null){ 20 node.right = new TreeNode(array[i]); 21 queue.offer(node.right); 22 } 23 queue.poll(); 24 isLeft = true; 25 } 26 } 27 return root; 28 } 29 }
這樣,一維數組轉換成二叉樹就完成了!輸入一個一維數組,返回二叉樹的根節點。