Recursion写法太简单,不值得一提。如果有人问你怎么写,那么他一定是要你写iterative的解法
这里是新版
preOrder Traversal的写法
public List preorderTraversal(TreeNode root) {
Deque deque = new ArrayDeque<>();
List ans = new ArrayList<>();
if (root != null) deque.push(root);
while (!deque.isEmpty()) {
TreeNode node = deque.pop();
ans.add(node.val);
if (node.right != null) deque.push(node.right);
if (node.left != null) deque.push(node.left);
}
return ans;
}
Inorder traversal的建议写法:
public List inorderTraversal(TreeNode root) {
List ans = new ArrayList<>();
Deque deque = new ArrayDeque<>();
pushLeft(deque, root);
while (!deque.isEmpty()) {
TreeNode node = deque.pop();
ans.add(node.val);
pushLeft(deque, node.right);
}
return ans;
}
private void pushLeft(Deque deque, TreeNode node) {
while (node != null) {
deque.push(node);
node = node.left;
}
}
preOrder Traversal的建议写法
public List postorderTraversal(TreeNode root) {
Deque deque = new ArrayDeque<>();
List ans = new ArrayList<>();
TreeNode prev = null;
pushLeft(deque, root);
while (!deque.isEmpty()) {
TreeNode node = deque.peek();
if (node.right != null && prev != node.right) {
pushLeft(deque, node.right);
} else {
ans.add(deque.pop().val);
prev = node;
}
}
return ans;
}
private void pushLeft(Deque deque, TreeNode node) {
while (node != null) {
deque.push(node);
node = node.left;
}
}
下面是旧版
Preorder
先说preorder,这种最简单.
思路就是先把root丢进栈里。
每次从栈里pop一个元素出来,记下来元素的值,再把它的右孩子丢进去,再把左孩子丢进去。
public List preorderTraversal(TreeNode root) {
List ans = new ArrayList<>();
Deque deque = new ArrayDeque<>();
if (root == null) return ans;
deque.push(root);
while (!deque.isEmpty()) {
TreeNode node = deque.pop();
ans.add(node.val);
if (node.right != null) deque.push(node.right);
if (node.left != null) deque.push(node.left);
}
return ans;
}
Inorder,
Lazy push做法
思路是先建一个空栈。然后借助一个helper变量, 初始化为root。
如果helper不是空的,把就helper丢进栈里,然后helper变成它的左孩子。如果helper是空的,表明已经走到最左边了。这时从栈里取一个元素pop出来,记下它的值,然后让helper等于它的右孩子。
每次从栈顶取元素时,要先把它的值记下来,再 try 它的右孩子,因为他的左孩子早已经 try过了。
这种做法我给它取了个名字叫做 lazy push, 被动压栈。
public List inorderTraversal(TreeNode root) {
Deque deque = new ArrayDeque();
TreeNode helper = root;
List result = new ArrayList<>();
while(helper != null || !deque.isEmpty()) {
if (helper != null) {
deque.push(helper);
helper = helper.left;
} else {
helper = deque.pop();
result.add(helper.val);
helper = helper.right;
}
}
return result;
}
Inorder: active push写法
第二种写法是积极压栈的写法。每拿到一个点,我就一路向左走到底,把它所有直系左孩子都放进栈里。
然后每次从栈顶pop取值,然后把pop出来这个点的右孩子的所有直系左孩子都放进去。
这个做法不需要像上次那样记录一个当前helper节点,感觉更好。
我把这种做法叫做active push, 积极压栈,以区分上面lazy push的写法。
public List inorderTraversal(TreeNode root) {
Deque deque = new LinkedList<>();
List ans = new ArrayList<>();
while (root != null) {
deque.push(root);
root = root.left;
}
while (!deque.isEmpty()) {
TreeNode node = deque.pop();
ans.add(node.val);
node = node.right;
while ( node != null) {
deque.push(node);
node = node.left;
}
}
return ans;
}
post order
积极压栈的写法
这种写法有点绕,我打赌你记不住,还是看上面的解法吧
public List postorderTraversal(TreeNode root) {
List result = new ArrayList();
Deque stack = new LinkedList();
TreeNode node = root;
//push all the left node to the stack
while(node != null) {
stack.push(node);
node = node.left;
}
//clearing all the stack
while(!stack.isEmpty()) {
node = stack.peek();
if(node.right == null) {
result.add(node.val);
stack.pop();
while(!stack.isEmpty() && node == stack.peek().right) {
node = stack.pop();
result.add(node.val);
}
}
else {
node = node.right;
while(node != null) {
stack.push(node);
node = node.left;
}
}
}
return result;
}