关于一类用简单迭代可以解答算法题的解法

有一类算法题,其实最简单的解法就是用简答迭代。但是,这不意味着这类算法题可以很容易被解答,关键在于对它的识别。一旦识别出,解答相对简单;但是一旦没有识别出,这类问题的解答不但麻烦,而且复杂度可能很高,达不到要求。举一个例子:

 

题目大意:一个字符串,不包含a, e, i, o, u的子字符串并满足一定长度要求则是我们想要的。题目给出若干字符串和长度要求,找出所有包含符合要求的子字符串的子字符串数量。比如:“quartz",长度要求:3. 则有如下子字符串满足要求:rtz, artz, uartz, quartz。一共四个。注意:因为rtz满足要求,artz即便包含了'a',但是只要它包含了一个满足要求的子字符串就满足我们的要求。

 

这是一道竞赛题。如果我们找到了一个满足要求的子字符串,并且该字符串左边有n个字符,右边有m个字符,则一共可以组成(n+1)*(m+1)个满足要求的字符串。但是如果对所有满足要求的子字符串这样计算并最后求和,则会有重复的情况。如果你想用排列组合的知识先求出所有的字符串在减去重复的,则不但很麻烦而且复杂度很高。

 

按照迭代的思路,先求出第一个满足要求的字符串并计算包含它的所有字符串数量,然后移动整个字符串开始的位置到这个子字符串的第一个字符后,再按照相同的思路寻找下一个满足要求的子字符串,不但复杂度很低(只有O(n * l)),而且程序很好些。比如我就可以一遍写对。代码如下:

const int fcn = 5; 
char fcs[fcn] = {'a', 'e', 'i', 'o', 'u'};
bool isOK(char c) {
    for (int i=0; i<fcn; i++) 
        if (c == fcs[i])
            return false;

    return true;
}


//
int main(int argc, char* argv[]) {
    srand(time(0));

    ifstream inf(argv[1]);

    string ln;  
    inf >> ln;

    int number = atoi(ln.c_str());

    for (int cases=0; cases<number; cases++) 
    {
        string s; 
        int l = 0; 
        inf >> s >> l; 
        vector<bool> v;
        v.resize(s.size()); 
        int tl = 0; 
        for (int i=s.size()-1; i>=0; i--) {
            if (isOK(s[i]) ) {
                tl++; 
            }
            else {
                tl = 0;
            }

            if (tl == l){
                v[i] = true;
                tl --; 
            }
            else {
                v[i] = false;
            }
        }

        __int64 r = 0, start = 0; 
        for (int i=0; i<s.size(); i++) {
            if (v[i]) {
                r += (i-start+1)*(s.size() - i - l + 1);
                start = i+1;
            }
        }

        // print result
        cout << "Case #" << (cases + 1) << ": " << r << endl;
    }

    return 0;
}


对于所有的算法问题,特别是应该是比较简单的算法问题,思考时一定不要让迭代方法逃出自己的大脑,而且应该第一步就考虑一下是否可以用迭代解决该问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值