Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e1d8c46

Browse files
refactor 545
1 parent 2988409 commit e1d8c46

File tree

3 files changed

+77
-89
lines changed

3 files changed

+77
-89
lines changed

src/main/java/com/fishercoder/common/utils/TreeUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static TreeNode constructBinaryTree(List<Integer> treeValues) {
4848
}
4949

5050
public static void printBinaryTree(TreeNode root) {
51-
CommonUtils.println("\n\nPrinting out the binary tree in a very visual manner as below:");
51+
CommonUtils.println("\nPrinting out the binary tree in a very visual manner as below:\n");
5252

5353
// imitating from BTreePrinter class
5454
int maxLevel = TreeUtils.maxLevel(root);

src/main/java/com/fishercoder/solutions/_545.java

Lines changed: 44 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@
33
import com.fishercoder.common.classes.TreeNode;
44

55
import java.util.ArrayList;
6-
import java.util.HashSet;
76
import java.util.List;
8-
import java.util.Set;
97

108
/**
11-
* Given a binary tree, return the values of its boundary in anti-clockwise direction starting from root. Boundary includes left boundary, leaves, and right boundary in order without duplicate nodes.
12-
13-
Left boundary is defined as the path from root to the left-most node. Right boundary is defined as the path from root to the right-most node. If the root doesn't have left subtree or right subtree, then the root itself is left boundary or right boundary. Note this definition only applies to the input binary tree, and not applies to any subtrees.
14-
15-
The left-most node is defined as a leaf node you could reach when you always firstly travel to the left subtree if exists. If not, travel to the right subtree. Repeat until you reach a leaf node.
16-
17-
The right-most node is also defined by the same way with left and right exchanged.
9+
* 545. Boundary of Binary Tree
10+
* Given a binary tree, return the values of its boundary in anti-clockwise direction starting from root.
11+
* Boundary includes left boundary, addLeaves, and right boundary in order without duplicate nodes.
12+
* Left boundary is defined as the path from root to the left-most node.
13+
* Right boundary is defined as the path from root to the right-most node.
14+
* If the root doesn't have left subtree or right subtree,
15+
* then the root itself is left boundary or right boundary.
16+
* Note this definition only applies to the input binary tree, and not applies to any subtrees.
17+
* The left-most node is defined as a leaf node you could reach when you always firstly travel
18+
* to the left subtree if exists. If not, travel to the right subtree.
19+
* Repeat until you reach a leaf node.
20+
* The right-most node is also defined by the same way with left and right exchanged.
1821
1922
Example 1
2023
Input:
@@ -29,7 +32,7 @@
2932
3033
Explanation:
3134
The root doesn't have left subtree, so the root itself is left boundary.
32-
The leaves are node 3 and 4.
35+
The addLeaves are node 3 and 4.
3336
The right boundary are node 1,2,4. Note the anti-clockwise direction means you should output reversed right boundary.
3437
So order them in anti-clockwise without duplicates and we have [1,3,4,2].
3538
@@ -49,109 +52,62 @@
4952
5053
Explanation:
5154
The left boundary are node 1,2,4. (4 is the left-most node according to definition)
52-
The leaves are node 4,7,8,9,10.
55+
The addLeaves are node 4,7,8,9,10.
5356
The right boundary are node 1,3,6,10. (10 is the right-most node).
5457
So order them in anti-clockwise without duplicate nodes we have [1,2,4,7,8,9,10,6,3].
5558
5659
*/
5760
public class _545 {
5861
public List<Integer> boundaryOfBinaryTree(TreeNode root) {
59-
List<Integer> nodes = new ArrayList<>(1000);
60-
if(root == null) return nodes;
62+
List<Integer> nodes = new ArrayList<>();
63+
if (root == null) {
64+
return nodes;
65+
}
6166

6267
nodes.add(root.val);
6368
leftBoundary(root.left, nodes);
64-
leaves(root.left, nodes);
65-
leaves(root.right, nodes);
69+
addLeaves(root.left, nodes);
70+
addLeaves(root.right, nodes);
6671
rightBoundary(root.right, nodes);
6772
return nodes;
6873
}
74+
6975
public void leftBoundary(TreeNode root, List<Integer> nodes) {
70-
if(root == null || (root.left == null && root.right == null)) return;
71-
nodes.add(root.val);
72-
if(root.left == null) leftBoundary(root.right, nodes);
73-
else leftBoundary(root.left, nodes);
74-
}
75-
public void rightBoundary(TreeNode root, List<Integer> nodes) {
76-
if(root == null || (root.right == null && root.left == null)) return;
77-
if(root.right == null)rightBoundary(root.left, nodes);
78-
else rightBoundary(root.right, nodes);
79-
nodes.add(root.val); // add after child visit(reverse)
80-
}
81-
public void leaves(TreeNode root, List<Integer> nodes) {
82-
if(root == null) return;
83-
if(root.left == null && root.right == null) {
84-
nodes.add(root.val);
76+
if (root == null || (root.left == null && root.right == null)) {
77+
/**we don't want to add any LEAVES in leftBoundary and rightBoundary functions either,
78+
* that's why we have the later condition in the if branch.*/
8579
return;
8680
}
87-
leaves(root.left, nodes);
88-
leaves(root.right, nodes);
89-
}
90-
91-
92-
//assume the tree has no duplicate values
93-
public List<Integer> boundaryOfBinaryTree_failed_attempt(TreeNode root) {
94-
//this my original naive attemp failed by 79/117 test cases, specifically by {@link BoundaryofBinaryTreeTest.test5}.
95-
List<Integer> leftBoundary = new ArrayList<>();
96-
leftBoundary = findLeftBoundary(root, leftBoundary);
97-
List<Integer> leaves = new ArrayList<>();
98-
leaves = findLeaves(root, leaves);
99-
List<Integer> rightBoundary = new ArrayList<>();
100-
rightBoundary = findRightBoundary(root, rightBoundary);
101-
List<Integer> boundary = new ArrayList<>();
102-
Set<Integer> set = new HashSet<>();
103-
for (int i = 0; i < leftBoundary.size(); i++) {
104-
boundary.add(leftBoundary.get(i));
105-
set.add(leftBoundary.get(i));
81+
nodes.add(root.val);// add BEFORE child visit
82+
if (root.left == null) {
83+
leftBoundary(root.right, nodes);
84+
} else {
85+
leftBoundary(root.left, nodes);
10686
}
107-
for (int i = 0; i < leaves.size(); i++) {
108-
if (!set.add(leaves.get(i))) continue;
109-
boundary.add(leaves.get(i));
110-
}
111-
for (int i = rightBoundary.size()-1; i >= 0; i--) {
112-
if (!set.add(rightBoundary.get(i))) continue;
113-
boundary.add(rightBoundary.get(i));
114-
}
115-
return boundary;
11687
}
11788

118-
private List<Integer> findRightBoundary(TreeNode root, List<Integer> rightBoundary) {
119-
if (root == null) return rightBoundary;
120-
if (root.right != null) {
121-
rightBoundary.add(root.right.val);
122-
findRightBoundary(root.right, rightBoundary);
123-
} else if (root.left != null) {
124-
rightBoundary.add(root.left.val);
125-
findRightBoundary(root.left, rightBoundary);
126-
} else if (root.left == null && root.right == null) {
127-
return rightBoundary;
128-
}
129-
return rightBoundary;
130-
}
131-
132-
private List<Integer> findLeaves(TreeNode root, List<Integer> leaves) {
133-
if (root == null) return leaves;
134-
if (root.left != null) {
135-
findLeaves(root.left, leaves);
136-
}
137-
if (root.right != null) {
138-
findLeaves(root.right, leaves);
89+
public void rightBoundary(TreeNode root, List<Integer> nodes) {
90+
if (root == null || (root.right == null && root.left == null)) {
91+
return;
13992
}
140-
if (root.left == null && root.right == null) {
141-
leaves.add(root.val);
93+
if (root.right == null) {
94+
rightBoundary(root.left, nodes);
95+
} else {
96+
rightBoundary(root.right, nodes);
14297
}
143-
return leaves;
98+
nodes.add(root.val); // add AFTER child visit(reverse)
14499
}
145100

146-
private List<Integer> findLeftBoundary(TreeNode root, List<Integer> leftBoundary) {
101+
public void addLeaves(TreeNode root, List<Integer> nodes) {
147102
if (root == null) {
148-
return leftBoundary;
103+
return;
149104
}
150-
if (root != null) {
151-
leftBoundary.add(root.val);
152-
findLeftBoundary(root.left, leftBoundary);
105+
if (root.left == null && root.right == null) {
106+
nodes.add(root.val);
107+
return;
153108
}
154-
return leftBoundary;
109+
addLeaves(root.left, nodes);
110+
addLeaves(root.right, nodes);
155111
}
156112

157113
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.fishercoder;
2+
3+
import com.fishercoder.common.classes.TreeNode;
4+
import com.fishercoder.common.utils.TreeUtils;
5+
import com.fishercoder.solutions._545;
6+
import org.junit.BeforeClass;
7+
import org.junit.Test;
8+
9+
import java.util.Arrays;
10+
import java.util.List;
11+
12+
import static junit.framework.Assert.assertEquals;
13+
14+
public class _545Test {
15+
private static _545 test;
16+
private static TreeNode root;
17+
private static List<Integer> expected;
18+
19+
@BeforeClass
20+
public static void setup(){
21+
test = new _545();
22+
}
23+
24+
@Test
25+
public void test1(){
26+
root = TreeUtils.constructBinaryTree(Arrays.asList(1, 2, 3, null, 4, 5, null, 6, 7));
27+
TreeUtils.printBinaryTree(root);
28+
expected = Arrays.asList(1, 2, 4, 6, 7, 5, 3);
29+
assertEquals(expected, test.boundaryOfBinaryTree(root));
30+
}
31+
32+
}

0 commit comments

Comments
 (0)