1. 문제
문제 설명
스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.
예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.
종류이름
| 얼굴 | 동그란 안경, 검정 선글라스 | 
| 상의 | 파란색 티셔츠 | 
| 하의 | 청바지 | 
| 겉옷 | 긴 코트 | 
스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.
제한사항
- clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
- 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
- 같은 이름을 가진 의상은 존재하지 않습니다.
- clothes의 모든 원소는 문자열로 이루어져 있습니다.
- 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.
- 스파이는 하루에 최소 한 개의 의상은 입습니다.
입출력 예
clothesreturn
| [[yellow_hat, headgear], [blue_sunglasses, eyewear], [green_turban, headgear]] | 5 | 
| [[crow_mask, face], [blue_sunglasses, face], [smoky_makeup, face]] | 3 | 
입출력 예 설명
예제 #1
headgear에 해당하는 의상이 yellow_hat, green_turban이고 eyewear에 해당하는 의상이 blue_sunglasses이므로 아래와 같이 5개의 조합이 가능합니다.
1. yellow_hat 2. blue_sunglasses 3. green_turban 4. yellow_hat + blue_sunglasses 5. green_turban + blue_sunglasses
예제 #2
face에 해당하는 의상이 crow_mask, blue_sunglasses, smoky_makeup이므로 아래와 같이 3개의 조합이 가능합니다.
1. crow_mask 2. blue_sunglasses 3. smoky_makeup
2. 내 풀이
Java
import java.util.HashMap;
public class Camouflage {
    public int solution(String[][] clothes) {
        int answer = 1;
        HashMap<String, Integer> clothName = new HashMap<>();
        HashMap<String, Integer> clothType = new HashMap<>();
        for (int i = 0; i < clothes.length; i++) {
            // 옷 이름이 이미 있으면 카운트 추가 해당 옷이 없으면 넣고 카운트 1
            clothName.put(clothes[i][0], clothName.getOrDefault(clothes[i][0], 0) + 1);
            // 옷 종류가 이미 있으면 카운트 추가 , 해당 옷이 없으면 넣고 카운트 1
            clothType.put(clothes[i][1], clothType.getOrDefault(clothes[i][1], 0) + 1);
        }
        for (String type:clothType.keySet()) {
            int count = 0;
            for (int i = 1; i < clothType.size(); i++) {
                count += i;
            }
            answer = (int) (count * Math.pow(2, clothType.size()));
        }
        if (clothType.keySet().size() == 1){ return clothes.length; }
        return clothes.length + answer;
    }
}- 못풀었다. 거의 다 푼것 같았는 데 경우의수를 세는 방법을 몰랐다..
- 너무 부끄럽다.
JS
function solution(clothes) {
    let clothesCount = new Map();
    // clothes 배열을 받은 다음 clothesType목록만 추가 시킴
    for(let i = 0; i < clothes.length; i++){
        // 만약 옷 종류가 등록 되지 않았다면 [옷 종류,  1] 추가
        if(!clothesCount.has(clothes[i][1])) clothesCount.set(clothes[i][1], 1);
        else{
            // 만약 옷 종류가 등록이 되어 있는 경우라면 [옷 종류 ,기존에 들어 있던 옷 종류의 갯수  + 1] 로 map 최신화
            clothesCount.set(clothes[i][1], clothesCount.get(clothes[i][1]) + 1);
        }
    }
    let answer = 1;
    
    // map의 keys()는 키들의 집합, values()는 값들의 집합
    // of 라는 표현은 foreach같은 표현 , 반복 가능한 객체를 하나씩 떠서 반복문 안에 넣는다.
    for(let a of clothesCount.values()){
        answer *= (a + 1);
    }
    return answer - 1;
}
let clothes = [['yellow_hat', 'headgear'], ['blue_sunglasses', 'eyewear'], ['green_turban', 'headgear']];
console.log(solution(clothes));
Map 객체
- js에는 hashmap처럼 쓸수 있는 Map이라는 객체가 존재한다.
- key와 value값을 가지며 key는 하나의 value값만을 가진다.
길이
- map의 길이는 size로 구할 수 있다. map.lenght는 0이다.
초기화
- map.clear()
키 제거
- map.delete(key) : 해당하는 키에 대한 value값이 제거 되고 map.has(key) 값이 반환된다.
키 참조
- map.get(key) : 해당하는 키에 대한 value값을 반환한다.
키값이 존재하는지
- map.has(key) : 해당하는 키가 존재하면 true, 존재하지 않으면 false를 반환한다.
키 set
- map.keys() : 객체안에 존재하는 모든키들을 iterator 객체로 반환한다.
값 set
- map.values() : 객체안에 존재한는 모든값들을 iterator 객체로 반환한다.
키, 값 추가
- map.set(key, value) : 해당하는 키에 value값을 집어넣고 최신화된 map을 반환한다.
developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Map
Map
Map 객체는 키-값 쌍을 저장하며 각 쌍의 삽입 순서도 기억하는 콜렉션입니다.
developer.mozilla.org
for of 구문
- for of 구문은 반복가능한 객체를 반복문에서 사용자 정의 반복 후크를 적용할 수 있는 구문이다.
- java식 foreach 같다.
for(let a of array){
	console.log(a)
}
// array값을 하나씩 뽑아내서 출력한다.Set 객체
- 중복을 제거하는 python의 set과 개념이 같다.
- 중복되는 값이 제거된다.
- 중복되는 set 객체를 다시 배열로 바꿀때에는 전개연산자(Spread)를 사용할 수 있다.
let arr = [1, 2, 3, 3 ,3];
let set = new Set(arr);
for(let a of set){
    console.log(a);
}
//1
//2
//3
let newArr = [...set];
// spread of 문법
// set객체는 객체안의 속성을 펼친다음 []로 묶어서 배열로 만들었다.
전개연산자 (Spread)
- js에만 있는 특이한 문법인데 객체 안의 내용을 모두 풀어내어 버린다.
- 위 예시와 같이 객체 앞에 ...라는 표현을 사용한다.
let arr = [1 ,2, 3];
let arr2 = [1, ...arr, 2, ...arr, 3];
console.log(...arr2);
//1 1 2 3 2 1 2 3 3
- 이는 객체에서도 마찬가지인데, 객체에서 전개연산자를 다음과 같이 사용할 수 있다.
- 객체안의 요소를 모두 풀어서 객체안에 집어 넣을 수도 있다.
const obj1 = {
	name : "name"
};
const obj2 = {
    ...obj1,
    age : 17,
};
const obj3 = {
    ...obj2,
    weight: 121
};
console.log(obj3);
//Object {name: "name", age: 17, weight: 121}
3. 다른 사람 풀이
import java.util.HashMap;
public class Camouflage {
    public int solution(String[][] clothes) {
        int answer = 1;
        HashMap<String, Integer> clothType = new HashMap<>();
        // 옷 종류에 따른 옷 갯수 구하기
        for (int i = 0; i < clothes.length; i++) {
            // 옷 종류가 이미 있으면 카운트 추가 , 해당 옷이 없으면 넣고 카운트 1
            clothType.put(clothes[i][1], clothType.getOrDefault(clothes[i][1], 0) + 1);
        }
        // 조합을 센다. 옷 종류 별로 가지고 있는 옷갯수를 보자 추가로 옷종류 별로 안입을 경우의 수를 더한다.
        // 예를 들면 모자 2개 상의 3개 라고 한다면 모자로 나올수 있는 경우는 모자1, 모자2, 안입음 이렇게 3가지가 나온다.
        // 즉, 옷 종류에 있는 갯수 + 1을 해야 옷을 입는 경우의 수가 나온다.
        // 따라서 clothType.get(key) + 1 하고 answer에 곱해나가면 경우의수가 나온다. 이후 마지막에 - 1을 한다.(안입는 경우의수)
        for (String key:clothType.keySet()) {
            answer *= clothType.get(key) + 1;
        }
        // 아무것도 안입는 경우의 수 제거
        return answer - 1;
    }
}- 옷 종류 별로 가지고 있는 옷의 갯수를 보자면 보통
모자 2개 상의 3개를 입는 경우의 수는 6이다.
하지만 모자를 안입고 상의를 안입는 경우까지 세자면 (2 + 1) * (3 + 1) 이렇게 된다.
그리고 아얘 안입는 경우를 빼면 - 1을 해주면된다.
따라서 옷을 입는 경우의수 만을 세면
*= (clothType.get(key) + 1)
마지막에 -1
4. Tip
- 경우의 수를 잘 세보자.
- 처음에 옷종류에 따른 옷갯수를 중복을 제외해서 구하기 위해 HashMap을 사용하고 getOrDefalut를 사용했다.
'알고리즘 > Programers' 카테고리의 다른 글
| Programmers - 스택/큐 [기능개발] (0) | 2020.10.27 | 
|---|---|
| Programmers - 스택/큐 [주식가격] (0) | 2020.10.26 | 
| Programmers - 분류 [제목] (0) | 2020.10.22 | 
| Programmers - Hash [전화번호 목록] (0) | 2020.10.22 | 
| Programers - Hash [완주하지 못한 선수] (0) | 2020.10.22 |