코딩 테스트 풀이 6 - 위장

배효림·2023년 3월 17일
0

코딩테스트

목록 보기
6/20

✔ 문제

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

💡 접근 방법

우선 HashMap 을 이용해 의상의 종류를 key로 해당 종류의 의상의 개수를 value 로 만든다. 주어진 2차원 String 배열을 iterate 하며 HashMap 을 업데이트 한다. 그 다음에, 입을 수 있는 의상의 조합을 계산하는데, 이 때 벗은 경우의 수도 염두에 둔다.

⭐ 코드

import java.util.ArrayList;
import java.util.HashMap;

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

class Solution {
   public int solution(String[][] clothes)
    {
        HashMap<String, Integer> clothesMap = new HashMap<>();

        // 맵에 값 추가
        for (String[] cloth : clothes)
        {
            clothesMap.merge(cloth[1],1,Integer::sum);
        }

        int answer = 1;

        for (String key : clothesMap.keySet())
        {
        	// 벗은 경우도 추가 
            answer *= ( clothesMap.get(key) + 1);
        }

		// 다 벗은 경우 제외
        answer -= 1;

        return answer;
    }
}

💻 더 나은 코드 분석

코드 통과는 했지만, 더 간략하거나, 더 효과적이게 코드를 짠 결과들을 보고 어떤 것을 배우면 좋을지 분석해봤다.

	Arrays.stream(clothes)
                .collect(groupingBy(p -> p[1], mapping(p -> p[0], counting())))
                .values()
                .stream()
                .collect(reducing(1L, (x, y) -> x * (y + 1))).intValue() - 1;

위 코드는 내 코드보다 훨씬 간결하다. 사실 근데 아직 stream에 익숙치 않아 line by line 어떤 역할을 하는지 한 번 분석해 보려고 한다.

  1. groupingBy(classifier, downStream)

    첫번째 파라미터는 classifer - 분류 기준이다. 여기서는 p -> p[1] 즉 의상의 종류가 된다. 두번째 파라미터는 downStream - 집계 방식인데 분류 기준에 의해 분류된 결과값들에 다른 기준의 집계방식을 더한다고 생각하면 된다. classifier 기준으로 Key를 분류하여, Map<Key,Value> 를 리턴한다. counting() 이 파라미터로 들어가게 되면 그룹 안에 오브젝트가 몇 개 있는지를 준다. 따라서, 위의 코드에서는 의상 종류 (classifier - key) 당 몇 개의 값이 있는지를 저장하게 된다.

  2. reducing()
    최종연산 으로, 스트림의 원소를 줄여나가면서 처음 두 원소를 가지고 연산한 결과로 그 다음 원소와 연산한다.

  3. collect()
    최종연산 으로 연산된 결과값을 원하는 자료형으로 수집하여 반환한다. 동일한 데이터를 List 나 Set 자료형으로 변환하는데에도 쓰인다.

요약하자면, 우선 의상 종류를 key 로 하고, 해당 종류의 대한 count 값을 value 로 하는 map 을 만든다. 그리고 해당 map 의 value 를 다시 스트림으로 만들어, reduce 연산을 통해 조합 연산을 한다. 그리고 최종 값에 - 1을 하여 전부 벗은 상태 (예외 상태)를 처리한다.

⏱ 더 좋은 함수 선택

  1. merge(key,1,Integer::sum) : 이중배열을 iterate 하면서 각 의상 종류가 몇 개 있는 업데이트할 때, contains 여부 확인 후 없다면 put, 있다면 replace를 썼는데, 그것보다 위 함수가 더 좋은 선택이었을 것 같다. 위 함수는 key 가 있는지를 검사하고, 없다면 1을 value로 세팅, 있다면 value +1을 한다고 한다.
profile
항상 위를 바라보는 프로그래머

0개의 댓글