递归写法总结

递归写法总结

问题描述

递归是算法中的一种很重要思想。好的递归程序逻辑清楚,代码简洁,有时候时间上也非常高效;此外链表、二叉树等结构用递归算法一般都有鲜明优势。
往往递归问题口头说起来感觉十分清晰顺畅;而用代码实现起来确总感觉层峦叠嶂,不知从何下手,思路也越来越混乱不堪。

几点总结

最近在解决一些算法相关的小问题时候,经常需要用到递归,有几点感悟。

  1. 递归的目标,时刻从要得到的结果\目标考虑。
  2. 当然,递归要把握住从本层到下一层的具体逻辑/代数关系。例如需要各层数值累加;本层的条件不足以判断需求的结果,还需要下一层的条件等。这一般是认为相对简单的。
  3. 代码中要有明确的在每一层传递变量返回结果;以使递归持续下去,同时能获取下一级的结果。
  4. 递归的终止条件。可能是数值超过给定的范围,可能是已经能判断出需要的结果。
  5. 递归到边界时候的写法统一到递归中。到达容器边界,也会导致递归终止,这就给程序终止带来一定的复杂性。把问题想明白了就很简单,因为在边界上除了有强行终止,还有递归条件目标的终止。
    1> 递归的每一层都可能是容器边界,从着手写代码就应该考虑。
    2> 列举所有可能的容器边界,判断个边界对应的返回结果。
    3> 除容器边界外的情况,都应当是可向下一步递归的。在这个情况下写出符合目标条件的递归关系式。

一个例子

对称树的判别

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

bool isSubSym(TreeNode* tr1,TreeNode* tr2)
{
    if(tr1==NULL&&tr2==NULL) return true;
    if((tr1==NULL&&tr2!=NULL)||(tr1!=NULL&&tr2==NULL)) return false;
    if(tr1!=NULL&&tr2!=NULL)
    {
        if(tr1->val==tr2->val)
            return isSubSym(tr1->left,tr2->right)&&isSubSym(tr1->right,tr2->left);
        else 
            return false;
    }    
}

bool isSymmetric(TreeNode* root)
{
    if(root==NULL || (root->left==NULL && root->right==NULL)) return true;
    TreeNode* tr1=root, * tr2=root;
    return isSubSym(tr1,tr2);    
}
  1. 考察对称树某对节点的数值是否相等还不足以判定是否为对称树,必须进一步判断以其为根的子树是否对称。
  2. 树只能从根节点往叶节点遍历,递归是很好的办法,可以回溯。
  3. 没有直接用 isSymmetric() 递归,因为向下一层判断的时候树根不一样。
  4. 判断两个子树是不是对称的 isSubSym() ,考虑到子树的所有可能情况:
    1> 两子树为空,或两子树都已经到了叶节点且数值相等,为对称树。(容器边界)
    2> 两子树一个为空,另一个不为空,非对称树。(容器边界)
    3> 两子树都不为空 >> 可以继续递归,当前层的条件不能充分得到判断结果。
    4> 两子树树根数值相等,向下递归,递归的时候按照对称的规则;数值不等,非对称树。(传递变量,终止条件)

你可能感兴趣的:(算法与编程)