Welcome! Everything is fine.

[프로그래머스 고득점 Kit Lv.2] 해시 - 의상(Java) (+ HashMap 사용법 정리) 본문

프로그래머스/알고리즘 고득점 Kit

[프로그래머스 고득점 Kit Lv.2] 해시 - 의상(Java) (+ HashMap 사용법 정리)

개발곰발 2024. 3. 15.
728x90

📌 문제

📌 코드

import java.util.*;

class Solution {
    public int solution(String[][] clothes) {
        // clothes 크기 만큼의 map 생성
        HashMap<String, Integer> map = new HashMap<>(clothes.length);

        // clothes[i][0] : 의상 이름, clothes[i][1] : 의상 종류
        for (String[] cloth : clothes) {
            if (map.containsKey(cloth[1])) { // map에 해당 의상 종류가 있으면 실행
                map.put(cloth[1], map.get(cloth[1]) + 1); // 그 전 value에 +1
                continue;
            }
            map.put(cloth[1], 1); // map에 해당 의상 종류가 없으면 추가
        }
        // 의상 종류와 의상 종류별 개수가 map에 저장됨

        // Iterator를 이용해 map에서 value값 꺼내기(의상 종류별 개수)
        Iterator<Integer> it = map.values().iterator();
        int answer = 1;

        while (it.hasNext()) { // 다음 요소가 없을 때까지 반복
            answer *= it.next() + 1; // 의상을 착용하지 않을 경우의 수 각 +1
        }

        return answer - 1; // 아무 의상도 착용하지 않았을 경우는 빼서 리턴
    }
}

📌 풀이

  • HashMap에 익숙하지 않아서 생소했던 문제. 각 종류별로 경우의 수를 구하려고 한다면 해시를 사용하는 것이 좋다.
  • 먼저 의상 종류를 Key로, 해당 의상 종류별 개수를 value로 넣어 출력해보니 다음과 같은 값이 들어간 것을 볼 수 있었다. HashMap에 값을 넣을 때는 HashMap에 추가하려는 의상 종류가 없다면 새로 추가한 후 value에 1을 넣었다. 그리 추가하려는 의상 종류가 이미 있다면 들어있는 value(map.get(cloth[1]))값에 1을 더했다.

HashMap 출력 결과

  • 이제 모든 조합을 계산하는데, 이때 의상을 착용하지 않을 경우까지 계산해야한다. 테스트1에 따르면 HashMap에서 headgear는 2개, eyewear는 1개지만, 조합의 수를 구할 때는 각 1을 더해줘서 headgear는 3개, eyewear는 2개가 된다.

1을 더하지 않았을 때(좌) / 1을 더했을 때(우)

  • 이제 headgear의 개수 * eyewear의 개수 = 6으로 조합을 구했지만, 아무것도 안입는 경우는 포함하지 않기 때문에 answer에서 1을 빼준다.

💡 HashMap 사용법

Collection Framework In Java.  by Nishajha

HashMap이란?

HashMap은 자바에서 제공하는 데이터 구조 중 하나로, Map 인터페이스를 상속하고 있는 Map 컬렉션이다. 키-값(key-value) 쌍을 저장하는 자료구조이며 해시 테이블(hash table)을 기반으로 구현되어있다. HashMap은 키를 해시 함수에 넣어 해시 코드(hash code)를 생성하고, 이 해시 코드를 사용하여 배열의 인덱스를 계산한다. 그래서 키와 연관된 값을 빠르게 검색할 수 있다.

특징

  • 해시 기반이므로 검색 속도가 빠르다.
  • 키의 중복을 허용하지 않는다.
  • 순서를 보장하지 않는다.
  • 스레드에 안전하지 않아 동시에 여러 스레드에서 사용될 때는 외부에서 동기화 처리를 해줘야 한다.

HashMap 선언

HashMap을 선언하는 방법은 다음과 같다.  꼭 HashMap으로 선언하지 않아도 Map 형태로 선언해 유연성을 높힐 수 있다.

// 기본 선언
HashMap<KeyType, ValueType> map = new HashMap<>();
// 초기 용량 지정
HashMap<KeyType, ValueType> map = new HashMap<>(initialCapacity);
// 로드 팩터 지정
HashMap<KeyType, ValueType> map = new HashMap<>(initialCapacity, loadFactor);
// 기존 맵으로 초기화
Map<KeyType, ValueType> existingMap = new HashMap<>();
HashMap<KeyType, ValueType> map = new HashMap<>(existingMap); // 다른 작업 수행 후

HashMap 값 추가

HashMap에서는 기본적으로 put() 메서드를 통해 원하는 만큼 데이터를 추가할 수 있다. 이 때 추가하려는 데이터의 키가 이미 존재한다면 이전 값은 새로운 값으로 대체된다. 이 외에도 해당 키가 존재하지 않을 때에만 값을 추가하는 putIfAbsent(), 다른 맵에 있는 모든 키-값 쌍을 현재 HashMap에 추가하는 putAll()을 이용해 추가할 수 있다.

// put() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.put(key1, value1);
map.put(key2, value2);
// putIfAbsent() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.putIfAbsent(key1, value1);
map.putIfAbsent(key2, value2);
// putAll() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
Map<KeyType, ValueType> anotherMap = new HashMap<>();
map.putAll(anotherMap); // 다른 맵에 데이터를 추가한 후

HashMap 값 삭제

HashMap에서는 remove() 메서드로 주어진 키에 해당하는 값을 제거 할 수 있다. 모든 요소를 제거하려면 clear() 메서드를 사용한다.

// remove() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.remove(key);
// remove(key, value) 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.remove(key, value);
// clear() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.clear();

HashMap 값 출력

HashMap의 값은 다음과 같은 방법으로 출력할 수 있다. forEach 메서드가 간결하고 직관적이어서 최근에 많이 사용된다고 한다.

// forEach() 메서드 사용
HashMap<KeyType, ValueType> map = new HashMap<>();
map.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));
// KeySet()을 통한 키 순회
HashMap<KeyType, ValueType> map = new HashMap<>();
for (KeyType key : map.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
// entrySet()을 통한 키-값 쌍 순회
HashMap<KeyType, ValueType> map = new HashMap<>();
for (Map.Entry<KeyType, ValueType> entry : map.entrySet()) {
    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
// Iterator를 통한 순회
HashMap<KeyType, ValueType> map = new HashMap<>();
Iterator<Map.Entry<KeyType, ValueType>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<KeyType, ValueType> entry = iterator.next();
    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}