본문 바로가기
TIL/Programmers

[TIL] 2023.05.06 Programmers_문자열 내 마음대로 정렬하기

by heereal 2023. 5. 6.

Today I Learned

  • Programmers 문제 풀기

 


Programmers 문제 풀기

문자열 내 마음대로 정렬하기

문제 설명

문자열로 구성된 리스트 strings와, 정수 n이 주어졌을 때, 각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하려 합니다. 예를 들어 strings가 ["sun", "bed", "car"]이고 n이 1이면 각 단어의 인덱스 1의 문자 "u", "e", "a"로 strings를 정렬합니다.

 

 

입출력 예

strings n return
["sun", "bed", "car"] 1 ["car", "bed", "sun"]
["abce", "abcd", "cdx"] 2 ["abcd", "abce", "cdx"]

입출력 예 1
"sun", "bed", "car"의 1번째 인덱스 값은 각각 "u", "e", "a"입니다. 이를 기준으로 strings를 정렬하면 ["car", "bed", "sun"]입니다.

 

입출력 예 2
"abce"와 "abcd", "cdx"의 2번째 인덱스 값은 "c", "c", "x"입니다. 따라서 정렬 후에는 "cdx"가 가장 뒤에 위치합니다. "abce"와 "abcd"는 사전순으로 정렬하면 "abcd"가 우선하므로, 답은 ["abcd", "abce", "cdx"]입니다.

 

 

나의 1차 풀이

function solution(strings, n) {
    let answer = [];
    let index = strings.sort().map((word) => word.split("")[n]);
    let sorted = [...index].sort();
    for (const i in strings) {
        answer.push(strings[index.indexOf(sorted[i])])
    }
    return answer;
}

strings에서 각 요소의 n번째 글자만 뽑아서 배열을 만든 후에, for문을 돌려서 indexOf로 순서대로 배열에 push 해주려고 했다. 그런데 문제점은 입출력 예 2번과 같이 n번째 인덱스 값이 "c", "c", "x"로 문자열이 중복되는 경우 indexOf는 일치하는 첫 번째 인덱스만 반환하기 때문에 원하는 대로 답이 출력되지 않는다.

 

indexOf가 동일한 인덱스를 출력했기 때문에 "abcd"가 두 번 들어가서 풀이를 통과하지 못했다.

 

 

나의 2차 풀이

function solution(strings, n) {
    let answer = [];
    let index = strings.sort().map((word) => word.split("")[n]);
    let sorted = [...index].sort();
    for (const i in strings) {
        if (sorted[i-1] === sorted[i]) answer.push(strings[index.indexOf(sorted[i], i)])
        else answer.push(strings[index.indexOf(sorted[i])])
    }
    return answer;
}

indexOf 메서드에 두 번째 파라미터로 fromIndex를 넣을 수 있다는 점을 이용해서 if문으로 indexOf로 동일한 인덱스를 출력하는 경우에 예외처리를 해주었다. 근데 여전히 테스트 케이스 12개 중에 3개밖에 통과하지 못했다.

 

 

나의 최종 풀이

function solution(strings, n) {
  let answer = strings.sort((a,b) => {
      if (a[n] > b[n]) return 1;
      if (a[n] < b[n]) return -1;
      if (a[n] === b[n] && a > b) return 1;
      if (a[n] === b[n] && a < b) return -1;
  })  
  return answer
}

도대체 어디가 문제인지 알 수 없어서 아예 풀이 방법을 바꿔봤다. sort 메서드에 compareFunction을 이용해서 배열 정렬하기. a와 b가 동일한 경우에 예외처리를 추가했다. sort 메서드에 파라미터로 넘기는 함수를 직접 작성하는 방법은 처음 사용해 봤는데 생각보다 어렵지 않아서 그동안 괜히 겁먹었다 싶었다. 

 

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

출처 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

 

 

다른 사람의 풀이 01

function solution(strings, n) {
    return strings.sort((s1, s2) => s1[n] === s2[n] ? s1.localeCompare(s2) : s1[n].localeCompare(s2[n]));
}

n번째 문자가 동일한 경우에는 문자열 자체를 비교하고, n번째 문자가 동일하지 않다면 n번째 문자열 자체를 비교한다. 와우... localeCompare라는 메서드는 이번에 처음 알게 됐음!

 

// "a"는 "c" 전에 위치하므로 음수 값을 반환
'a'.localeCompare('c'); // -2 혹은 -1 (또는 다른 음수 값)

// 알파벳 순으로 단어 "check"는 "against"보다 뒤에 위치하므로 양수 값을 반환
'check'.localeCompare('against'); // 2 혹은 1 (또는 다른 양수 값)

// "a"와 "a"는 서로 동등하므로 중립 값 0을 반환
'a'.localeCompare('a'); // 0

 

 

다른 사람의 풀이 02

function solution(strings, n) {
    return strings.sort().sort((a,b) => a.charCodeAt(n)-b.charCodeAt(n));
}

strings를 먼저 알파벳순으로 sort 한 다음에 charCodeAt 메서드를 이용해서 각 단어의 인덱스에 접근해서 인덱스순으로 다시 sort 한다.

 

const sentence = 'The quick brown fox jumps over the lazy dog.';

const index = 4;

console.log(`The character code ${sentence.charCodeAt(index)} is equal to ${sentence.charAt(index)}`);
// Expected output: "The character code 113 is equal to q"

 

 

 

댓글