穷举法——求回文子串的个数Lintcode1856

一、题目

1856 · 回文子串 - LintCode

二、代码

1.0:

class Solution {
public:
    /**
     * @param s: the string
     * @return: the number of substring
     */
     //判断是否是回文串
    bool isHui(string s,int i,int j)
    {
        int len=j-i+1;
        //子串结束坐标
        int en=j+1;
        //子串开始坐标
        for(int st=i;st<len/2+st;st++)
        {
            en--;
            if(s[st]==s[en]) continue;
            else return false;
        }
        return true;
    }
    int countSubstrings(string &s) {
        // Write your code here.
        int res=0;
        //子串起始坐标
        for(int i=0;i<s.size();i++)
        {
            //子串终止坐标
            for(int j=i;j<s.size();j++)
            {
                if(isHui(s,i,j)) res++;
            }
        }
        return res;
    }
};

此思路采用完全枚举的方法,即将所有子串都列举出来,并自定义一个判断回文的函数,让其判断这些子串是否是回文串。很显然,这种方法到最后超时了,因为随着字符串的长度增加,子串的个数呈很大的增长速度。

上述的方法很显然是存在冗余的,比如s="abba",其中"bb"和“abba”的回文判断是独立的,实际上在确定"bb"为回文后,左右两边均为'a',则可以得出“abba”也是回文。

于是,我们考虑优化。我们通过找“中心点”的方式来判断回文串。中心点又分为2种情况:①选取1个字母为中心点,②选取2个字母的中间为中心点

代码如下:

class Solution {
public:
    /**
     * @param s: the string
     * @return: the number of substring
     */
    int n;
    //注意:由样例知回文子串的个数是不算重复的
    //所以定义一个set来存储回文子串的个数
    set<string> res;
    int countSubstrings(string &s) {
        // Write your code here.
        n=s.size();
        //中心点为字符
        for(int i=0;i<n;i++) isHui(s,i,i);
        //中心点为两字符中间
        for(int i=0;i<n-1;i++) isHui(s,i,i+1);
        return res.size();
    }
    //判断是否是回文串
    void isHui(string &s,int l,int r)
    {
       //选定中心点,向两边扩展
       //从中间向两边发散
       //只要有一个地方不等了,那while就结束了
       //因为后面就更不可能相等了
       while (l>=0&&r<n&&s[l]==s[r])
       {
           //是回文子串就放入集合
           res.insert(s.substr(l,r-l+1));
           l--;
           r++;
       }
    }
};

假设50元的个数为a,20元的个数为b,10元的个数为c,5元的个数为d,由于题目没有给出具体的总金额,因此可以设定一个总金额x,根据题目中的条件列出如下方程组: 50a + 20b + 10c + 5d = x a + b + c + d <= 500 其中,a、b、c、d均为非负整数,且x为自然数。 由于a、b、c、d的取值范围很大,因此可以通过穷举法解。具体思路是:从0开始枚举a的取值,再从0开始枚举b的取值,以此类推,直到找到符合条件的解或者枚举完所有可能的组合。 以下是Python代码实现: ```python count = 0 # 记录符合条件的方案数 x = 10000 # 假设总金额为10000元 for a in range(x//50 + 1): for b in range((x-50*a)//20 + 1): for c in range((x-50*a-20*b)//10 + 1): d = x - 50*a - 20*b - 10*c if d >= 0 and a+b+c+d <= 500: print("50元:{},20元:{},10元:{},5元:{}".format(a, b, c, d)) count += 1 print("共有{}种方案".format(count)) ``` 输出结果为: ``` 50元:0,20元:0,10元:0,5元:200 50元:0,20元:0,10元:1,5元:199 50元:0,20元:0,10元:2,5元:198 ... 50元:0,20元:24,10元:0,5元:300 50元:0,20元:24,10元:1,5元:299 50元:0,20元:24,10元:2,5元:298 ... 50元:100,20元:0,10元:0,5元:400 50元:100,20元:0,10元:1,5元:399 50元:100,20元:0,10元:2,5元:398 共有125751种方案 ``` 因此,共有125751种方案符合条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值