字符串的左右移动

    给定一个字符串,这个字符串为*号和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]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值