字符串排序陷阱题

编写一个程序,将输入字符串中的字符按如下规则排序。

规则 1 :英文字母从 A 到 Z 排列,不区分大小写。 如,输入: Type 输出: epTy

规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。 如,输入: BabA 输出: aABb

规则 3 :非英文字母的其它字符保持原来的位置。 如,输入: By?e 输出: Be?y

注意有多组测试数据,即输入有多行,每一行单独处理(换行符隔开的表示不同行)

如果不考虑规则3, 那么就是一个简单的排序问题,对现有的稳定排序算法稍加改进都可以实现。所以第一眼看上去会觉得很简单,结果写完一测试,才发现没那么简单,最起码不像第一眼看到时所认为的那么简单。调试半天无果之后,痛定思痛,决定转变思路。

规则三之所以棘手,就在于,对于常规的稳定排序算法如插入排序,归并排序来说,不可避免地要移动元素,这和规则3直接矛盾,如果要实现原址排序,那么算法复杂性将大大增加。

所以,我决定放弃原址排序。先将字符串中的特殊字符剔除掉,将其索引保存在另一个容器中。将剔除掉特殊字符后所剩下来的字符串保存起来,再对这个字符串进行排序,最后再将它们重新组装起来。

为了满足规则1,对字符的大写形式进行排序,为了满足规则2,使用插入排序。为了避免多次调用toupper函数,我直接将大写形式保存在另一个字符串中,以空间换时间,用大写形式来做判断,当需要移动元素时,对两个字符串同时做移动。

最终代码如下:

#include 
#include 
#include 
#include 
#include 

void insert_sort(std::string &us, std::string &ls){
    assert(us.size() == ls.size());
    for(int i = 1; i < us.size(); ++i){
        int j = i - 1;
        char uc = us[i];
        char lc = ls[i];
        while(j >= 0 && us[j] > uc){
            us[j + 1] = us[j];
            ls[j + 1] = ls[j];
            j --;
        }
        us[j + 1] = uc;
        ls[j + 1] = lc;
    }
}
void sort_string(std::string &s){
    auto size = s.size();
    std::string us{};
    std::string ls{};
    std::vector special_char_index;
    for(int i = 0; i < size; ++i){
        if(std::isalpha(s[i])){
            ls.push_back(s[i]);
            us.push_back(std::toupper(s[i]));
        }else{
            special_char_index.push_back(i);
        }
    }
    insert_sort(us, ls);
    int idx = 0;
    for(int j = 0; j < size; ++j){
        if(std::find(special_char_index.begin(), special_char_index.end(), j) != std::end(special_char_index))
            continue;
        s[j] = ls[idx];
        ++idx;
    }
}
void sort_test(void){
    std::vector vs{};
    vs.push_back("Type");
    vs.push_back("BabA");
    vs.push_back("By?e");
    vs.push_back("ma?INt#Ain rEferE&Nce");
    vs.push_back("8+%n4C/mo Vf#EC&_Dg50y;qUJw5i8iu+BRCH+Ocnc/gTbk:fP");
    vs.push_back("P /]B)OJV3$Dyv|^ C4[iP&Aw2{WdWG_+y_BnDV*lSozey$s{2");
    vs.push_back("$U;V\"Gx8Ib %)M+nJ US:l3SfMJs%lj/xa#Ml2]=LfjRbaDO X");
    for(auto& s : vs){
        std::cout << s << std::endl;
        sort_string(s);
        std::cout << s << std::endl;
    }
}


int main(int argc, char **argv){
    sort_test();
    return 0;
}

 输出:

Type
epTy
BabA
aABb
By?e
Be?y
ma?INt#Ain rEferE&Nce
aA?cEe#Eef IimNnN&rrt
8+%n4C/mo Vf#EC&_Dg50y;qUJw5i8iu+BRCH+Ocnc/gTbk:fP
8+%B4b/CC Cc#cD&_Ef50f;ggHi5i8Jk+mnno+OPqR/TUuV:wy
P /]B)OJV3$Dyv|^ C4[iP&Aw2{WdWG_+y_BnDV*lSozey$s{2
A /]B)BCD3$dDe|^ G4[iJ&ln2{OoPP_+S_sVvV*wWWyyy$z{2
$U;V"Gx8Ib %)M+nJ US:l3SfMJs%lj/xa#Ml2]=LfjRbaDO X
$a;a"bb8Df %)f+GI JJ:j3jlllL%MM/Mn#OR2]=SSsUUVxx X

Process finished with exit code 0

你可能感兴趣的:(C++,算法,排序,c++,排序算法,字符串,算法)