題目連接:https://leetcode.com/problems/symmetric-tree/description/java
題目大意:給出一個二叉樹,判斷其是不是對稱的,例子以下node
法一:用常規層序遍歷一直WA,某一天忽然開竅發現bug,改了以後提交ac了,這個bug其實就是怎麼去記錄當前層的最後一個結點,不能直接用結點指針進行標記,由於有可能出現null的狀況,也不能用每層固定的結點個數也就是2^depth來進行判斷是不是一層的最後一個結點,由於前面可能有不少個null,而並非每一個null都會進入隊列。這裏採用的辦法是利用queue.size()來記錄每層進隊列的結點個數,而後利用cnt--操做來判斷當前層是否遍歷完。雖然時間長點,但畢竟本身的心血,代碼以下(耗時5ms):ide
1 public static boolean isSymmetric(TreeNode root) { 2 if(root == null) { 3 return true; 4 } 5 boolean flag = true; 6 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 7 queue.offer(root); 8 int cnt = 1; 9 List<TreeNode> listNode = new ArrayList<TreeNode>(); 10 while(!queue.isEmpty()) { 11 TreeNode node = queue.poll(); 12 cnt--; 13 listNode.add(node); 14 if(node != null) { 15 queue.offer(node.left); 16 queue.offer(node.right); 17 } 18 if(cnt == 0) { 19 cnt = queue.size(); 20 int length = listNode.size(); 21 for(int i = 0; i < length / 2; i++) { 22 if((listNode.get(i) == null && listNode.get(length - 1 - i) != null) || 23 (listNode.get(i) != null && listNode.get(length - 1 - i) == null)) { 24 flag = false; 25 break; 26 } 27 else if(listNode.get(i) != null && listNode.get(length - 1 - i) != null) { 28 if(listNode.get(i).val != listNode.get(length - 1 - i).val) { 29 flag = false; 30 break; 31 } 32 } 33 } 34 if(flag == false) { 35 return flag; 36 } 37 listNode.clear(); 38 } 39 } 40 return flag; 41 }
法二(借鑑):看完題解後,利用層序遍歷的變種,每次進隊時同時壓入左右孩子,注意壓入的順序,代碼以下(耗時2ms):spa
1 public static boolean isSymmetric(TreeNode root) { 2 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 3 queue.offer(root); 4 queue.offer(root); 5 boolean flag = true; 6 while(!queue.isEmpty()) { 7 TreeNode nodeLeft = queue.poll(); 8 TreeNode nodeRight = queue.poll(); 9 10 if((nodeLeft != null && nodeRight == null) || (nodeLeft == null && nodeRight != null)) { 11 return false; 12 } 13 else if(nodeLeft != null && nodeRight != null) { 14 if(nodeLeft.val != nodeRight.val) { 15 return false; 16 } 17 else { 18 queue.offer(nodeLeft.left); 19 queue.offer(nodeRight.right); 20 21 queue.offer(nodeLeft.right); 22 queue.offer(nodeRight.left); 23 } 24 } 25 } 26 return flag; 27 }
法三(借鑑):利用雙端隊列來作,思想與法二相似,每次同時壓入左右孩子,只是這裏用到了java中的雙端隊列類,代碼以下(耗時3ms):指針
1 public static boolean isSymmetric(TreeNode root) { 2 Deque<TreeNode> queue = new LinkedList<TreeNode>(); 3 queue.offerFirst(root); 4 queue.offerLast(root); 5 boolean flag = true; 6 while(!queue.isEmpty()) { 7 TreeNode nodeLeft = queue.pollFirst(); 8 TreeNode nodeRight = queue.pollLast(); 9 10 if((nodeLeft != null && nodeRight == null) || (nodeLeft == null && nodeRight != null)) { 11 return false; 12 } 13 else if(nodeLeft != null && nodeRight != null) { 14 if(nodeLeft.val != nodeRight.val) { 15 return false; 16 } 17 else { 18 queue.offerFirst(nodeLeft.left); 19 queue.offerFirst(nodeLeft.right); 20 21 queue.offerLast(nodeRight.right); 22 queue.offerLast(nodeRight.left); 23 } 24 } 25 } 26 return flag; 27 }
法四(借鑑):這個比較難,利用遞歸左右子樹同時判斷,代碼以下(耗時0ms):code
1 public static boolean isSymmetric(TreeNode root) { 2 if(root == null) { 3 return true; 4 } 5 return isSymmetric2(root, root); 6 } 7 public static boolean isSymmetric2(TreeNode root1, TreeNode root2) { 8 if(root1 == null && root2 == null) { 9 return true; 10 } 11 else if(root1 == null || root2 == null) { 12 return false; 13 } 14 else { 15 if(root1.val != root2.val) { 16 return false; 17 } 18 else { 19 return isSymmetric2(root1.left, root2.right) && isSymmetric2(root1.right, root2.left); 20 } 21 } 22 }