递归转非递归的栈方法

尾递归

  定义:某个方法在其最后调用自身进行递归,并且这个递归调用一定是该方法做的最后一件事。当需要返回值时是return f(n),没有返回就直接是f(n)。
  误区:这个f(n)外不能加其他东西,因为这就不是最后一件事了。比如如果有返回值的,你不能:乘个常数 return 3*f(n);乘个n return n*f(n);甚至是 f(n)+f(n-1),这些都不算是尾递归。
  尾递归转循环比较简单,增加一个变量或对象数组,记录在递归中发生变化的量即可。
  包括类似斐波那契数列的循环写法,使用两个变量记录f(n)和f(n-1)即可。

一般递归

  LeetCode 112题。

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and sum = 22,
递归转非递归的栈方法_第1张图片
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. 

  在Tree数据结构中,递归的方法用的很多。通常也是将当前节点的问题分解为其左子树和右子树两个子问题,再进行合并进行求解。
  Java递归代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root == null)
            return false;
        if(root.left == null && root.right == null && sum == root.val)
            return true;
        return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
    }
}

  递归的好处在于代码简洁,可读性强,容易维护。然而缺点往往更致命,在于其占用堆栈(尤其是堆)厉害。易导致内存溢出。因此,有时候需要将递归方法转变成非递归的方法。
  将一般非尾递归的方法转换成循环的方法,通常需要一个新的数据结构来代替Java内存结构中的栈。自然就是使用一样原理的stack数据结构。
  递归->循环:
  递归中发生变化的变量(递归返回值)->循环中每一次处理完相应变量存入stack中(push进栈)
  递归中使用递归返回值->循环中取出stack中的值进行处理(pop出栈)
  
  本题的非递归方法,起点和结束点不变。起点从根节点root开始(将root push进栈),结束于遍历完整棵Tree为止(所有对象pop出栈,栈为空,最后pop出栈的为root)。
  Java非递归代码如下:

public boolean hasPathSum(TreeNode root, int sum) {
    Stack  stack = new Stack<> ();        
    stack.push(root) ;      
    while (!stack.isEmpty() && root != null){
        TreeNode cur = stack.pop() ;    
        if (cur.left == null && cur.right == null){             
            if (cur.val == sum ) return true ;
        }
        if (cur.right != null) {
            cur.right.val = cur.val + cur.right.val ;
            stack.push(cur.right) ;
        }
        if (cur.left != null) {
            cur.left.val = cur.val + cur.left.val;
            stack.push(cur.left);
        }
    }       
    return false ;
}

  LeetCode 101. Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following [1,2,2,null,3,null,3] is not:
1
/ \
2 2
\ \
3 3
Note:
Bonus points if you could solve it both recursively and iteratively.

  Java递归代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public boolean isSymmetric(TreeNode root) {
    return root==null || isSymmetricHelp(root.left, root.right);
}

private boolean isSymmetricHelp(TreeNode left, TreeNode right){
    if(left==null || right==null)
        return left==right;
    if(left.val!=right.val)
        return false;
    return isSymmetricHelp(left.left, right.right) && isSymmetricHelp(left.right, right.left);//判断左子树的左子树与右子树的右子树,和 左子树的右子树与右子树的左子树 即可
}

  递归->循环:
  递归中发生变化的变量(递归返回值)->循环中每一次处理完相应变量存入stack中(push进栈)
  递归中使用递归返回值->循环中取出stack中的值进行处理(pop出栈)
  
  Java非递归代码如下:

public boolean isSymmetric(TreeNode root) {
    if(root==null)  return true;

    Stack stack = new Stack();
    TreeNode left, right;
    if(root.left!=null){
        if(root.right==null) return false;
        stack.push(root.left);
        stack.push(root.right);
    }
    else if(root.right!=null){
        return false;
    }

    while(!stack.empty()){
        if(stack.size()%2!=0)   return false;
        right = stack.pop();
        left = stack.pop();
        if(right.val!=left.val) return false;

        if(left.left!=null){
            if(right.right==null)   return false;
            stack.push(left.left);
            stack.push(right.right);
        }
        else if(right.right!=null){
            return false;
        }

        if(left.right!=null){
            if(right.left==null)   return false;
            stack.push(left.right);
            stack.push(right.left);
        }
        else if(right.left!=null){
            return false;
        }
    }

    return true;
}

你可能感兴趣的:(LeetCode,数据结构)