인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

Ambition님의 프로필 이미지
Ambition

작성한 질문수

코딩테스트 [ ALL IN ONE ]

[코테 적용] 👉 [Unique Paths] 완전탐색 / DP (후반부)

unique paths 코드 시간복잡도에 관련해서 궁금한 것이 있습니다.

해결된 질문

작성

·

94

·

수정됨

1

우선 강사님께서 풀어주신 top-down 코드는 다음과 같습니다.

class Solution(object):
    def uniquePaths(self, m, n):
        memo = {}

        def dfs(r, c):
            if (r, c) == (0, 0):  # 출발점에 도달한 경우
                return 1
            if (r, c) not in memo:  # 메모이제이션에 값이 없는 경우 계산
                paths = 0
                if r - 1 >= 0:  # 위쪽 셀에서 오는 경우
                    paths += dfs(r - 1, c)
                if c - 1 >= 0:  # 왼쪽 셀에서 오는 경우
                    paths += dfs(r, c - 1)
                memo[(r, c)] = paths  # 결과 저장
            return memo[(r, c)]  # 결과 반환

        return dfs(m - 1, n - 1)

이 코드는 grid에 해당하는 함수만 호출하고, 중복되는 호출은 memo에 저장하기 때문에 총 O(M*N)이 됩니다.

 

다음은, 디스코드의 다른 사람이 올려주신 코드를 참고해서 조합론을 적용한 코드입니다.

class Solution(object):
    def uniquePaths(self, m, n):
        memo = {}
        def fact(x):
            if x <= 1:
                return 1
            if x not in memo: 
                memo[x] = fact(x - 1) * x # factorial의 결과값을 메모리에 저장
            return memo[x]
        return fact(m + n - 2) / (fact(m - 1) * fact(n - 1)) # fact(m + n - 2) 부분만 호출하고, 분모는 캐싱하므로 시간복잡도는 O(M+N)

분자에 해당하는 부분만 함수를 호출하기 때문에 시간복잡도는 O(M+N)이 됩니다.

 

우선 제가 궁금한 것은 2가지입니다.

1) 위의 두 코드를 비교했을 때, 수학적으로 접근한 코드가 시간복잡도가 더 낮은데요 항상 dfs, bfs를 먼저 쓰는게 좋은 것은 아닌가요?

2) 강의에서는 조합론을 이용한 방법이 198C99 = 약 2*10^58이여서 완전탐색은 안된다고 하셨는데, 실제로 제출했을 때는 제출이 됬습니다. 왜 이런 차이가 발생한건가요?

답변 1

0

안녕하세요. Ambition님!

다른 사람들의 코드를 보면서 공부하시는 모습이 정말 보기 좋습니다 ㅎㅎ

자.. 답변 시작해보겠습니다.

 

1) 위의 두 코드를 비교했을 때, 수학적으로 접근한 코드가 시간복잡도가 더 낮은데요 항상 dfs, bfs를 먼저 쓰는게 좋은 것은 아닌가요?

 

이건 문제의 특성과 상황에 따라서 다릅니다.

이 문제에서는 조합 공식을 이용하여 문제를 해결할 수 있지만, 모든 문제가 수학적으로 해결할 수 있는 것은 아닙니다. 혹여나, 가능하더라도 식을 세우는 것이 쉽지 않습니다. (또한 코드가 복잡해질 가능성도 있습니다.)

 

기업용 코딩테스트에서 시간복잡도는 중요한 요소이지만, 보통 극한으로 최적화하는 코드를 작성해야 해결되는 경우는 거의 없습니다. 따라서 일반적이고, 구현하기 쉬운 방법으로 접근하는 것이 좋습니다.

 

물론, 문제를 보자마자 획기적인 방법이 생각난다면, 그 방법대로 진행하는 것이 옳습니다.

(이 문제를 처음 접했을 때, 프로그래밍에 익숙한 사람들은 대부분 DFS를 먼저 떠올릴 가능성이 큽니다. 물론 사람에 따라 다르겠죠?)

 

결론은, 좋고 나쁨의 문제로 접근할 문제는 아닙니다. 시간복잡도를 계산했을 때 문제만 없다면 어느 방법을 사용해도 무방합니다.

 


2) 강의에서는 조합론을 이용한 방법이 198C99 = 약 2*10^58이여서 완전탐색은 안된다고 하셨는데, 실제로 제출했을 때는 제출이 됬습니다. 왜 이런 차이가 발생한건가요?

 

음.. Ambition님께서 헷갈리신 부분이 있으신듯 합니다.

강의에서 의미하는 바는

모든 경로를 탐색하는 것은 시간초과가 발생한다는 의미입니다.

 

Ambition님께서 작성해주신 조합으로 해결한 코드는

'조합 공식'을 이용한 것이지 모든 경로를 순회한 것은 아닙니다.

 

모든 경로를 탐색하도록 코드를 작성하면 시간초과가 발생합니다.

 

강의를 다시 시청하면서 고민해보시는 것을 추천합니다.


이해가 안되는 부분이 있거나 추가적인 질문이 있다면 언제든 질문 주세요!

 

감사합니다.

Ambition님의 프로필 이미지
Ambition
질문자

와...! 감사합니다 아 그렇군요 조합 공식을 사용한 것과 모든 경로를 탐색한것은 완전히 다른거군요?? 아무래도 문제를 많이 풀어보면서 가장 보편적이고 기업에서 제시한 시간복잡도 이내에 푸는 풀이가 무엇인지 고민 많이 해봐야겠습니다 ㅎㅎ

Ambition님의 프로필 이미지
Ambition

작성한 질문수

질문하기