• LeetCode 856 递归思路详解


    1. 题目描述

    给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

    • () 得 1 分。
    • AB 得 A + B 分,其中 A 和 B 是平衡括号字符串。
    • (A) 得 2 * A 分,其中 A 是平衡括号字符串。

    示例 1:

    输入: "()"
    输出: 1
    

    示例 2:

    输入: "(())"
    输出: 2
    

    示例 3:

    输入: "()()"
    输出: 2
    

    示例 4:

    输入: "(()(()))"
    输出: 6
    

    提示:

    S 是平衡括号字符串,且只含有 ( 和 ) 。

    2 <= S.length <= 50

    2.思路过程

    根据题目,我们明显知道这个题百分之一万是要使用递归的思想了,但是递归的思想需要把握一个很细粒度的问题,就是怎么判断每个递归的子问题。然后这些子问题一个一个进行迭代(入栈出栈)计算,最后解决问题,这正是递归重点,也正是难点。(听我装一会儿ACD吧,mua~)

    首先,我们定义一个子串的概念:

    我们从字符串(...)开始往栈里面压,当遇到对称的符号时(即stack.top()是‘(’,下一个字符是‘)’的时候),就pop出这个元素,正好栈为空的时候,我们称之为子串(...)。例如(());();((())());

    这样的话,我们可以将所有的问题都转化为子串(...)的组合:

    例如:

    (())()是两个子串(...)(...)相加,A+B的情况。

    (()(()))也是一个子串(...)。

    我们可以发现一个特点:子串的第一个符号’(‘和最后一个符号‘)’永远是匹配的一对括号。

    这样的话,就可以将整个问题划分为以下几个子问题:

    1. 判断S有几个子串(...),让这些子串的分数相加即可。
    2. 然后子串里面有可能又是若干个子串的相加情况,例如(()()),我们就让2*()()

    明白了以上的递归的小问题之后,我们就可以进行下手写代码了,先把自己的代码运行情况晒一下,性能不是太好,毕竟自己学识短浅,只能写到这样的程度了,同时也证明一下自己不是胡编乱造。嘻嘻。

     

    3.代码实战

    两个方法:

    • scoreOfParentheses(string S)用来判断一个字符串里面有几个子串。让这些子串的分数相加就可以了。
    • countScore()传入的参数永远是子串(...),与前面分析一样,必须保证子串的第一个左括号和子串最后一个右括号永远是保持一对的这个特征。只有这样的话,return 2*scoreOfParentheses(S1.substr(1,S1.size()-2));这句话才可正常执行,他目的就是剥去第一个和最后一个括号,将子串里面的字符串交给scoreOfParentheses()方法来判断,子串里面是不是还有子串相加的情况。

    这样两个方法相互递归。相互配合就将整个问题转化为:

    子串+子串:分数相加

    子串嵌套子串:2*子串

    然后over!

    具体还有看代码,欢迎关注,欢迎来撩!

    class Solution {
    public: 
    
        //该方法用于处理一个子串,也就是栈可pop为empty中的情况
        int countScore(string S1)
        {
            if(S1.size()==2)
            {
                return 1;
            }
            else{
                char ch=S1[0];//S1[0]肯定是'('
                if(S1[1]==')')
                {
                    //这是()的情况
                    return 1+scoreOfParentheses(S1.substr(2,S1.size()-2));
                }
                else{
                /*”((“的情况,由于S1本身传进来的时候就是一个子串,也就是不含A+B这种情况。所以还要检查里面是不是还有各个子串相加的问题.*/
                    return 2*scoreOfParentheses(S1.substr(1,S1.size()-2));
                }
            }
            
        }
      
    
        //遍历一个字符串,看看有多少个A+B的情况,例如串(())()中(())和()就是两个子串
        int scoreOfParentheses(string S) //遍历整个串,看一个串能够分成多少个子串
        {
            int total_score=0;
            stack<char> sta1;
            int i1=0;//用于记录子串的开始位置,
            int i2=0;//i2用于记录子串的结束位置,i2-i1+1就只子串的长度,可以用来截取子串。
            
            while(i2<=S.size()-1)
            {
                sta1.push(S[i2]);//插入的肯定是‘(’
                while(!sta1.empty())//不空
                {
                    i2++;
                    if(S[i2]=='(')
                    {
                        sta1.push(S[i2]);
                    }
                    else
                    {
                        int top=sta1.top();
                        sta1.pop();
                    }
                }//空了之后,说明一个子串(i1<->i2)遍历完毕,记录指针i,然后将指针数据传送给countScore()进行计算子串。
                total_score+=countScore(S.substr(i1,i2-i1+1));
                i2++;
                i1=i2;
            }
            return  total_score;
        }
    };
    
    斯是陋室惟汝德馨!欢迎来访!
  • 相关阅读:
    101个微软提供的Visual Studio 2005示例[转贴]
    验证码的三种做法[纯数字][纯汉字][字母\数字\汉字混合]C#
    XML做数据库操作之 我浑了
    推荐几个用得上且免费的 .NET控件
    一些怪得你没想过的软件,大多还是有用的!
    ASP.NET 程序中常用的三十三种代码[转载与 aspcool]
    js入门系列演示·数组
    AJAX!?!入门之道
    js入门·移动窗体/弹出提示
    javascript入门系列演示·函数的定义以及简单参数使用,调用函数
  • 原文地址:https://www.cnblogs.com/yuanmh/p/10091234.html
Copyright © 2020-2023  润新知