给定一个字符串,这个字符串为*号和26个字母。现在需要把字符串的*号移动到左侧,字母移动到右侧,字母顺序不变。
*号和字母,其实可以用一个一元函数来泛华bool func(char ch)。
3个做法:
1)空间复杂度O(n)。就是开辟一个一样长度的数组,剩下的事情就是遍历,判断,移动。从两端同时开始移动。这能保证两个类型的字符都有序。
2)这种方法只能保证func(ch)为true的元素的有序性。
假设func(ch)=true的放左边,fun*ch)=false的放右边
设置两个游标i,j,都从开头向末尾遍历。
i用于寻找第一个func(ch)=false的元素,
j用于寻找第一个func(ch)=true且位于i右边的元素,
swap(i,j)
然后循环即可
伪代码:
while until end
find first func(i)==false
find first func(j)==true && j > i
swap(i,j)
代码:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void swap(char &a, char &b) {
char ch = a;
a=b;
b=ch;
}
bool isdash(char ch) {
return ch == '*';
}
void move(char *p, bool (*func) (char)) {
if (NULL == p || *p == '\0') {
return;
}
char *end = p + strlen(p) - 1;
char *i = end; // 第一个游标,用于寻找*
char *j = end; // 第二个游标,用于寻找非*字符
while (true) {
while (i >= p && *i != '*') {
--i;
}
if (i < p) {
break;
}
while (j >= p && (j >= i || *j == '*')) {
// 注意这里的j>=i
--j;
}
if (j < p) {
break;
}
swap(*i, *j);
}
}
void test(char *p) {
printf("[%s] -- ", p);
move(p, isdash);
printf("[%s]\n", p);
}
int main() {
{ char a[] = {"**fs**abc*"}; test(a); }
{ char a[] = {""}; test(a); }
{ char a[] = {"a"}; test(a); }
{ char a[] = {"*"}; test(a); }
{ char a[] = {"****"}; test(a); }
{ char a[] = {"abcde"}; test(a); }
{ char a[] = {"ab**cde*"}; test(a); }
{ char a[] = {"*ab**cde"}; test(a); }
{ char a[] = {"*abcdef**gh**ij*k*lm**nop"}; test(a); }
}
测试结果:
[fall@localhost ~]$ g++ test.cc -o po && ./po
[**fs**abc*] -- [*****fsabc]
[] -- []
[a] -- [a]
[*] -- [*]
[****] -- [****]
[abcde] -- [abcde]
[ab**cde*] -- [***abcde]
[*ab**cde] -- [***abcde]
[*abcdef**gh**ij*k*lm**nop] -- [*********abcdefghijklmnop]