[Programmers] Lv1 성격 유형 검사하기 Java

2023. 2. 6. 21:44CS/자료구조 & 알고리즘

728x90

문제 출처

[프로그래머스 코딩 테스트 연습]

https://school.programmers.co.kr/learn/courses/30/lessons/118666

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 풀이

이 문제는 다음과 같이 나뉜다.

  1. 성격 유형 RT, CF, JM, AN에 해당하는 값을 각각의 점수를 저장
  2. 점수에 따라서 출력

 

성격 유형 RT, CF, JM, AN에 해당하는 값을 각각의 점수를 저장

 

자료구조 선택

우선 점수를 저장하기 위해서 자료구조를 무엇을 쓸지 정해야한다.

여기서는 HashMap이 아닌 순서가 유지되는 LinkedHashMap을 이용한다.

key에는 성격유형들 “RT”, “CF”, “JM”, “AN” 이 순서대로 들어간다.

value에는 각각의 성격 유형의 점수를 저장할 수 있게 int 배열을 주었다.

public LinkedHashMap<String, int[]> kakaoPersonality = new LinkedHashMap<>();

LinkedHashMap은 순서가 유지되는 HashMap이기 때문에 후에 출력해줄 순서대로 입력을 해주면된다.

여기서는 Stirng 배열로 순서를 잡고 for로 LinkedHashMap에 넣었다.

String[] personality = {"RT", "CF", "JM", "AN"};
for (String key : personality)
    kakaoPersonality.put(key, new int[] {0, 0});

 

자료구조에 저장

우선 survey의 유형 상관없이 값을 얻는 방법을 생각해보자.

각 유형의 점수는 0~3점까지 얻을 수 있다.

그리고 choices의 최댓값은 7이고 중앙값은 4이다.

choices에서 4를 뺀다면 범위는 -3~3을 얻을 수있다.

이를 절댓값을 취하면 어떤 유형이든 점수 0~3을 얻을 수있다.

int personalValue = Math.abs(choices[i] - 4);

choices에 들어갈 수 있는 방법은 1부터 7까지이다.

1~3까지는 survey에 왼쪽 5~7까지는 survey의 오른쪽으로 정의된다.

이를 수학으로 바꾼다면 choices / 4를 한것의 몫으로 바꿀 수 있다.

예를 들면 RT 유형일때 5점이라면 5/4의 몫은 1이다.

즉 int 배열에 index 1로 접근해서 저장이 가능하다.

int personalIndex = choices[i] / 4;

자료구조를 저장할때 우리는 RT로 저장을 했다.

하지만 위에 경우에 TR로 들어오면 int[]에 잘못된 index에 접근 할 수 도 있다.

이를 막기 위해서 생각을 해보자.

RT, CF, JM, AN을 비교해보자.

R은 T보다 사전상 앞에 있다.

C도 F보다 사전상 앞에 있다.

나머지 JM, AN도 마찮가지 이다.

즉 문자를 비교해서 올바른 값을 바꾸면 된다.

이를 위해 key와 int의 index를 바꿔줘야 한다.

key를 String으로 변경하는 것보다 StringBuilder를 이용하여 변경해주는 것이 빠르므로 StringBuilder를 사용했다.

index의 변경은 최댓값 - 현재값을 역순으로 되기 때문에 이를 이용하면 쉽게 바꿀 수 있다.

StringBuilder key = new StringBuilder(survey[i]);

if (key.charAt(0) > key.charAt(1)) {
    personalIndex = 1 - personalIndex;
    key.reverse();
}

설문지 길이 만큼 돌면서 위에 있는 것을 작성하고

만든 자료구조에 점수를 넣으면 코드는 아래와 같아진다.

for (int i = 0; i < survey.length; i++) {
    int personalIndex = choices[i] / 4;
    int personalValue = Math.abs(choices[i] - 4);
    StringBuilder key = new StringBuilder(survey[i]);
    if (key.charAt(0) > key.charAt(1)) {
        personalIndex = 1 - personalIndex;
        key.reverse();
    }
    kakaoPersonality.get(key.toString())[personalIndex] += personalValue;
}

 

점수에 따라서 출력

점수를 출력 조건은 다음과 같다.

유형 중 점수가 큰 것이 유형이 된다.

하지만 점수가 같다면 사전상 앞에 나온것이 유형이 된다.

자료 구조에 저장할때 기억을 하는가?

우리는 RT, CF, JM, AN가 사전 상으로 된것을 파악했다.

또한 자료를 선택할때 RT, CF, JM, AN 순서대로 저장을 했다.

또한 LinkedHashMap은 저장한 순서가 유지가 된다.

즉 key를 가져와서 조건에 맞추면 된다.

index를 0으로 두고 크기만 비교해서 index를 지정하면 크기가 같을때는 무조건 사전상 앞으로 유지가 된다.

StringBuilder answer = new StringBuilder() ;
for (String key : kakaoPersonality.keySet()) {
    int[] values = kakaoPersonality.get(key);
    int index = 0;
    if (values[0] < values[1])
        index = 1;
    answer.append(key.charAt(index));
}

 

String vs StringBuilder 비교

StringBuilder을 이용하는 것이 전체적으로 빨랐다.

  String StringBuilder(출력) StringBuilder(저장, 출력)
테스트 1 〉 통과 (16.17ms, 76.9MB) 통과 (8.83ms, 83.4MB) 통과 (0.23ms, 74.5MB)
테스트 2 〉 통과 (16.39ms, 82.4MB) 통과 (8.76ms, 80.9MB) 통과 (0.24ms, 75.5MB)
테스트 3 〉 통과 (15.55ms, 75.3MB) 통과 (8.79ms, 75.8MB) 통과 (0.30ms, 79.4MB)
테스트 4 〉 통과 (16.11ms, 75.1MB) 통과 (9.50ms, 79.5MB) 통과 (0.23ms, 75.4MB)
테스트 5 〉 통과 (13.04ms, 74.5MB) 통과 (8.09ms, 82.9MB) 통과 (0.22ms, 74.3MB)
테스트 6 〉 통과 (16.69ms, 83.7MB) 통과 (9.00ms, 77.6MB) 통과 (0.26ms, 71.4MB)
테스트 7 〉 통과 (22.29ms, 81.9MB) 통과 (10.64ms, 74.8MB) 통과 (0.32ms, 78MB)
테스트 8 〉 통과 (13.59ms, 70.2MB) 통과 (11.29ms, 73MB) 통과 (0.38ms, 75.4MB)
테스트 9 〉 통과 (17.14ms, 75.3MB) 통과 (13.49ms, 81.5MB) 통과 (0.29ms, 72.1MB)
테스트 10 〉 통과 (18.01ms, 83.5MB) 통과 (8.62ms, 83.9MB) 통과 (0.46ms, 90.2MB)
테스트 11 〉 통과 (14.36ms, 80.9MB) 통과 (8.96ms, 76.2MB) 통과 (0.51ms, 79.1MB)
테스트 12 〉 통과 (20.59ms, 88.2MB) 통과 (11.63ms, 80.7MB) 통과 (0.66ms, 83.9MB)
테스트 13 〉 통과 (18.43ms, 75.5MB) 통과 (17.62ms, 78.7MB) 통과 (2.25ms, 73.4MB)
테스트 14 〉 통과 (19.96ms, 78.1MB) 통과 (11.59ms, 77.1MB) 통과 (1.16ms, 79.1MB)
테스트 15 〉 통과 (18.95ms, 76.4MB) 통과 (10.37ms, 72MB) 통과 (1.10ms, 70MB)
테스트 16 〉 통과 (25.15ms, 72.5MB) 통과 (8.68ms, 81.8MB) 통과 (1.27ms, 78MB)
테스트 17 〉 통과 (15.35ms, 83MB) 통과 (8.81ms, 79.3MB) 통과 (1.82ms, 75.7MB)
테스트 18 〉 통과 (16.33ms, 83.4MB) 통과 (8.53ms, 85MB) 통과 (1.35ms, 84.8MB)
테스트 19 〉 통과 (20.48ms, 71.3MB) 통과 (8.60ms, 79.3MB) 통과 (1.61ms, 85.2MB)
테스트 20 〉 통과 (23.76ms, 86.1MB) 통과 (8.49ms, 80.8MB) 통과 (1.15ms, 84.7MB)

 

소스 코드

import java.util.LinkedHashMap;

public class Solution {

    public LinkedHashMap<String, int[]> kakaoPersonality = new LinkedHashMap<>();

    public String solution(String[] survey, int[] choices) {

        String[] personality = {"RT", "CF", "JM", "AN"};
        for (String key : personality)
            kakaoPersonality.put(key, new int[] {0, 0});

        for (int i = 0; i < survey.length; i++) {
            StringBuilder key = new StringBuilder(survey[i]);
            int personalIndex = choices[i] / 4;
            int personalValue = Math.abs(choices[i] - 4);
            if (key.charAt(0) > key.charAt(1)) {
                personalIndex = 1 - personalIndex;
                key.reverse();
            }
            kakaoPersonality.get(key.toString())[personalIndex] += personalValue;
        }

        StringBuilder answer = new StringBuilder() ;
        for (String key : kakaoPersonality.keySet()) {
            int[] values = kakaoPersonality.get(key);
            int index = 0;
            if (values[0] < values[1])
                index = 1;
            answer.append(key.charAt(index));
        }

        return answer.toString();
    }
}
728x90