首页 > 试题广场 >

字符串排序

[编程题]字符串排序
  • 热度指数:299272 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}对于给定的由可见字符和空格组成的字符串,按照下方的规则进行排序:
\hspace{23pt}\bullet\,按照字母表中的顺序排序(不区分大小写);
\hspace{23pt}\bullet\,同一字母的大小写同时存在时,按照输入顺序排列;
\hspace{23pt}\bullet\,非字母字符保持原来的位置不参与排序;
\hspace{15pt}直接输出排序后的字符串。

\hspace{15pt}字符串由 ASCII 码在 32126 范围内的字符组成。您可以参阅下表获得其详细信息。

../图片/可见字符集Ascii.png


输入描述:
\hspace{15pt}在一行上输入一个长度为 1 \leqq {\rm length}(s) \leqq 1000 ,由上表中的字符组成的字符串 s


输出描述:
\hspace{15pt}输出一个字符串,代表按照规则排序后的字符串。
示例1

输入

BabA

输出

aABb
示例2

输入

Hello NowCoder!

输出

CdeeH llNooorw!
将字符串中所有字母取出存储,然后排序,将排序后的字母数组替换到原字符串对应的字母位置。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextLine()) {
            String s = sc.nextLine();
            System.out.println(order(s));
        }
    }

    public static String order(String s) {
        int n = s.length();
        // 存储所有字母
        List<Character> list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (Character.isLetter(s.charAt(i))) {
                list.add(s.charAt(i));
            }
        }
        // 排序list
        list.sort(Comparator.comparingInt(Character::toLowerCase));
        // 拼接结果字符串
        StringBuilder sb = new StringBuilder();
        // 用于取字符数组
        int index = 0;
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (Character.isLetter(c)) {
                sb.append(list.get(index++));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}


发表于 2021-08-04 16:49:30 回复(0)
#include<iostream>

using namespace std;

int main(){
    string Message;
    while(getline(cin,Message)){
        string Removed = "";
        for(int i=0; i<Message.size(); i++){
            if(isalpha(Message[i])) Removed+=Message[i];
        }
        for(int i=0;i<Removed.size()-1;i++){
            for(int j=0; j<Removed.size()-i-1;j++){
                if(tolower(Removed[j])>tolower(Removed[j+1])) swap(Removed[j], Removed[j+1]);
            }
        }
        
        for(int i=0; i<Message.size(); i++){
            if(!isalpha(Message[i])){
                Removed.insert(i,1,Message[i]);
            }
        }
        
        cout<<Removed<<endl;
    }
}

发表于 2021-07-22 11:27:00 回复(0)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in=new Scanner(System.in);
		while(in.hasNext()){
			String str=in.nextLine();
			Character[] s=new Character[str.length()];
			int l=0;
			for(int i=0;i<str.length();i++){
				if((str.charAt(i)>='A'&&str.charAt(i)<='Z')||(str.charAt(i)>='a'&&str.charAt(i)<='z')){
					s[l]=str.charAt(i);
					l++;
				}
			}
			Arrays.sort(s,0,l,new Comparator<Character>(){
				public int compare(Character o1, Character o2) {
	                return Character.toLowerCase(o1) - Character.toLowerCase(o2);
	            }
			});
			int i=0;
			for(int j=0;j<str.length();j++){
				if((str.charAt(j)>='A'&&str.charAt(j)<='Z')||(str.charAt(j)>='a'&&str.charAt(j)<='z'))
					System.out.print(s[i++]);
				else
					System.out.print(str.charAt(j));
					
			}
            System.out.println();
		}
	}
}

发表于 2021-06-25 13:34:07 回复(0)
C++简洁代码
思路:
1 用一个vector1装原始字符,用vector2装纯字母字符
2 利用插入排序对vector2排序,插入排序最合适
3 循环遍历vector1,如果是字母字符,直接用vector2中字符替换,如果是非字母字符,保持不变
代码如下:
#include<iostream>
#include<vector>
using namespace std;
void m_sort(vector<char>&v)
{
    for (int i=1;i<v.size();i++)
    {
        int key = v[i];
        int j=i-1;
        while( j>=0 && tolower(v[j]) > tolower(key))
        {
            v[j+1] = v[j];
            j--;
        }
        v[j+1] = key;
    }
}
int main(void)
{

    char ch;
    vector<char>m_vector;
    vector<char>sort_vector;
    while(cin.get(ch))
    {
        //读取字符
        m_vector.push_back(ch);
        if(isalpha(ch))sort_vector.push_back(ch);
        if(ch=='\n')
        {
            //排序
            m_sort(sort_vector);
            //插入
            int j=0;
            for(int i=0;i<m_vector.size();i++)
            {
                if(isalpha(m_vector[i]))
                    m_vector[i]=sort_vector[j++];
            }
            //输出
            for(auto it:m_vector)cout << it;
            //清除
            m_vector.clear();
            sort_vector.clear();
        }
    }
    return 0;
}


发表于 2021-04-01 18:43:54 回复(0)
25行C++极短代码
#include <bits/stdc++.h>
using namespace std;
bool cmp(const char& c1,const char& c2){
    const char tmp1 = toupper(c1);
    const char tmp2 = toupper(c2);
    return tmp1<tmp2;
}
int main(){
    string s;
    while(getline(cin, s)){
        string ss="";
        map<int,char> mp;
        for(int i=0;i<s.size();i++){
            if(!isalpha(s[i])) mp[i] = s[i];
            else ss += s[i];
        }
        stable_sort(ss.begin(), ss.end(),cmp);
        for(auto p:mp){
            auto it = ss.begin()+p.first;
            ss.insert(it, p.second);
        }
        cout<<ss<<endl;
    }
    return 0;
}



编辑于 2021-03-29 21:47:24 回复(0)
先把字母字符拎出来组成列表,对其进行二次排序(首先全部转化为小写按字典序排,这样就忽略了大小写,字典序相同就按索引序,这样就保持了原来的顺序)。然后准备个空结果列表,遍历原始的字符串:如果当前字符是非字母,就直接加入列表,使其保持原来的位置;否则就从排好序的字母字符列表的队头弹出一个字母字符加入到结果列表中,保证字母字符按题意的顺序。
将结果列表中的字符拼接成字符串输出即可。
while True:
    try:
        s = input()
        str_list = [(i, c) for i, c in enumerate(list(s)) if c.isalpha()]
        sorted_list = sorted(str_list, key=lambda c: (c[1].lower(), c[0]))
        n = len(s)
        res = [""]*n
        startIdx = 0
        while startIdx < n:
            if s[startIdx].isalpha():
                # 这个位置在原来的位置上本来就是字母,就复制为排序后的字母
                res[startIdx] = sorted_list.pop(0)[1]
            else:
                # 否则此位置仍然是原来的字符
                res[startIdx] = s[startIdx]
            startIdx += 1
        print(''.join(res))
    except:
        break


编辑于 2021-03-21 15:51:06 回复(0)
从左往右冒泡排序:
1. 先从最后一个位置开始往前循环,判断该位置是否是字母,可以作为冒泡的最终目标位,直到找到字母才正式开始冒泡。
2. 从0开始确定left,遇到非字母的继续往右找,找到以后再向右找字母right。
3. 如果left大于right,交换,然后将right的位置赋值给left,继续循环步骤2。
import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String input;
        while ((input = reader.readLine()) != null) {
            int size = input.length();
            InputChar[] array = new InputChar[size];
            for (int i = 0; i < size; i++) {
                array[i] = new InputChar(input.charAt(i));
            }
            // 冒泡
            for (int target = size-1; target > 0; target--) {
                if (array[target].isAlphabet) {
                    // 冒泡目标位是字母,可交换
                    int left = 0;
                    int right = 0;
                    while (left < target) {
                        while (!array[left].isAlphabet && left < target) {
                            left += 1;
                        }
                        if (left == target) {
                            // 只剩target一个字母,直接结束
                            break;
                        }
                        right = left + 1;
                        while (!array[right].isAlphabet && right <= target) {
                            right += 1;
                        }
                        if (array[left].weight > array[right].weight) {
                            // 交换
                            InputChar temp = array[right];
                            array[right] = array[left];
                            array[left] = temp;
                            left = right;
                        } else {
                            // 不需要交换,往后移动1位继续循环找下一个字母
                            left += 1;
                        }
                    }
                }
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < size; i++) {
                sb.append(array[i].input);
            }
            System.out.println(sb.toString());
        }
    }
    
    public static class InputChar {
        public boolean isAlphabet = false;
        public int weight;
        public char input;
        public InputChar(char input) {
            this.input = input;
            if (input >= 65 && input <= 90) {
                // 大写字母
                this.isAlphabet = true;
                this.weight = input + 32;
            } else if (input >= 97 && input <= 122) {
                // 小写字母
                isAlphabet = true;
                this.weight = input;
            }
        }
    }
}


发表于 2021-03-18 02:32:25 回复(0)
#include <iostream>
using namespace std;
int main(){
    string s;
    while(getline(cin,s)){
        int len=s.size();
        for(int i=0;i<len-1;i++){
            for(int j=0;j<len-i-1;j++){
                if(tolower(s[j])>='a'&&tolower(s[j])<='z'){
                    int k=j+1;
                    while(!(tolower(s[k])>='a'&&tolower(s[k])<='z')&&k<=len-1) k++;
                    if(k==len) break;
                    if(tolower(s[j])>tolower(s[k]))
                        swap(s[j],s[k]);
                    j=k-1;
                }
            }
        }
        cout<<s<<endl;
    }
    return 0;
}//用了一个冒泡排序,感觉自己想复杂了QAQ


#include <iostream>
#include <vector>
using namespace std;

int main(){
    string s;
    while(getline(cin,s)){
        int len=s.size();
        vector<char> vec;
        for(int i=0;i<26;i++){
            for(int j=0;j<len;j++){
                if(s[j]=='a'+i||s[j]=='A'+i)
                    vec.push_back(s[j]);
            }
        }
        int k=0;
        for(int i=0;i<len;i++){
            if(tolower(s[i])>='a'&&tolower(s[i])<='z')
                cout<<vec[k++];
            else
                cout<<s[i];
        }
        cout<<endl;
    }
    return 0;
}//这个是仿照其他人的做法


编辑于 2021-02-28 13:52:03 回复(0)
纯C的噩梦 
#include "string.h"
#include <stdio.h>
#include <stdbool.h>
#include "stdlib.h"
char buf[1000]={0};
int k=0;
void trans( char *a) //把字符串里的字母按照规则1 2 排列放在buf里
{
    int len=strlen(a);
    int i,j;
    for (i=0;i<26;i++)
    {
        for (j=0;j<len;j++)
        {
            if (a[j]=='a'+i || a[j]=='A'+i)
            {
                buf[k++]=a[j];
            }
        }
    }
}

int main ()
{
    char str[1000];
    while (gets(str)!=NULL)
    {
        int len=strlen(str);
        int i,j=0;
        k=0;
        trans(str);
        for (i=0;i<len;i++)
        {
            if (islower(str[i]) || isupper(str[i])) printf("%c",buf[j++]); //是字母就输出buf里的
             else  printf("%c",str[i]); //规则3
        }
        printf("\r\n");
    }

}


发表于 2020-09-14 19:36:01 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()){
            List<String> list = Arrays.asList(scanner.nextLine().split(""));
            String[] alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
            int[] pointers = new int[26];
            char[] temp = new char[list.size()];
            char[] result = new char[list.size()];
            int prev = 0;
            for (int j = 0; j < alphabet.length; j++){
                int num = Collections.frequency(list,alphabet[j]);
                num += Collections.frequency(list,alphabet[j].toUpperCase());
                if (j < alphabet.length-1){
                    pointers[j+1] = prev + num;
                    prev += num;
                }
                    }
            for (int i = 0; i < list.size(); i++){
                if (!Character.isLetter(list.get(i).charAt(0))){
                    result[i] = list.get(i).charAt(0);
                }else{
                    int idx = (list.get(i).toLowerCase().charAt(0)) - 'a';
                    temp[pointers[idx]] = list.get(i).charAt(0);
                    pointers[idx] += 1;
                }
            }
            int iter = -1;
            for (char c : temp){
                while (iter < result.length-1){
                    iter += 1;
                    if (result[iter] == 0){
                        result[iter] = c;
                        break;
                    }
                }
            }
            System.out.println(String.valueOf(result));
        }
    }
}

发表于 2020-08-21 01:35:59 回复(0)
#include <stdio.h> 
#include <ctype.h>

int main(void)
{
    char s[1000];
    while(gets(s) != 0)
    {
        char alpha[1000];
        int pos = 0;

        for (int i = 0; i < 26; i++)
        {
            for (int j = 0; s[j] != '\0'; j++)
            {
                if (('A' + i) == toupper(s[j])) { alpha[pos++] = s[j]; }
            }
        }
        
        pos = 0;
        for (int i = 0; s[i] != '\0'; i++)
        {
            if (isalpha(s[i])) { s[i] = alpha[pos++]; }
        }
        
        printf("%s\n", s);
    }
    return 0;
}

发表于 2020-08-15 04:21:25 回复(0)
#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
bool cmp(const char a, const char b)
{
	return tolower(a) < tolower(b);
}
string sort1(string vec)
{
	stable_sort(vec.begin(), vec.end(), cmp);
	return vec;
}
int main()
{
	string str;
	while (getline(cin, str))
	{
		string vec="";
		for (int i = 0;i < str.size();i++)
		{
			if ((str[i] >= 'a'&&str[i] <= 'z') || (str[i] >= 'A'&&str[i] <= 'Z'))
			{
				vec += str[i];
			}
		}
		vec = sort1(vec);
		queue<char>q;
		for (int i = 0;i < vec.size();i++)
		{
			q.push(vec[i]);
		}
		for (int i = 0;i < str.size();i++)
		{
			if ((str[i] >= 'a'&&str[i] <= 'z') || (str[i] >= 'A'&&str[i] <= 'Z'))
			{
				str[i] = q.front();
				q.pop();
			}
		}
		cout << str << endl;

	}
	return 0;
}

发表于 2020-08-10 17:32:26 回复(0)

由于排序只针对字母进行,因此可以预先存储字母的下标,然后对该下标数组进行冒泡排序。当然,排序的内容不是下标数组的值,而是其指向的输入字符串的字符。根据规则2,得知排序算法还必须是稳定的。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const string transform_string(string str)
{
    vector<size_t> alpha_indexs;
    for (size_t i = 0; i < str.size(); ++i) {
        const char ch = str[i];
        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
            alpha_indexs.push_back(i);
        }
    }

    for (size_t i = 0; i < alpha_indexs.size(); ++i) {
        for (size_t j = 0; j < alpha_indexs.size()-1; ++j) {
            if (std::toupper(str[alpha_indexs[j + 1]])
                < std::toupper(str[alpha_indexs[j]])) {
                std::swap(str[alpha_indexs[j + 1]],
                          str[alpha_indexs[j]]);
            }
        }
    }

    return str;
}

int main()
{
    string line;
    while (getline(cin, line)) {
        cout << transform_string(line) << endl;
    }
    return 0;
}
编辑于 2020-04-06 17:10:15 回复(0)
while True:
    try:
        a = input()
        result = [False] * len(a)  #最终返回值,先初始化
        chr_list = []   #接受字母的列表
        for i,v in enumerate(a):
            if v.isalpha():
                chr_list.append(v)
            else:
                result[i] = v
        chr_list.sort(key= lambda x: x.lower()) #将有字母的列表按序排列(大写全变为小写,方便排列,如果字母相同不影响本来输入的数据的顺序)
        for i,v in enumerate(result):
            if not v:       #如果result列表索引i值为False,则将字母列表的数据添加
                result[i] = chr_list[0]     #将字母列表的数据一一导入最终列表
                chr_list.pop(0)     #每循环导入一个字母,删除字母列表第一个数据
        print(''.join(result))
    except:
        break
不是原创,学了大神的,自己理解慢慢做的,希望能融会贯通吧
编辑于 2020-03-23 00:22:41 回复(0)

字母按序入队列,然后输出的时候按原始串输出,遇符号输出原始串的符号,否则队列出队~

#include<queue>
(789)#include<iostream>
#include<string>

using namespace std;

int main() {
    string str;
    while(getline(cin, str)) {
        queue<char> qc;
        for(int i = 0; i < 26; ++i) {
            for(auto st : str) {
                if((st-'a' == i) || (st-'A' == i)) {
                    qc.push(st);
                }
            }
        }
        for(auto st : str) {
            if((st >= 'a' && st <= 'z') || (st >= 'A' && st <= 'Z')) {
                cout << qc.front();
                qc.pop();
            }
            else
                cout << st;
        }
        cout << endl;
    }

    return 0;
}
发表于 2020-02-21 19:44:25 回复(0)
用冒泡排序
#include <iostream>
using namespace std;
bool isChar(char ch){
    return (ch>='a'&&ch<='z') || (ch>='A' && ch <='Z');
}
int toInt(char ch){

    return ch>='A'&&ch <='Z'?ch-'A':ch-'a';
}
int main() {
    string str;
    while (getline(cin, str)){
        int lastSwap;
        int next, temp;
        for(int j=str.size()-1;j>0;j=lastSwap){
            lastSwap = 0;
            for(int i=0; i<j;i=next){
                if(isChar(str[i])){
                    next = i+1;
                    while (next<=j && !isChar(str[next])){
                        next++;
                    }

                    if(isChar(str[next]) && toInt(str[i])>toInt(str[next])){
                       temp = str[next];
                       str[next] = str[i];
                       str[i] = temp;
                       lastSwap = i;
                    }
                }
            }
        }

        cout << str << endl;
    }
    return 0;
}

编辑于 2020-01-12 00:12:35 回复(0)
对冒泡排序进行修改即可。
#include <iostream>
#include <string>
#include <cctype> //for isalpha()

using namespace std;

int main(){
    string input;
    while(getline(cin,input)){
        //对冒泡排序进行修改
        int len = input.size();        
        //最多len轮
        for(int i=0; i<len; i++){
            bool completed = false;
            
            //每一轮的结束位置不同
            for(int j=0; j<len-1-i; ){
                //注意这里下一轮的结束位置与原始冒泡排序不同
                while((j<len-1-i) && (!isalpha(input[j])) ){
                    //当不是字母时,直接跳过
                    j++;
                }
                
                int next = j+1;
                while((next<len-i) && (!isalpha(input[next])) ){
                    next++;
                }
                
                if(j>=len-1-i || next>=len-i){
                    break;
                }
                
                //若能运行到这里,则说明input[j]和input[next]均为字母
                if(tolower(input[j])>tolower(input[next])){
                    char temp = input[j];
                    input[j] = input[next];
                    input[next] = temp;
                    
                    completed = true; //该轮有元素交换
                }
                
                j++; //进行下一个字符的比较
            }
            
            //这一轮没有元素交换,说明排序已经完成
            if(!completed){
                break;
            }
        }
        
        cout<<input<<endl;
    }
}

发表于 2019-07-28 11:05:20 回复(0)
#include<iostream>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;
bool compare(const char &a1, const char &a2)
{
    return tolower(a1) < tolower(a2);
}
int main(){
    string s;
    while(getline(cin,s)){
    string c;
    
    for(int i=0;i<s.size();i++){
        if(toupper(s[i])>='A'&&toupper(s[i])<='Z')
            c.push_back(s[i]);
    }
    stable_sort(c.begin(),c.end(),compare);
    string::iterator ite=c.begin();
    for(int i=0;i<s.size();i++){
        if(toupper(s[i])>='A'&&toupper(s[i])<='Z')
            cout<<*ite++;
        else cout<<s[i];
    }
        cout<<endl;
    }
}

发表于 2019-07-07 23:34:08 回复(0)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

bool mysort(char a,char b) //由于大小写顺序不变,所以全部按照小写排序
{
    return (tolower(a)<tolower(b));
}

int main()
{
    string strIn;
    while(getline(cin,strIn))
    {
        string alphaStr;
        for(char c:strIn)
        {
            if(isalpha(c)) alphaStr.push_back(c);
        }
        stable_sort(alphaStr.begin(),alphaStr.end(),mysort); //稳定排序
        for(int i=0,j=0;i<strIn.size();++i) //如果是字母则输出alphaStr,否则输出strIn
        {
            if(isalpha(strIn[i]))
            {
                cout<<alphaStr[j];
                j++;
            }
            else
                cout<<strIn[i];
        }
        cout<<endl;
    }
    return 0;
}
主要思路是先把输入字符串strIn中的所有字母另存到一个字符串alphaStr中,并对这个字符串排序,最后遍历strIn,如果遇到字母就输出alphaStr中的字符,否则输出strIn中的字符。关键是在排序上,这里的排序没必要自己写,由于题目要求同一个字母的大小写保持原来的顺序,所以用stable_sort+自定义排序方式实现不区分大小写的稳定排序。
编辑于 2019-04-09 10:51:47 回复(0)
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

void swap(char &a, char &b) {
    char temp = a;
    a = b;
    b = temp;
}

void Insert_sort(vector <char> &char_s) {
    for(int i = 1; i < char_s.size(); i++){
        for(int ii = i; ii > 0; ii --) {
            if(toupper(char_s[ii]) < toupper(char_s[ii - 1])) {
                swap(char_s[ii], char_s[ii - 1]);
            }
            else {
                break;
            }
        }
    }
}

int main() {
    string str_in;
    while(getline(cin, str_in)){
        vector <char> char_s;
        for(int i = 0; i < str_in.length(); i++) {
            if(isalpha(str_in[i])) {
                char_s.push_back(str_in[i]);
            }
        }
        Insert_sort(char_s);
        for(int i = 0; i < str_in.length(); i++) {
            if(!isalpha(str_in[i])) {
                cout << str_in[i];
            }
            else{
                cout << char_s[0];
                char_s.erase(char_s.begin());
            }
        }
        cout << endl;
    }
    system("pause");
    return 0;
}
//保持非字母符号位置不变 vector
//排序保持稳定性 同字母大小写顺序一致 插入排序 Insert Sort
发表于 2018-10-10 12:33:53 回复(0)

问题信息

难度:
965条回答 82729浏览

热门推荐

通过挑战的用户

查看代码
字符串排序