문제

https://programmers.co.kr/learn/courses/30/lessons/1845

풀이

nums	result
[3,1,2,3]	2
[3,3,3,2,2,4]	3
[3,3,3,2,2,2]	2

우선 곧장 모든 조합을 구하는 것은 굉장히 무거우므로 배제한다.
안봐도 시간초과가 수두룩 하게 뜰 것이다.

“nums를 바로 중복배제 시킨 다음 모든 조합을 구해보자!”
라는 생각으로 접근해봤던 코드.

from itertools import combinations
def solution(nums):
    num = list(set(combinations(nums, len(nums)//2)))
    answer = 0
    for n in num :
        if answer < len(set(n)) : answer = len(set(n))
    return answer

시간초과가 우수수수수 쏟아졌다.
set을 통해 중복배제 시켰는데도 무겁다…

불필요하게 생성되는 조합이 없는지 고려해본다.
예제 3개 중 3번의 조합이 바로 그런 경우였다.

[3,3,3,2,2,2]

이 경우 조합을 구해보지 않아도 답이 2라는걸 알 수 있다.
아하, 처음 중복배제를 시켜봤을 때 이미 nums의 절반 보다 작으면 바로 답을 반환하자!

from itertools import combinations
def solution(nums):
    setnums = set(nums)
    if len(nums)//2 > len(setnums) : # 중복배제 길이가 이미 더 짧다면 종료
        return len(setnums)

    num = list(combinations(setnums, len(nums)//2))

    result = 0
    for n in num :
        if len(set(n)) > result :
            result = len(set(n))
    return result

이렇게 처리를 해줬음에도 시간초과가 계속 나왔다.
중복배제 후 반환시키는 라인을 멍하니 보다가 문뜩 머리에 스친 생각이…

어… 가져가라는 nums의 절반보다 중복배제가 더 작으면
어차피 최대종류는 중복배제고…
중복배제가 가져가라는 nums의 절반보다 크면
답이 nums의 절반인거 아닌가?

그대로 코드로 옮기다보니, 조합을 구할 필요도 없어졌다. 코드를 정리해봤다.

def solution(nums):
    return len(set(nums)) if len(nums)//2 > len(set(nums)) else len(nums)//2

응 맞다. 조합을 구할 필요 자체가 없었다.
조합을 구해야하는 것처럼 지문이 적혀있었지만,
함정에 빠지지 않는다면 조합과는 관계없이 바로 답을 작성할 수 있는 문제였다.

채점 버튼 누르고 성공으로 도배되는 채점화면을 보면서
내가 문제의 본질을 파악하기보다 지문에 얼마나 신경을 쓰고있는가 깨달으면서
허탈하게 웃음이 나오는 문제였다.

댓글남기기