[코딩테스트] 프로그래머스 튜플 문제 | Map 값 가져오기, 리스트 정렬

Bluewave·2024년 3월 28일

코테공부_java

목록 보기
14/99
post-thumbnail

문제

사이트문제레벨정답률
프로그래머스튜플Lv.263%

✏️ 문제 바로가기

셀수있는 수량의 순서있는 열거 또는 어떤 순서를 따르는 요소들의 모음을 튜플(tuple)이라고 합니다. n개의 요소를 가진 튜플을 n-튜플(n-tuple)이라고 하며, 다음과 같이 표현할 수 있습니다.

(a1, a2, a3, ..., an)
튜플은 다음과 같은 성질을 가지고 있습니다.

중복된 원소가 있을 수 있습니다. ex : (2, 3, 1, 2)
원소에 정해진 순서가 있으며, 원소의 순서가 다르면 서로 다른 튜플입니다. ex : (1, 2, 3) ≠ (1, 3, 2)
튜플의 원소 개수는 유한합니다.
원소의 개수가 n개이고, 중복되는 원소가 없는 튜플 (a1, a2, a3, ..., an)이 주어질 때(단, a1, a2, ..., an은 자연수), 이는 다음과 같이 집합 기호 '{', '}'를 이용해 표현할 수 있습니다.
{{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}}
예를 들어 튜플이 (2, 1, 3, 4)인 경우 이는
{{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}
와 같이 표현할 수 있습니다. 이때, 집합은 원소의 순서가 바뀌어도 상관없으므로
{{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}
{{2, 1, 3, 4}, {2}, {2, 1, 3}, {2, 1}}
{{1, 2, 3}, {2, 1}, {1, 2, 4, 3}, {2}}
는 모두 같은 튜플 (2, 1, 3, 4)를 나타냅니다.

특정 튜플을 표현하는 집합이 담긴 문자열 s가 매개변수로 주어질 때, s가 표현하는 튜플을 배열에 담아 return 하도록 solution 함수를 완성해주세요.

시행착오

우선 나는 튜플 요소를 분리한 뒤, 집합 원소의 개수대로 오름차순 정렬을 하여 큐에 저장하였다. 그리고 앞에서부터 하나씩 저장을 해나가는데, 앞에서 저장한 수는 전부 제외하면 그 다음에 저장할 수가 하나 남는다. 그 규칙을 활용해서 하나씩 배열에 저장해나갔다.

그런데 코드가 너무 복잡하고 길다는 걸 깨달았다 ..
그래서 또 다른 방법이 있나? 하고 gpt에게 물어보았더니, 엄청나게 짧고 효율적인 규칙을 알려주었다.

예시 코드

import java.util.*;

class Solution {
    public int[] solution(String s) {
        // 문자열 파싱하여 튜플의 요소를 추출
        String[] elements = s.replaceAll("[{}]", "").split(",");
        
        // 요소의 등장 횟수를 저장할 Map
        Map<String, Integer> counts = new HashMap<>();
        for (String element : elements) {
            counts.put(element, counts.getOrDefault(element, 0) + 1);
        }
        
        // 등장 횟수를 기준으로 정렬
        List<String> sortedElements = new ArrayList<>(counts.keySet());
        sortedElements.sort((a, b) -> counts.get(b) - counts.get(a));
        
        // 정렬된 요소를 배열에 저장
        int[] answer = new int[sortedElements.size()];
        for (int i = 0; i < sortedElements.size(); i++) {
            answer[i] = Integer.parseInt(sortedElements.get(i));
        }
        
        return answer;
    }
}

전체적인 로직을 정리하면 다음과 같다.

  1. 문자열을 파싱하여 각 튜플의 요소 추출
  2. 추출된 요소를 튜플의 크기에 따라 정렬
  3. 각 튜플을 배열에 저장

사실 전체적인 로직은 내가 짠 코드와 비슷하다.
그런데 나는 우선순위 큐를 사용하였는데, gpt는 Map을 사용하였다.
그리고 가장 중요한 규칙 ,,

⭐ 숫자가 언급된 횟수가 많은 순서대로 배열에 저장된다.

나는 앞서 언급했듯이, 앞에 이미 저장한 수들을 제거하는 식으로 하니까 당연히 코드가 길어졌다.
그런데 그냥 쉼표 구분없이 모든 숫자들을 대상으로 언급 횟수를 기록하고, 이를 내림차순으로 정렬하여 배열에 넣으면 되는 일이었던 것 ,,,,,,, so easy

모르는 문법, 이해가 안되는 부분이 있다면 아래 정리 참고!


관련 문법 정리

Map

🤍 생성
Map<String, Integer> counts = new HashMap<>();

🤍 GetOrDefault() 메서드
counts.put(element, counts.getOrDefault(element, 0) + 1)
참고로 위의 코드에서 각 요소들은 Map의 키로 저장되고, 등장 횟수는 Map의 값으로 저장된다.

  • counts.getOrDefault(element, 0)
    counts 맵에서 element에 해당하는 값을 가져오는데, 해당 값이 없다면 기본 값으로 0을 반환!
    그래서 이름 그대로 'get' or 'Default'

한마디로 counts에 이미 저장된 요소라면 +1 해주고, 처음 언급된 요소라면 1을 저장한다는 의미..!

림다 표현식

Java 8부터 도입된 기능
익명 함수를 생성할 수 있도록 도와주는 간단한 문법.

형식 : (매개변수) -> expression
예시 : (int a, int b) -> a + b

예시에서 int a와 int b를 매개변수로 받고, 이들을 더한 값을 반환하게 되는 것!

리스트 내맘대로 정렬하기

🤍 sort() 메서드에서의 람다 표현식
sortedElements.sort((a, b) -> counts.get(b) - counts.get(a));
우선 위의 코드는 sortedElements라는 리스트를 등장 횟수에 따라 내림차순 정렬하는 코드.
즉, 등장횟수가 많은 순서대로 정리하는 것!

  • (a,b) -> counts.get(b) - counts.get(a)
    정렬 기준을 정의하는 람다 표현식.
    등장횟수를 counts 맵에서 get해와서 비교한다. 만약 b의 등장 횟수가 a보다 많다면 위의 식은 양수가 되는 것.

☁️ 반환 값이 음수 : 첫 번째 인수가 두 번째 인수보다 작다고 판단
☁️ 반환 값이 양수 : 첫 번째 인수가 두 번째 인수보다 크다고 판단
☁️ 반환 값 0 : 두 인수가 같다고 판단


java 문법엔 내가 머릿속에 있는 공식을 훨씬 간단하게 표현할 수 있도록 지원하는 문법들이 많은데, 모르고 있는게 태산이다 ..후
Map과 List의 경우에는 아직 사용하는게 익숙하지 않아서 적용이 바로 내 머릿속에서 되지 않는다.
ㄴ queue는 익숙해져서 이제 경우에 맞춰서 잘 사용 중!
익숙해지려고 노력해야지-!

profile
Developer's Logbook

0개의 댓글