关于递归的误解
结论:
递归本身并不存在所谓的效率差。
认为递归慢的原因:
它要多开一些栈,存储中间结果,如果递归深度很深的话会存在效率问题。
现实实践中:
- 一般情况不会有非常深的递归
- 计算机的存储方式和编译器对递归,特别是尾递归的优化,使得我们可以认为递归的效率和循环的效率是一样的。不需要带有有色眼镜一看到递归就认为一定比循环慢。
举例:
斐波那契数列如果只是傻递归,而没有存储中间结果,导致本身线性可以解决的问题,需要指数级的时间复杂度才能解决的话,那这是不合理的,但是这不怪递归这种方法,而是程序本身的问题。
题目详述
给定一个二叉树,返回它的中序 遍历。
Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
解法一
递归。时间复杂度:O(n).空间复杂度:O(logn)
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
helper(root, res);
return res;
}
public void helper(TreeNode root, List<Integer> res) {
if (root != null) {
if (root.left != null) helper(root.left, res);
res.add(root.val);
if (root.right != null) helper(root.right, res);
}
}
}
解法二
栈。时间复杂度:O(n),空间复杂度:O(n)
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
res.add(curr.val);
curr = curr.right;
}
return res;
}
}
解法三
用栈模拟递归。时间复杂度:O(n),空间复杂度:O(n)
class Solution {
class ColorNode {
TreeNode node;
int color;//1:访问过,即灰色;0:未访问,即白色
public ColorNode(TreeNode node, int color) {
this.node = node;
this.color = color;
}
}
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<ColorNode> stack = new Stack<>();
stack.push(new ColorNode(root, 0));
while (!stack.isEmpty()) {
ColorNode cn = stack.pop();
if (cn.color == 0) {
if (cn.node.right != null) stack.push(new ColorNode(cn.node.right, 0));
stack.push(new ColorNode(cn.node, 1));
if (cn.node.left != null) stack.push(new ColorNode(cn.node.left, 0));
}else
res.add(cn.node.val);
}
return res;
}
}