DLife Planet

[코딩연습] 해시1 프로그래머스 - 완주하지 못한 선수 본문

Programming

[코딩연습] 해시1 프로그래머스 - 완주하지 못한 선수

Western_Gem 2020. 12. 1. 09:11
반응형

프로그래스 해시 1번 문제입니다.

 

 

풀이


import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

class Solution {
    public String solution(String[] participant, String[] completion) {

        // 해석 
        // Map<String, Long> Key값 String Value Long타입이다.
        // Arrays.asList() 배열 ( ArrayList 타입으로 변동)
        // Stream() Iterator와 유사, 저장 요소를 하나씩 참조하는 내부 반복자
        // ArrayList.stream().collect() : Arraylist collector타입 최종 변경.
        
        // Collectors.groupingBy() 정렬과 집계가 가능한 코드
        // 실제 요소 : Function.identity() 값  (즉 participant String 값)
        // dummy number 1 (갯수) : Collectors.counting() 
        
        // 정리
        // 수도코드 : 배열 participant를 잘 정렬된 participantMap으로 변환하는 과정이다.
        // 하는 이유, participant가 타켓 데이터이기 때문
        
        //1. 배열 -> Map 타입으로 바꾸기
        //2. 배열 -> ArrayList.stream().collect() 형 변환 
        //3. Collectors.gruouingby 실질적으로 정렬과 집계가 이뤄지는 곳
        //4. Function.identify(), Collectors.Counting() = 실제값, 더미 데이터
        
        // 인사이트
        // Map,stream.collect() 함수의 매개변수 Collectors 객체를 좀더 공부하자
        // Map은 공부할게 많구나
        
        Map<String, Long> participantMap = Arrays.asList(participant).stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        //completion은 비교 데이터로 타겟데이터와 비교하는 연산을 작업한다
        for(String name : completion) {

            // Map.get("실제값")은 Map의 value를 부르며, 1개인데, Long에선 1L로 잡는다
            // Long을 쓴 이유, Map에서 primative 불가, Integer는 산술 연산이 불가능함, 그래서 Long을 씀
            // Long의 1은 1L이다. 그리고 0은 0L 이다. 해시맵구조 쓸때 숫자 연산이 필요하면 Long을 쓰고
            // 연산이 필요하지 않은 경우 Integer를 쓰자.
            
            // completion name 파라미터 비교연산 1L 
            Long value = participantMap.get(name) - 1L;

            if(value == 0L) {
                // Completion = Participant 요소 제거
                participantMap.remove(name);
             } else {
                 // next 값 출력을 위해 값을 1회 삽입
                 participantMap.put(name, value); 
            }
        }
        // 최종적으로 한명 남은 Map의 값을 리턴해주면 끝
        return participantMap.keySet().iterator().next();
    }
}

솔직히 for문 안에 else가 왜 필요한지는 완벽히 이해 못함,

그러나 풀 문제가 많으므로 넘어가기로 함 ㅠㅠ 나란 놈이란

개발 3년차인데 아직도 해시맵 구조를 이해 못하는 한심한놈 ㅠ

일단 이 코드 자체도 주석이 이리 장황한걸 보면 제가 짠게 아니라는걸

게시물을 보신 분들도 아시리라 믿습니다.

 

실제로 else는 추가 삽입을 해주는건데,

저거 없어도 코드 실행 단계에서는 통과되는데 채점에서 막힘

아마도, iterator.next()가 값이 한개일때 인식을 제대로 못하거나

for문이 한번 더 돌아서 그럴 가능성도 보이는데 (네 압니다 근거 없는 추측성 리뷰는 죄악이라는거)

정확한 원인을 모르겠음, 알려주실분 구함... 제 블로그가 Stackoverflow는 아니지만...

 

function solution(participant, completion) {
    participant.sort(); //참가자 배열 정렬
    completion.sort(); //완주자 배열 정렬
    for(let i=0;i<participant.length;i++){
        if(participant[i] !== completion[i]){
            //인덱스 0부터 순차적으로 두 배열 비교
            return participant[i];
            //비완주자가 참가자 배열에 나올 경우 출력
        }
    }
}

// 제가 직접 짠 하찮은 자바스크립트 풀이법
// 자바의 sort나 얘나, sort()함수를 쓰는거 자체가 반복문을 돌리는거라
// 사실 성능상 썩 좋은 풀이는 아님, 다만 가독성이 높고, 간결해서
// 처음 배우시는 분들께는 좋음... 그러나 문제가 Hash를 요구한 만큼
// 잘 모르더라도, Hash를 사용한 풀이법을 보고 공부합시다.

번외로 어떤 현자님의 풀이법 입니다.

import java.util.HashMap;

class Solution {
    public String solution(String[] participant, String[] completion) {
        String answer = "";
        HashMap<String, Integer> hm = new HashMap<>();
        // participant key값으로 put 입력
        for (String player : participant) hm.put(player, hm.getOrDefault(player, 0) + 1);
        // completion key 값으로 value값 조정해서 put 재입력
        for (String player : completion) hm.put(player, hm.get(player) - 1);

		// 키셋함수를 활용한 반복문, get해서 value값이 조정이 안된 값 탐색 & answer 할당
        for (String key : hm.keySet()) {
            if (hm.get(key) != 0){
                answer = key;
            }
        }
        // answer리턴
        
        // 반복문에 대한 카더라가 있음(for만 나쁘다 땡, while, do~while, for 모두 성능에는 악영향을 줌
        // 굳이 말하자면 switch case가 성능상 나은데 해시맵 비교연산이 = 가 아닌 equal을 써야 하기에
        // switch case는 사용이 어려움, 그 어려운걸 해내는 사람
                
        return answer;
    }
}

// 가장 인기 많은 짧지만 명쾌한 해시 풀이법...
// 이걸 첫번째로 쓰지 않은 이유는
// 해시맵에 대한 이해를 기준으로 말하자면 (순수 코딩실력이라 보다는)
// 이건 뛰는걸 넘어서서 하늘을 나는 수준의 풀이기 때문
// 엉금엉금 기어가는것도 힘겨운 수준에서
// 걷지도 못하는 애한테 뛰는법도 아니고 나는법을 알려주는 꼴...
// 고로 해시가 익숙한 사람이 아니면 비추...

// 이 풀이의 장점
// 함수콜을 적게했다는 장점도 분명있음...
// 무엇보다 가독성이 높고 간결함

// 끝
반응형
Comments