My code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int countNodes(TreeNode root) {
if (root == null)
return 0;
int left = 1 + getLeftHeight(root);
int right = 1 + getRightHeight(root);
if (left == right)
return (1 << left) - 1;
else
return 1 + countNodes(root.left) + countNodes(root.right);
}
private int getLeftHeight(TreeNode root) {
if (root == null)
return 0;
int height = 0;
while (root.left != null) {
height++;
root = root.left;
}
return height;
}
private int getRightHeight(TreeNode root) {
if (root == null)
return 0;
int height = 0;
while (root.right != null) {
height++;
root = root.right;
}
return height;
}
public static void main(String[] args) {
Solution test = new Solution();
TreeNode n1 = new TreeNode(1);
System.out.println(test.countNodes(n1));
}
}
My test result:
這道題目最簡單的做法,就是直接隨便遍歷。但肯定是不對的,太慢了。
我也在想辦法,利用完整樹的特性。
但是最后沒做出來。
具體做法看下這個博客吧。寫的很清楚。
http://www.programcreek.com/2014/06/leetcode-count-complete-tree-nodes-java/
programcreek 好網站
**
總結: 之前有道題目,kth Smallest number 也是采用了把樹劈成兩半,左右各自統計結點個數。
而這道題目,同樣是左右各自遍歷。雖然具體細節不同。
但是可以看出,這也算是樹的遍歷方式的一種。
Tree 免費的medium和easy差不多都做完了,還差兩道easy。
感覺樹的遍歷方式有如下幾種。
pre-order top-down
in-order sort-order for BST
post-order bottom-up
然后遞歸形式我可以很輕松地寫出來。但是非遞歸形式不會寫。
所以這三種遍歷的非遞歸,要在這周末前學會寫!!!!
然后,level-order
left to right
right to left
zigzag (use two stacks)
然后,
這道題目的遍歷方式,分別遍歷左子樹與右子樹,統計信息。
然后繼續遍歷左子樹的左子樹與右子樹。。。。
以此循環。
同時,設置一些全局的私有變量,有時候會方便寫代碼。
**
Anyway, Good luck, Richardo!
My code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int countNodes(TreeNode root) {
if (root == null)
return 0;
return helper(root);
}
private int helper(TreeNode root) {
if (root == null)
return 0;
int left = getLeftDepth(root);
int right = getRightDepth(root);
if (left == right)
return (int) (2 << (left - 1)) - 1;
else
return 1 + helper(root.left) + helper(root.right);
}
private int getLeftDepth(TreeNode root) {
int counter = 0;
while (root != null) {
counter++;
root = root.left;
}
return counter;
}
private int getRightDepth(TreeNode root) {
int counter = 0;
while (root != null) {
counter++;
root = root.right;
}
return counter;
}
}
這道題目第二次做還是沒做出來。
就是用二分法做。
其中, 用左移位求 2 ^ n 速度更快。 如果用 Math.pow(2, n); 會超時。
參考網頁:
http://www.programcreek.com/2014/06/leetcode-count-complete-tree-nodes-java/
另外,衍生出來一個問題,如果判斷一棵樹是不是complete
我寫了一段代碼如下:
My code:
public boolean isFullBT(TreeNode root) {
if (root == null)
return false;
Queue<TreeNode> q = new LinkedList<TreeNode>();
q.offer(root);
boolean totalNull = false;
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode curr = q.poll();
if (curr.left != null) {
if (totalNull)
return false;
q.offer(curr.left);
}
else if (curr.left == null) {
totalNull = true;
}
if (curr.right != null) {
if (totalNull)
return false;
q.offer(curr.right);
}
else if (curr.right == null) {
totalNull = true;
}
}
}
return true;
}
自己寫出來的。
可以參考下下面兩個網頁:
http://www.geeksforgeeks.org/check-if-a-given-binary-tree-is-complete-tree-or-not/
http://www.geeksforgeeks.org/check-whether-binary-tree-complete-not-set-2-recursive-solution/
Anyway, Good luck, Richardo!
My code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int h = height(root);
if (h == -1) {
return 0;
}
else {
int right = height(root.right);
if (right == h - 1) {
return (1 << h) + countNodes(root.right);
}
else {
return (1 << (h - 1)) + countNodes(root.left);
}
}
}
private int height(TreeNode root) {
if (root == null) {
return -1;
}
return 1 + height(root.left);
}
}
這道題目我的做法超時了,即使換成 比特移位操作。
然后看了答案,覺得還是醍醐灌頂。
做大的變化在于右子樹。
右子樹高度和左子樹之差,可能是0,可能是1
當差是0, 那么左子樹一定會complete,那么我們可以用公式先計算出 左子樹 + 根節點個數,然后recursion計算,右子樹結點個數
當差是1,那么,右子樹一定是complete tree,只不過高度少了1,移位的時候,少向右移動移位即可。然后我們需要recursive計算出,左子樹的結點個數。
差不多就這么個思路。
iteration的做法也是如此:
My code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int h = height(root);
int ret = 0;
while (root != null) {
int right = height(root.right);
if (right == h - 1) {
ret += (1 << h);
root = root.right;
}
else {
ret += (1 << (h - 1));
root = root.left;
}
h--;
}
return ret;
}
private int height(TreeNode root) {
if (root == null) {
return -1;
}
return 1 + height(root.left);
}
}
reference:
https://discuss.leetcode.com/topic/15533/concise-java-solutions-o-log-n-2
上一下我寫的TLE的解法:
My code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
return helper(root);
}
private int helper(TreeNode root) {
if (root == null) {
return 0;
}
int left = getMaxDepth(root.left);
int right = getMinDepth(root.right);
if (left == right) {
return (1 << (left + 1)) - 1;
}
else {
int leftMin = getMinDepth(root.left);
if (left == leftMin) {
return (1 << left) + helper(root.right);
}
else {
return helper(root.left) + 1 + helper(root.right);
}
}
}
private int getMaxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(getMaxDepth(root.left), getMaxDepth(root.right)) + 1;
}
private int getMinDepth(TreeNode root) {
if (root == null) {
return 0;
}
else {
return Math.min(getMinDepth(root.left), getMinDepth(root.right)) + 1;
}
}
}
如何判斷一棵樹是否為complete?
就判斷 左子樹的最大深度和右子樹的最小深度是否相等。
如果相等,就是complete
Anyway, Good luck, Richardo! -- 09/07/2016