Skip to content

Commit 49c086f

Browse files
committed
elevator
1 parent 3e6dbf5 commit 49c086f

File tree

10 files changed

+567
-128
lines changed

10 files changed

+567
-128
lines changed

src/main/java/joshua/leetcode/binarytree/InorderTraversal.java

Lines changed: 114 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,81 +6,123 @@
66

77
public abstract class InorderTraversal {
88

9-
/**
10-
* Given a binary tree, return the in-order traversal of its nodes' values.
11-
For example:
12-
Given binary tree {1,#,2,3},
13-
1
14-
\
15-
2
16-
/
17-
3
18-
return [1,3,2].
19-
20-
* @param root
21-
* @return
22-
*/
23-
public abstract List<Integer> inorderTraversal(TreeNode root);
9+
/**
10+
* Given a binary tree, return the in-order traversal of its nodes' values.
11+
* For example:
12+
* Given binary tree {1,#,2,3},
13+
* 1
14+
* \
15+
* 2
16+
* /
17+
* 3
18+
* return [1,3,2].
19+
*
20+
* @param root
21+
* @return
22+
*/
23+
public abstract List<Integer> inorderTraversal(TreeNode root);
2424

25-
/**
26-
* non-recursive way.
27-
* @author joy
28-
*
29-
*/
30-
static class Solution1 extends InorderTraversal {
25+
/**
26+
* non-recursive way.
27+
*
28+
* @author joy
29+
*/
30+
static class Solution1 extends InorderTraversal {
3131

32-
@Override
33-
public List<Integer> inorderTraversal(TreeNode root) {
34-
List<Integer> result = new ArrayList<Integer>();
35-
if (root == null)
36-
return result;
37-
Stack<NodeInfo> nodes = new Stack<NodeInfo>();
38-
nodes.push(new NodeInfo(root,false));
39-
while (!nodes.isEmpty()) {
40-
NodeInfo curNode=nodes.peek();
41-
if(curNode.isVisited){
42-
result.add(curNode.node.val);
43-
nodes.pop();
44-
if(curNode.node.right!=null)
45-
nodes.add(new NodeInfo(curNode.node.right,false));
46-
}else{
47-
curNode.isVisited=true;
48-
if(curNode.node.left!=null)
49-
nodes.add(new NodeInfo(curNode.node.left,false));
50-
}
51-
}
52-
return result;
53-
}
32+
@Override
33+
public List<Integer> inorderTraversal(TreeNode root) {
34+
List<Integer> result = new ArrayList<Integer>();
35+
if (root == null)
36+
return result;
37+
Stack<NodeInfo> nodes = new Stack<NodeInfo>();
38+
nodes.push(new NodeInfo(root, false));
39+
while (!nodes.isEmpty()) {
40+
NodeInfo curNode = nodes.peek();
41+
if (curNode.isVisited) {
42+
result.add(curNode.node.val);
43+
nodes.pop();
44+
if (curNode.node.right != null)
45+
nodes.add(new NodeInfo(curNode.node.right, false));
46+
} else {
47+
curNode.isVisited = true;
48+
if (curNode.node.left != null)
49+
nodes.add(new NodeInfo(curNode.node.left, false));
50+
}
51+
}
52+
return result;
53+
}
5454

55-
class NodeInfo {
56-
TreeNode node;
57-
Boolean isVisited;
55+
class NodeInfo {
56+
TreeNode node;
57+
Boolean isVisited;
5858

59-
NodeInfo(TreeNode node, Boolean isVisited) {
60-
this.node = node;
61-
this.isVisited = isVisited;
62-
}
63-
}
64-
}
65-
66-
static class Solution2 extends InorderTraversal{
59+
NodeInfo(TreeNode node, Boolean isVisited) {
60+
this.node = node;
61+
this.isVisited = isVisited;
62+
}
63+
}
64+
}
6765

68-
@Override
69-
public List<Integer> inorderTraversal(TreeNode root) {
70-
List<Integer> result=new ArrayList<Integer>();
71-
traverseSubTree(root,result);
72-
return result;
73-
}
74-
75-
private void traverseSubTree(TreeNode subRoot,List<Integer> result){
76-
if(subRoot==null)
77-
return;
78-
if(subRoot.left!=null)
79-
traverseSubTree(subRoot.left,result);
80-
result.add(subRoot.val);
81-
if(subRoot.right!=null)
82-
traverseSubTree(subRoot.right,result);
83-
}
84-
85-
}
66+
static class Solution2 extends InorderTraversal {
67+
68+
@Override
69+
public List<Integer> inorderTraversal(TreeNode root) {
70+
List<Integer> result = new ArrayList<Integer>();
71+
traverseSubTree(root, result);
72+
return result;
73+
}
74+
75+
private void traverseSubTree(TreeNode subRoot, List<Integer> result) {
76+
if (subRoot == null)
77+
return;
78+
if (subRoot.left != null)
79+
traverseSubTree(subRoot.left, result);
80+
result.add(subRoot.val);
81+
if (subRoot.right != null)
82+
traverseSubTree(subRoot.right, result);
83+
}
84+
}
85+
86+
/**
87+
* Morris Traversal算法。
88+
*
89+
* 不占用任何额外空间,空间复杂度为常量。
90+
*
91+
*/
92+
static class Solution3 extends InorderTraversal {
93+
94+
@Override
95+
public List<Integer> inorderTraversal(TreeNode root) {
96+
List<Integer> result = new ArrayList<Integer>();
97+
TreeNode curNode = root;
98+
while (curNode != null) {
99+
// 该节点的左子树为空,说明curNode本身已经是最左下角的元素,中序遍历条件下访问该元素,同时
100+
// 继续访问该节点的右子树,如果该节点本身没有右子树,它的右子树在这之前已经被标记为中序遍历下的它的后继节点,
101+
// (见后面的分支),这样就达到了Solution1使用栈同样的效果,就是找到了父节点
102+
if (curNode.left == null) {
103+
result.add(curNode.val);
104+
curNode = curNode.right;
105+
} else {
106+
// 开始找curNode在中序遍历下的前驱节点,即leftNode的最右下节点
107+
TreeNode prevNode = curNode.left;
108+
while (prevNode.right != null && prevNode.right != curNode) {
109+
prevNode = prevNode.right;
110+
}
111+
// 找到了中序下的前驱节点,而且prevNode.right == null 说明是第一次访问curNode,所以将前驱关系标好,
112+
// 方便后面回到前驱节点
113+
if(prevNode.right == null) {
114+
prevNode.right = curNode;
115+
curNode = curNode.left;
116+
// curNode的前驱节点就是curNode本身,说明之前已经被标记过,说明curNode的整个左子树都遍历完了。
117+
// 所以访问自身,同时开始访问右子树。
118+
} else {
119+
prevNode.right = null;
120+
result.add(curNode.val);
121+
curNode = curNode.right;
122+
}
123+
}
124+
}
125+
return result;
126+
}
127+
}
86128
}

src/main/java/joshua/leetcode/binarytree/PreorderTraversal.java

Lines changed: 122 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,134 @@
44
import java.util.List;
55
import java.util.Stack;
66

7+
import joshua.leetcode.solutiontag.Stacks;
8+
79
/**
8-
* Binary Tree Preorder Traversal
9-
* @author joy
10+
* Binary Tree Preorder Traversal
1011
*
12+
* @author joy
1113
*/
1214
public abstract class PreorderTraversal {
1315

14-
/**
15-
* Given a binary tree, return the preorder traversal of its nodes' values.
16+
/**
17+
* Given a binary tree, return the preorder traversal of its nodes' values.
18+
* <p/>
19+
* For example:
20+
* Given binary tree {1,#,2,3},
21+
* 1
22+
* \
23+
* 2
24+
* /
25+
* 3
26+
* return [1,2,3].
27+
*
28+
* @param root
29+
* @return
30+
*/
31+
public abstract List<Integer> preorderTraversal(TreeNode root);
32+
33+
/**
34+
* iterative solution using stack.
35+
* <p/>
36+
* 时间复杂度为O(n), 每个节点访问了两遍。
37+
* 空间复杂度为O(logn), 最坏情况下为n,如果出现单侧树的情况下。
38+
*/
39+
@Stacks
40+
static class Solution1 extends PreorderTraversal {
41+
42+
@Override
43+
public List<Integer> preorderTraversal(TreeNode root) {
44+
List<Integer> result = new ArrayList<Integer>();
45+
if (root == null)
46+
return result;
47+
Stack<NodeInfo> nodes = new Stack<NodeInfo>();
48+
nodes.push(new NodeInfo(root));
49+
while (!nodes.isEmpty()) {
50+
NodeInfo nodeInfo = nodes.peek();
51+
if (nodeInfo.visited) {
52+
nodes.pop();
53+
if (nodeInfo.node.right != null)
54+
nodes.push(new NodeInfo(nodeInfo.node.right));
55+
} else {
56+
// visit the root firstly, then push the left node into stack.
57+
result.add(nodeInfo.node.val);
58+
nodeInfo.visited = true;
59+
if (nodeInfo.node.left != null)
60+
nodes.push(new NodeInfo(nodeInfo.node.left));
61+
}
62+
}
63+
return result;
64+
}
65+
66+
private class NodeInfo {
67+
TreeNode node;
68+
Boolean visited = false;
69+
70+
NodeInfo(TreeNode node) {
71+
this.node = node;
72+
}
73+
74+
@Override
75+
public String toString() {
76+
return "NodeInfo [node=" + node.val + ", visited=" + visited + "]";
77+
}
78+
}
79+
}
1680

17-
For example:
18-
Given binary tree {1,#,2,3},
19-
1
20-
\
21-
2
22-
/
23-
3
24-
return [1,2,3].
25-
* @param root
26-
* @return
27-
*/
28-
public abstract List<Integer> preorderTraversal(TreeNode root);
29-
30-
/**
31-
* iterative solution using stack.
32-
*/
33-
static class Solution1 extends PreorderTraversal{
81+
/**
82+
* Morris Traversal
83+
* <p/>
84+
* 时间复杂度为O(n), 空间复杂度为常量,即不占用任何空间,而是利用了叶子节点上的空指针。
85+
* 本文主要解决一个问题,如何实现二叉树的前中后序遍历,有两个要求:
86+
*
87+
* 1. O(1)空间复杂度,即只能使用常数空间;
88+
* 2. 二叉树的形状不能被破坏(中间过程允许改变其形状)。
89+
*
90+
* 通常,实现二叉树的前序(preorder)、中序(inorder)、后序(postorder)遍历有两个常用的方法:一是递归(recursive),
91+
* 二是使用栈实现的迭代版本(stack+iterative)。
92+
* 这两种方法都是O(n)的空间复杂度(递归本身占用stack空间或者用户自定义的stack),所以不满足要求。
93+
*
94+
* Morris Traversal方法可以做到这两点,与前两种方法的不同在于该方法只需要O(1)空间,而且同样可以在O(n)时间内完成。
95+
*
96+
* 要使用O(1)空间进行遍历,最大的难点在于,遍历到子节点的时候怎样重新返回到父节点(假设节点中没有指向父节点的p指针)。
97+
* 由于不能用栈作为辅助空间。为了解决这个问题,Morris方法用到了线索二叉树(threaded binary tree)的概念。
98+
*
99+
* 在Morris方法中不需要为每个节点额外分配指针指向其前驱(predecessor)和后继节点(successor),
100+
* 只需要利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以了。
101+
*
102+
*
103+
* <a href = "http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html">详细的博客</a>
104+
*/
105+
static class Solution2 extends PreorderTraversal {
34106

35-
@Override
36-
public List<Integer> preorderTraversal(TreeNode root) {
37-
List<Integer> result=new ArrayList<Integer>();
38-
if(root==null)
39-
return result;
40-
Stack<NodeInfo> nodes=new Stack<NodeInfo>();
41-
nodes.push(new NodeInfo(root));
42-
while(!nodes.isEmpty()){
43-
NodeInfo nodeInfo=nodes.peek();
44-
if(nodeInfo.visited){
45-
nodes.pop();
46-
if(nodeInfo.node.right!=null)
47-
nodes.push(new NodeInfo(nodeInfo.node.right));
48-
}else{
49-
result.add(nodeInfo.node.val);
50-
nodeInfo.visited=true;
51-
if(nodeInfo.node.left!=null)
52-
nodes.push(new NodeInfo(nodeInfo.node.left));
53-
}
54-
}
55-
return result;
56-
}
57-
58-
private class NodeInfo{
59-
TreeNode node;
60-
Boolean visited=false;
61-
62-
NodeInfo(TreeNode node){this.node=node;}
107+
@Override
108+
public List<Integer> preorderTraversal(TreeNode root) {
109+
List<Integer> result = new ArrayList<Integer>();
110+
TreeNode curNode = root;
111+
while (curNode != null) {
112+
if (curNode.left == null) {
113+
result.add(curNode.val);
114+
curNode = curNode.right;
115+
} else {
116+
TreeNode prevNode = curNode.left;
117+
while (prevNode.right != null && prevNode.right != curNode) {
118+
prevNode = prevNode.right;
119+
}
120+
// curNode is visited for the first time
121+
if (prevNode.right == null) {
122+
// visit curNode. 'cause this is preorder traversal
123+
result.add(curNode.val);
124+
prevNode.right = curNode;
125+
curNode = curNode.left;
126+
} else {
127+
// recover the pointer back into null
128+
prevNode.right = null;
129+
curNode = curNode.right;
130+
}
131+
}
132+
}
133+
return result;
134+
}
135+
}
63136

64-
@Override
65-
public String toString() {
66-
return "NodeInfo [node=" + node.val + ", visited=" + visited + "]";
67-
}
68-
}
69-
}
70-
71137
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2016 Baidu Inc. All rights reserved.
2+
3+
package joshua.oop.elevator;
4+
5+
/**
6+
* @author Jiang Yong ([email protected])
7+
*/
8+
public enum Direction {
9+
UP, DOWN
10+
}

0 commit comments

Comments
 (0)