코딩 테스트/Level 1

로또의 최고 순위와 최저 순위

컴닥 2021. 5. 3. 16:35
반응형

로또의 최고 순위와 최저 순위
2021 Dev-Matching: 웹 백엔드 개발자(상반기) 
736명 완료

programmers.co.kr/learn/courses/30/lessons/77484

 

코딩테스트 연습 - 로또의 최고 순위와 최저 순위

로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. 1 순위 당첨 내용 1 6개 번호가 모두 일치 2 5개 번호

programmers.co.kr

파이썬

def solution(lottos, win_nums):
    zero, match = 0, 0
    for num in lottos:
        if num == 0:
            zero += 1
        elif num in win_nums:
            match += 1
    return [min(6, 7 - match - zero), min(6, 7 - match)]

리스트보다 딕셔너리나 셋(집합)의 검색이 더 빠릅니다. 
파이썬의 딕셔너리와 셋은 해시 알고리듬으로 작성되어 있습니다. 

def solution(lottos, win_nums):
    zero, match, win_nums = 0, 0, set(win_nums)
    for num in lottos:
        if num == 0:
            zero += 1
        elif num in win_nums:
            match += 1
    return [min(6, 7 - match - zero), min(6, 7 - match)]

 

golang

func solution(lottos []int, win_nums []int) []int {
	zero, match := 0, 0
	count := make(map[int]bool)
	prize := []int{6, 6, 5, 4, 3, 2, 1}
	for _, v := range win_nums {
		count[v] = true
	}
	for _, v := range lottos {
		if v == 0 {
			zero++
		} else if count[v] {
			match++
		}
	}
	return []int{prize[zero+match], prize[match]}
}

 

Java 

정직하게...

class Solution {
    public int[] solution(int[] lottos, int[] win_nums) {
        var win_count = 0;
        var zero_count = 0;
        for (int lotto : lottos) {
            if (find(win_nums, lotto)) {
                win_count++;
            } else if (lotto == 0) {
                zero_count++;
            }
        }
        return new int[]{prize(zero_count + win_count), prize(win_count)};
    }

    boolean find(int[] numbers, int num) {
        for (var each : numbers) {
            if (each == num) {
                return true;
            }
        }
        return false;
    }

    int prize(int num) {
        return (num > 1) ? 7 - num : 6;
    }
}

해시 셋을 이용했습니다. 
루프를 반복하지 않으니 속도도 향상되고, 
코드량도 줍니다. 

class Solution {
    public int[] solution(int[] lottos, int[] win_nums) {
        var win_count = 0;
        var zero_count = 0;
        var winNumSet = new HashSet<Integer>();
        for (var each: win_nums) winNumSet.add(each);
        for (int lotto : lottos) {
            if (winNumSet.contains(lotto)) {
                win_count++;
            } else if (lotto == 0) {
                zero_count++;
            }
        }
        return new int[]{prize(zero_count + win_count), prize(win_count)};
    }

    int prize(int num) {
        return (num > 1) ? 7 - num : 6;
    }
}

45개의 결과를 검색하기 위해 해시를 사용하는 것은 메모리의 낭비입니다.
다이렉트 어드레스 테이블(?)을 직접 구현하는 게 더 좋습니다.   

import java.util.Arrays;

class Solution {
    public int[] solution(int[] lottos, int[] win_nums) {
        var win_count = 0;
        var zero_count = 0;
        var winNumTable = new Boolean[46];
        Arrays.fill(winNumTable, false);
        for (var each : win_nums) winNumTable[each] = true;
        for (int lotto : lottos) {
            if (winNumTable[lotto]) {
                win_count++;
            } else if (lotto == 0) {
                zero_count++;
            }
        }
        return new int[]{prize(zero_count + win_count), prize(win_count)};
    }

    int prize(int num) {
        return (num > 1) ? 7 - num : 6;
    }
}

등수 계산 함수도 array로 대체하였습니다. 
위 과 같은 원리입니다. 

import java.util.Arrays;

class Solution {
    public int[] solution(int[] lottos, int[] win_nums) {
        var win_count = 0;
        var zero_count = 0;
        var winNumTable = new Boolean[46];

        // array를 이용해 함수 하나를 줄일 수 있습니다.
        var prizeTable = new int[]{6, 6, 5, 4, 3, 2, 1};

        // 검색 시 null 에러 방지를 위해, false로 채워주었습니다.
        Arrays.fill(winNumTable, false);

        // winNumTable의 인덱스에 로또 번호를 넣으면 당첨 여부를 바로 알 수 있습니다.
        // prizeTable과 같은 원리입니다.
        for (var each : win_nums) winNumTable[each] = true;

        for (int lotto : lottos) {
            if (winNumTable[lotto]) {
                win_count++;
            } else if (lotto == 0) {
                zero_count++;
            }
        }
        return new int[]{prizeTable[zero_count + win_count], prizeTable[win_count]};
    }
}
반응형