牛客網字串排序程式設計題

detanx_墨鼬漓發表於2018-10-24

一、題目描述

編寫一個程式,將輸入字串中的字元按如下規則排序(一個測試用例可能包含多組資料,請注意處理)。

規則 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()方法,但方法也有侷限性,不要把思想也侷限了。

相關文章