개발조각

[프로그래머스] 문자열 내림차순으로 배치하기 본문

알고리즘🅰/프로그래머스

[프로그래머스] 문자열 내림차순으로 배치하기

개발조각 2022. 2. 18. 17:38
728x90
반응형

이번 문제는 뭐랄까 sort()가 왜 이렇게 정렬이 되는지 의문을 가지는 문제인 것 같아요.

이번에도 2가지 방법에 대해 설명해볼까 합니다.

 


해결방안

function solution(s) {
    // 버전1
    return s.split('').sort((a,b)=>{
        if (a < b) return 1;
        if (a > b) return -1;
        return 0;
    }).join('');
    
    // 버전2
    return s.split('').sort().reverse().join('');
}

 

이 문제는 문자열 s에 나타나는 문자를 큰 것부터 작은 순으로 정렬해 새로운 문자열을 리턴하는 문제입니다.

이번에도 역시 "정렬"이라는 단어가 나왔기 때문에 sort()를 써야 되는데

(전에도 말했지만 문제에서 정렬이라는 단어가 나오면 무조건 sort()를 써야 됩니다.)

 

sort() 메서드는 무조건 배열이나 객체에서만 사용이 가능해서 문자열을 배열로 만들어주고 정렬을 해주어야 됩니다.

그래서 sort()를 사용하기 위해 문자열s를 문자배열로 만들어주어야 되고 return해야되는 값이 문자열임으로 sort()로 정렬 후 문자열로 다시 만들어야 됩니다.

위에 설명을 코드로 쓰면 split(), sort(), join()메서드를 쓰게 되고

해결방안을 보시면 버전1, 버전2에서 split(), sort(), join()메서드를 공통적으로 써주었습니다.

 

해결방안 순서

  1. split()메서드를 사용해서 문자열s를 문자 하나하나로 쪼개어 배열로 만들어준다.
  2. sort()메서드를 사용해서 정렬을 한다.(이때 정렬방법을 해결방안 버전1, 버전2로 설명하겠습니다.)
  3. join()메서드를 사용해서 정렬된 문자배열을 다시 문자열로 합쳐줍니다.

 

전에 썼던 [프로그래머스] 비밀지도, [프로그래머스] 3진법 뒤집기에서 split()메서드와 join()메서드를 설명했었는데,

혹시나 [프로그래머스] 3진법 뒤집기, [프로그래머스] 비밀지도를 보고 싶다면 아래 링크에서 확인하시면 됩니다.👇

https://development-piece.tistory.com/9

 

[프로그래머스] 3진법 뒤집기

2021.11.05에 푼 문제입니다. 이 문제는 어려운 건 아닌데 검색하면 금방 풀 수 있어서 쉽게 풀 수 있었던 것 같아요. 해결방안 function solution(n) { return parseInt(n.toString(3).split('')..

development-piece.tistory.com

https://development-piece.tistory.com/14

 

[프로그래머스] 비밀지도

2021.12.08에 푼 문제입니다. 해결방안 function solution(n, arr1, arr2) { var answer = []; let arr1Bs = []; let arr2Bs = []; // arr1, arr2의 숫자를 2진법으로 만들고 #,공백으로 교체하기 for(let i=0; i..

development-piece.tistory.com

 

간단하게 split()메서드와 join()메서드는 설명하자면

MDN Web Docs
split()  메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.

구문 : str.split([separator[, limit]])

  • separator Optional
    원본 문자열을 끊어야 할 부분을 나타내는 문자열을 나타냅니다. 실제 문자열이나 정규표현식을 받을 수 있습니다. 문자열 유형의 separator가 두 글자 이상일 경우 그 부분 문자열 전체가 일치해야 끊어집니다. separator가 생략되거나 str에 등장하지 않을 경우, 반환되는 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우 str의 각각의 문자가 배열의 원소 하나씩으로 변환됩니다.
  • limit Optional
    끊어진 문자열의 최대 개수를 나타내는 정수입니다. 이 매개변수를 전달하면 split() 메서드는 주어진 separator가 등장할 때마다 문자열을 끊지만 배열의 원소가 limit개가 되면 멈춥니다. 지정된 한계에 도달하기 전에 문자열의 끝까지 탐색했을 경우 limit개 미만의 원소가 있을 수도 있습니다. 남은 문자열은 새로운 배열에 포함되지 않습니다.
// split 예제
var myString = 'Hello World. How are you doing?';
var splits = myString.split(' ', 3);
console.log(splits); //["Hello", "World.", "How"]

// limit를 안 쓸 경우
let mystring = 'Hello';
console.log(mystring.split('')); // [ 'H', 'e', 'l', 'l', 'o' ]

 

MDN Web Docs
join() 메서드는 배열의 모든 요소를 연결해 하나의 문자열로 만듭니다.

구문 : arr.join([separator])

  • separator Optional
    • 배열의 각 요소를 구분할 문자열을 지정합니다. 
    • 이 구분자는 필요한 경우 문자열로 변환됩니다. 
    • 생략하면 배열의 요소들이 쉼표로 구분됩니다. 
    • separator가 빈 문자열이면 모든 요소들이 사이에 아무 문자도 없이 연결됩니다.
// join예제
var a = ['바람', '비', '불'];
var myVar1 = a.join();      // myVar1에 '바람,비,불'을 대입
var myVar2 = a.join(', ');  // myVar2에 '바람, 비, 불'을 대입
var myVar3 = a.join(' + '); // myVar3에 '바람 + 비 + 불'을 대입
var myVar4 = a.join('');    // myVar4에 '바람비불'을 대입

여기까지 해결방안 순서의 1단계, 3단계에 대한 설명이었습니다.

이제 2단계에서 어떻게 정렬하느냐에 따라 버전 1, 버전 2로 설명하겠습니다.

해결방안

  1. sort()의 compare 함수의 형식의 내림차순으로 써서 해결하기
  2. sort().reverse() 를 써서 해결하기
s.split('')까지 실행하면

테스트 1 (s ="Zbcdefg")
return s.split(''); // ["Z","b","c","d","e","f","g"]

 

버전 1. sort()의 compare 함수의 형식의 내림차순으로 써서 해결하기

// 버전1. sort()의 compare 함수의 형식의 내림차순으로 써서 해결하기
return s.split('').sort((a,b)=>{
    if (a < b) return 1;
    if (a > b) return -1;
    return 0;
}).join('');

 

 

문제에서

"문자열 s에 나타나는 문자를 큰 것부터 작은 순으로 정렬해 새로운 문자열을 리턴하는 함수, solution을 완성해주세요.
s는 영문 대소문자로만 구성되어 있으며, 대문자는 소문자보다 작은 것으로 간주합니다."

라고 했습니다.

 

이 말은 

  • z~a Z~A

이 순으로 정렬하라는 말이 됩니다.

 

테스트 1 (s ="Zbcdefg")로 설명하자면 join()메서드를 사용하기 전까지 나와야 되는 값이

  • ["g","f","e","d","c","b","Z"]

임으로 단순하게 sort()로 내림차순 시키면 되겠다. 해서 써보았더니

  • sort((a,b)=>a-b); -> 오름차순
  • sort((a,b)=>b-a); -> 내림차순
// sort((a, b)=>b-a)를 사용해서 내림차순을 넣어보았다.

// 테스트 1 s="Zbcdefg"
return s.split('').sort((a,b)=>b-a); // ["Z","b","c","d","e","f","g"]

// 문자 정렬 적용해보기
const string1 = ['a', 'b', 'd', 'c'];
string1.sort((a,b)=>b-a);
console.log(string1); // ["a", "b", "d", "c"]

역시나 저 방법으로 쓰는 오름차순, 내림차순은 숫자에서만 적용이 가능하지 문자에서는 적용이 안됐습니다.

제 생각으로는 b-a부분에서 문자가 -를 해서 값이 나오지 않기 때문에 생기는 문제라고 생각합니다.

 

그래서 다른 방법인 compare 함수의 형식을 써서 구해보았습니다.

이 방법은 문자 정렬에서도 사용 가능하니 가능할 것 같다고 생각했습니다.

(대문자는 어떻게 정렬이 될지 의문을 가지면서)

// compare 함수의 형식의 오름차순, 내림차순 쓰는 법
// 오름차순
strings.sort(function (a, b) {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
});

// 내림차순
strings.sort(function (a, b) {
  if (a < b) return 1;
  if (a > b) return -1;
  return 0;
});

 

// compare 함수의 형식의 내림차순 사용해 보았습니다.

//테스트 1 s="Zbcdefg"
return s.split('').sort((a,b)=>{
    if (a < b) return 1;
    if (a > b) return -1;
    return 0;
}); // ["g","f","e","d","c","b","Z"]

역시 이 방법으로는 내림차순이 가능하더라고요!!

우연히 대문자도 얻어걸렸더라고요.😀

잘은 모르겠지만 sort()메서드 정렬에서는 내림차순으로 하면 소문자 다음에 대문자가 오나 봐요.

 

궁금증을 해결하기 위해

대문자, 소문자가 여러 개 있을 경우 compare 함수의 형식으로 썼을 때 오름차순과 내림차순을 둘 다 쓰면 어떤 결과가 나올까? 의문이 생겨서 써보았더니

// 대문자, 소문자가 여러개 있을 경우 어떻게 되는지 궁금해서 해보았습니다.

// 오름차순
let a = 'AabZcdeG'
let aa1 = a.split('').sort((a,b)=>{
    if (a > b) return 1;
    if (a < b) return -1;
    return 0;
}); // ['A', 'G', 'Z', 'a', 'b', 'c', 'd', 'e']

// 내림차순
let a = 'AabZcdeG'
let aa1 = a.split('').sort((a,b)=>{
    if (a < b) return 1;
    if (a > b) return -1;
    return 0;
}); // ['e', 'd', 'c', 'b', 'a', 'Z', 'G', 'A']

이렇게 됩니다.

즉 영문으로는 

  • 오른차순 : A~Z a~z
  • 내림차순 : z~a Z~A

이러한 순으로 진행이 된다는 것을 알 수 있습니다.

그래서 버전 1에서는 sort()메서드를 compare 함수의 형식의 내림차순을 사용해서 구해주었습니다.

 

버전 2. sort().reverse() 를 써서 해결하기

// 버전2. sort().reverse() 를 써서 해결하기
return s.split('').sort().reverse().join('');

버전2는 다른 사람의 풀이 보기에서 알아온 방법인데요.

그동안 sort()메서드를 쓸 때 sort()만쓰면 제출 후 채점하기에서 항상 오류가 나서 sort()만 쓴 적이 없는데

이번에는 왜 가능한지 의문이지만;;; 혹시 문자 배열은 괜찮은 거니???

 

궁금증으로 이것저것 예제를 만들어서 적용을 해보았는데요.

제가 알기로는 sort()만쓰면 오름차순으로 정렬이 되는 걸로 알고 있습니다.

// 영단어
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months); // ["Dec", "Feb", "Jan", "March"]

// 숫자
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1); // [1, 100000, 21, 30, 4]

// 대소문자
const string1 ="AabZcdeG";
console.log(string1.split('').sort()); // ["A", "G", "Z", "a", "b", "c", "d", "e"]

// //테스트 1 s="Zbcdefg"
return s.split('').sort(); // ["Z","b","c","d","e","f","g"]

이렇게 보면 영문자나 영단어에서는 정상적으로 오름차순이 되어있지만,

숫자 부분에서 보시면 정렬이 이상하게 되어있습니다.

아마 숫자 전체를 보는 것이 아니라 첫자리 순이 기준으로 돼서 그런지 이상하게 된 것 같습니다.

이렇게 sort()는 문자 오름차순에서는 사용해도 좋을 것 같아요.

 

그렇지만 지금 구해야 되는 건 내림차순을 구해야 되는데 sort()만 써서 오름차순이 되었습니다.

이걸 반대로만 바꾸면 원하는 답이 되는데

그래서 사용하는 것이 reverse() 메서드입니다.

 

MDN Web Docs
reverse() 메서드는 배열의 순서를 반전합니다. 첫 번째 요소는 마지막 요소가 되며 마지막 요소는 첫 번째 요소가 됩니다.

구문 : a.reverse()

const array1 = ['one', 'two', 'three'];
console.log('array1:', array1); // ["one", "two", "three"]

const reversed = array1.reverse();
console.log('reversed:', reversed); // ["three", "two", "one"]

console.log('array1:', array1); // ["three", "two", "one"]

 

sort().reverse()를 쓰면 문자배열이 내림차순으로 정렬하게 됩니다.


여기까지 프로그래머스 문자열 내림차순으로 배치하기 해결방안에 대해 설명해보았습니다.

728x90
반응형
Comments