개발자는 기록이 답이다

[프로그래머스][Java][Lv.2] 의상 본문

알고리즘/프로그래머스

[프로그래머스][Java][Lv.2] 의상

slow-walker 2023. 10. 3. 16:43

 

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

 

프로그래머스

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

programmers.co.kr

 

테이블에 의상 종류별로 해싱하는거까지는 쉬웠는데,

map : {eyewear=1, headgear=2}

이 상태에서 경우의 수를 구하는게 어려웠다. 2중 포문 하고 실패했는데, 검색해보니 훨씬 쉽게 푸는 방법이 있었다.

 

 

import java.util.*;

class Solution {
    public int solution(String[][] clothes) {
        int answer = 1;
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < clothes.length; i++) {
            map.put(clothes[i][1], map.getOrDefault(clothes[i][1], 0) + 1);
        }
        for (Integer count : map.values()) {
            answer *= (count + 1);
        }
        return answer - 1;
    }

}
테스트 1 통과 (0.10ms, 73.6MB)
테스트 2 통과 (0.05ms, 75.2MB)
테스트 3 통과 (0.10ms, 74.7MB)
테스트 4 통과 (0.09ms, 70.7MB)
테스트 5 통과 (0.04ms, 72.4MB)
테스트 6 통과 (0.06ms, 77.4MB)
테스트 7 통과 (0.08ms, 75.6MB)
테스트 8 통과 (0.10ms, 72.7MB)
테스트 9 통과 (0.06ms, 77.9MB)
테스트 10 통과 (0.08ms, 74.1MB)
테스트 11 통과 (0.07ms, 75.3MB)
테스트 12 통과 (0.11ms, 78MB)
테스트 13 통과 (0.08ms, 74.8MB)
테스트 14 통과 (0.06ms, 69.6MB)
테스트 15 통과 (0.05ms, 74.2MB)
테스트 16 통과 (0.05ms, 68.9MB)
테스트 17 통과 (0.07ms, 68.4MB)
테스트 18 통과 (0.08ms, 72.5MB)
테스트 19 통과 (0.05ms, 73.7MB)
테스트 20 통과 (0.05ms, 74.4MB)
테스트 21 통과 (0.05ms, 74.2MB)
테스트 22 통과 (0.05ms, 76.7MB)
테스트 23 통과 (0.06ms, 74MB)
테스트 24 통과 (0.05ms, 76.1MB)
테스트 25 통과 (0.05ms, 73MB)
테스트 26 통과 (0.11ms, 76.8MB)
테스트 27 통과 (0.08ms, 73.9MB)
테스트 28 통과 (0.09ms, 82.5MB)

 

 

다른 풀이 1 - Iterator 사용

  • Iterator:
    • Iterator는 컬렉션(collection)을 순회하고, 각 원소에 접근하기 위한 인터페이스입니다.
    • Iterator를 사용하려면 먼저 컬렉션에서 iterator() 메서드를 호출하여 Iterator 객체를 생성해야 합니다.
    • hasNext() 메서드는 다음 원소가 있는지 여부를 확인하며, next() 메서드를 호출하여 다음 원소에 접근할 수 있습니다.
    • Iterator 내장 함수:
      • hasNext(): 다음 요소가 있는지 여부를 확인합니다.
      • next(): 다음 요소를 반환합니다.
      • remove(): 현재 반복 중인 요소를 삭제합니다. (일부 컬렉션에서는 지원되지 않을 수 있습니다.)
import java.util.HashMap;
import java.util.Iterator;

class Solution {
    public int solution(String[][] clothes) {
        // 1. 옷을 종류별로 구분하기
        HashMap<String, Integer> map = new HashMap<>();
        for (String[] clothe : clothes) {
            String type = clothe[1];
            map.put(type, map.getOrDefault(type, 0) + 1); 
            // 만일 밑에서 +1하기 싫다면 defaultvalue를 1로 설정
        }

        // 2. 입지 않는 경우를 추가하여 모든 조합 계산하기
        Iterator<Integer> it = map.values().iterator();
        int answer = 1;
        
        while(it.hasNext())
            answer *= it.next().intValue() + 1;
            // map : {eyewear=1, headgear=2} 에서 none의 경우를 추가하기 위해 타입별로 +1

        // 3. 아무종류의 옷도 입지 않는 경우 제외하기
        return answer - 1; // 총 조합수 6 - 1 = 5
    }
}

 

테스트 1 통과 (0.11ms, 71.3MB)
테스트 2 통과 (0.07ms, 75.2MB)
테스트 3 통과 (0.06ms, 73.3MB)
테스트 4 통과 (0.07ms, 73.6MB)
테스트 5 통과 (0.06ms, 76.5MB)
테스트 6 통과 (0.05ms, 86.8MB)
테스트 7 통과 (0.07ms, 73.6MB)
테스트 8 통과 (0.10ms, 77.7MB)
테스트 9 통과 (0.05ms, 76.8MB)
테스트 10 통과 (0.07ms, 71MB)
테스트 11 통과 (0.04ms, 76MB)
테스트 12 통과 (0.08ms, 74.3MB)
테스트 13 통과 (0.08ms, 77.8MB)
테스트 14 통과 (0.06ms, 73.4MB)
테스트 15 통과 (0.05ms, 72.9MB)
테스트 16 통과 (0.04ms, 79.7MB)
테스트 17 통과 (0.05ms, 73.3MB)
테스트 18 통과 (0.07ms, 78.2MB)
테스트 19 통과 (0.04ms, 77MB)
테스트 20 통과 (0.05ms, 75.1MB)
테스트 21 통과 (0.04ms, 72.1MB)
테스트 22 통과 (0.04ms, 77.3MB)
테스트 23 통과 (0.04ms, 74.8MB)
테스트 24 통과 (0.06ms, 75.7MB)
테스트 25 통과 (0.07ms, 64.9MB)
테스트 26 통과 (0.07ms, 68.6MB)
테스트 27 통과 (0.04ms, 76MB)
테스트 28 통과 (0.05ms, 72.3MB)

 

Iterator 예시 코드

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        // List 생성 및 요소 추가
        List<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");

        // Iterator 생성
        Iterator<String> iterator = fruits.iterator();

        // hasNext()와 next()를 사용하여 요소 순회
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            System.out.println(fruit);
        }

        // Iterator를 사용하여 요소 삭제
        iterator = fruits.iterator(); // 다시 초기화 필요
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            if (fruit.equals("Banana")) {
                iterator.remove();
            }
        }

        // 삭제 후 리스트 출력
        System.out.println("After removing Banana:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}
import java.util.*; // Iterator도 util클래스

public class Solution {
    public int solution(String[][] clothes) {
        int answer = 1;
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < clothes.length; i++) {
            map.put(clothes[i][1], map.getOrDefault(clothes[i][1], 0) + 1);
        }
        // String 반환
        Iterator<String> itStr = map.keySet().iterator();
        while(itStr.hasNext()) {
            String next = itStr.next();
        }
        // Integer 반환
        Iterator<Integer> itInt = map.values().iterator();
        while(itInt.hasNext()) {
            Integer next = itInt.next().intValue();
            // intValue()사용하면 unboxing 필요없다고 나오는데, 안해도 될것같다
        }
        ....

 

 

Map 반복문

Java에서 `Map`을 반복할 때, 일반적으로 다음 세 가지 방법을 사용합니다: `keySet()`, `values()`, `entrySet()`.

1. keySet()을 사용한 반복:

   - `keySet()`을 사용하면 `Map`의 모든 키(key)를 반복합니다.
   - 이 방법은 키를 사용하여 값을 얻을 때 유용합니다.

   Map<String, Integer> map = new HashMap<>();
   map.put("A", 1);
   map.put("B", 2);
   
   for (String key : map.keySet()) {
       System.out.println(key + ": " + map.get(key));
   }



2. values()를 사용한 반복:

   - `values()`를 사용하면 `Map`의 모든 값(value)을 반복합니다.
   - 이 방법은 값만 필요한 경우에 유용합니다.
   

   Map<String, Integer> map = new HashMap<>();
   map.put("A", 1);
   map.put("B", 2);
   
   for (Integer value : map.values()) {
       System.out.println(value);
   }



3. entrySet()을 사용한 반복:

   - `entrySet()`을 사용하면 `Map`의 모든 키-값 쌍(entry)을 반복합니다.
   - 이 방법은 키와 값을 동시에 필요로 할 때 유용합니다.

   Map<String, Integer> map = new HashMap<>();
   map.put("A", 1);
   map.put("B", 2);
   
   for (Map.Entry<String, Integer> entry : map.entrySet()) {
       System.out.println(entry.getKey() + ": " + entry.getValue());
   }


일반적으로 `entrySet()`을 사용하면 키와 값을 모두 가져오기 위해 두 번의 조회 작업이 필요하지 않습니다. 그러나 특정 상황에 따라 `keySet()` 또는 `values()`를 사용하는 것이 더 효율적일 수 있습니다. 예를 들어, 값만 필요한 경우에는 `values()`를 사용하여 불필요한 키 조회를 피할 수 있습니다.

 

 

참고 링크 : 

https://coding-grandpa.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9C%84%EC%9E%A5-%ED%95%B4%EC%8B%9C-Lv-2-%EC%9E%90%EB%B0%94-Java