牛客网字符串排序编程题

一、题目描述

编写一个程序,将输入字符串中的字符按如下规则排序(一个测试用例可能包含多组数据,请注意处理)。

规则 1 :英文字母从 A 到 Z 排列,不区分大小写。

如,输入: Type 输出: epTy

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

如,输入: BabA 输出: aABb

规则 3 :非英文字母的其它字符保持原来的位置。

如,输入: By?e 输出: Be?y

样例:

输入:

A Famous Saying: Much Ado About Nothing(2012/8).

输出:

A aaAAbc dFgghh : iimM nNn oooos Sttuuuy (2012/8).

示例1

输入

A Famous Saying: Much Ado About Nothing (2012/8).
#$Y^!#Pf&~#FUyTtAfZhCs&Dly%M@(muOI@Le^mydvc((w$x-cP&t-f$R%CCp)bCck@P-ag

输出

A aaAAbc dFgghh: iimM nNn oooos Sttuuuy (2012/8).
#$A^!#ab&~#CccCCCcDdef&Fff%g@(hIkl@LM^mmOPP((p$P-Rs&T-t$t%Uuv)wxYy@y-yZ

二、解题思路

1、思路一:字符串分割

  对字符串分割,记录非字母位置和单词长度,再对字母排序,排序后按照单词长度分割,并非字母位置插入相应字符

  最后发现不可行,原因,操作过于繁琐且空间消耗过高,输入不为单词字符串时,问题较多,输入存在用例如下:#$Y^!#Pf&~#FUyTtAfZhCs&Dly%M@(muOI@Le^mydvc((w$x-cP&t-f$R%CCp)bCck@P-ag

2、思路二:字母替换

  将字符串中所有的大小写字符存入一个数组中,将数组排序,然后遍历字符串,当为字母时从数组中获取,并下标后移一位

  难点:所有的字母并不是按照常规排序,而是需要保留原来字符串中的顺序,且从A-Z排序

  尝试一、使用数组的sort()方法,排序结果无法保留原始相同字母的相对位置,且大写字母在前,小写在后

原始:["Y","y","y","y","P","P","p","P","f","F","f","f","U","u","T","t","t","A","a","Z","h","C","c","c","C","C","C","c","s","D","d","l","L","M","m","m","O","I","e","v","w","x","R","b","k","g"]
结果:["A", "C", "C", "C", "C", "D", "F", "I", "L", "M", "O", "P", "P", "P", "R", "T", "U", "Y", "Z", "a", "b", "c", "c", "c", "d", "e",
"f", "f", "f", "g", "h", "k", "l", "m", "m", "p", "s", "t", "t", "u", "v", "w", "x", "y", "y", "y"]

  

  尝试二、在存入字母时对相同字母保持相对位置不变存入数组,再使用arr.sort(function(a,b){return a.toLocaleLowerCase()>=b.toLocaleLowerCase()?1:-1;});排序,排序结果部分保留相对位置,任然有些字母的相对位置发生了变化

let upper = str[i].toLocaleUpperCase();
            let lower = str[i].toLocaleLowerCase();
            if(strArray.indexOf(upper) !== -1 || strArray.indexOf(lower) !== -1) {
               let subscript1 = strArray.lastIndexOf(upper);
               let subscript2 = strArray.lastIndexOf(lower);
               let subscript = Math.max(subscript1,subscript2)
               strArray.splice(subscript+1,0,str[i])
            }else {
               strArray.push(str[i])
            }
原始:["Y","y","y","y","P","P","p","P","f","F","f","f","U","u","T","t","t","A","a","Z","h","C","c","c","C","C","C","c","s","D","d","l","L","M","m","m","O","I","e","v","w","x","R","b","k","g"]
结果:["a", "A", "b", "c", "c", "C", "C", "c", "C", "C", "d", "D", "e", "f", "F", "f", "f", "g", "h", "I", "k", "l", "L", 
"M", "m", "m", "O", "P", "P", "P", "p", "R", "s", "t", "T", "t", "U", "u", "v", "w", "x", "Y", "y", "y", "y", "Z"]

  

  尝试三、在存入时使用二维数组,每个子数组的第二个值存放0,1标识当前字母的大小写,存入时全部存小写,然后使用sort()方法排序,结果sort()方法排序会先取数组的第一个值排序,再取第二个值排序,所以排序后即使在将大写转换回来,但相对字母的顺序发生了变化,相同字母在一起,但大写在前小写在后

原始:["Y","y","y","y","P","P","p","P","f","F","f","f","U","u","T","t","t","A","a","Z","h","C","c","c","C","C","C","c","s","D","d","l","L","M","m","m","O","I","e","v","w","x","R","b","k","g"]
结果:A,a,b,C,C,C,C,c,c,c,D,d,e,F,f,f,f,g,h,I,k,L,l,M,m,m,O,P,P,P,p,R,s,T,t,t,U,u,v,w,x,Y,y,y,y,Z 

  思考:自己陷入了误区,字母数组的序列必须用sort()方法来实现

  尝试四、创建26个大写字母的数组,使用for循环去循环遍历所存的字符串的字母的数组,依次从A-Z去判断,存在就放入一个新的数组,这样数组从A-Z进行了排序,字母的相对位置也没有发生变化

 var character = new Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
    for(let s=0;s < character.length;s ++)
    {
        for(let k = 0;k < strArray.length; k ++) {
            if(character[s] === strArray[k] || character[s].toLocaleLowerCase() === strArray[k]) {
                resultArray.push(strArray[k])
            }
        }
    }

  

原始:Y,P,f,F,U,y,T,t,A,f,Z,h,C,s,D,l,y,M,m,u,O,I,L,e,m,y,d,v,c,w,x,c,P,t,f,R,C,C,p,b,C,c,k,P,a,g
结果:A,a,b,C,c,c,C,C,C,c,D,d,e,f,F,f,f,g,h,I,k,l,L,M,m,m,O,P,P,p,P,R,s,T,t,t,U,u,v,w,x,Y,y,y,y,Z

三、完整代码

let resultArr = []
while(lines = readline()) {
    resultArr.push(changeString(lines))
}
console.log(resultArr.join("
"))
function changeString(str) {
    var strArray = [],resultArray = []
    for(let i = 0;i < str.length;i ++) {
        if(/[A-Za-z]/.test(str[i])) {
            strArray.push(str[i])
        }
    }
    var character = new Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
    for(let s=0;s < character.length;s ++)
    {
        for(let k = 0;k < strArray.length; k ++) {
            if(character[s] === strArray[k] || character[s].toLocaleLowerCase() === strArray[k]) {
                resultArray.push(strArray[k])
            }
        }
    }
    let index = 0,newstr = "";
    for(let j = 0;j < str.length;j ++) {
        if(/[A-Za-z]/.test(str[j])) {
            newstr += resultArray[index];
            index ++
        }else {
            newstr += str[j]
        }
    }
    return newstr
}

四、总结

  1、在看问题时要发现问题的关键点,例如本题中的关键点:字母排序,大小写相对位置不变,非字母位置不变;

  2、多尝试、发现总结问题,这个方法不行是为什么?哪儿出错了?针对问题寻找其他方法;

  3、不要陷入知识误区,例如本题中的排序,一想到排序就想到使用sort()方法,但方法也有局限性,不要把思想也局限了。

原文地址:https://www.cnblogs.com/detanx/p/niuCodeTest1.html