您的位置:首页 > 其它

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

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

题目大意:一个字符串,不包含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;
}


对于所有的算法问题,特别是应该是比较简单的算法问题,思考时一定不要让迭代方法逃出自己的大脑,而且应该第一步就考虑一下是否可以用迭代解决该问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: