[Meetcode-2020-08-02] 1395. Count Number of Teams

Cheol Kang·2020년 8월 8일
0

meetcode-2020-08-02

목록 보기
3/4

https://leetcode.com/problems/count-number-of-teams/

일단 가장 쉬운 방법을 생각해 보죠.

그냥 모든 경우의 수을 생각해 주면 됩니다.

이 경우 시간 복잡도는 O(N^3) 이 됩니다.

class Solution:
    def numTeams(self, rating: List[int]) -> int:
        ret = 0
        for i in range(len(rating)):
            for j in range(i+1, len(rating)):
                for k in range(j+1, len(rating)):
                    if rating[i] < rating[j] < rating[k]:
                        ret +=1
                    elif rating[i] > rating[j] > rating[k]:
                        ret +=1
        return ret

이제 조금 최적화을 해봅시다.

만약 배열이 [1,2,3,4,2,1] 라고 할때 (1,3,4) (2,3,4) 모두 팀이 될 수 있지만 이 때 우리는 3 뒤에 큰 수가 4밖에 없다는 걸 알지만 매번 반복문을 통해서 새로 찾습니다.

이걸 미리 구해놓으면 어떨 까요?

greater[i] = i 보다 오른쪽에 있는 수에서 rating[i] 보다 큰 수 라고 해보죠.

그렇다면 우리는 매번 탐색할 필요 없이 이 배열을 사용 할 수 있습니다.

밑의 코드의 시간복잡도는 O(N^2) 입니다.

class Solution:
    def numTeams(self, rating: List[int]) -> int:
        ret = 0
        greater = [sum(rating[j] > rating[i] for j in range(i+1, len(rating))) for i in range(len(rating))]
        less    = [sum(rating[j] < rating[i] for j in range(i+1, len(rating))) for i in range(len(rating))]
        
        for i in range(len(rating)):
            for j in range(i+1, len(rating)):
								# 만약 (rating[i] > rating[j]) 면 rating[j] 보다 작으면서, 더 오른쪽에 있는 갯수을 더해주면 된다. 
                if rating[i] > rating[j]:
                    ret += less[j]
                elif rating[i] < rating[j]:
                    ret += greater[j]
        return ret

보다 최적화을 해봅시다.

nums[j] 가 존재할 때, i<j 을 만족하면서 nums[i] < nums[j] 을 만족하는 갯수을 지금까지는 반복문을 통해서 구했습니다. 만약 nums[0~j] 까지 미리 정렬 되어 있는 배열이 있다면 우리는 binary search 을 통해서 쉽게 갯수을 구할 수 있습니다. 그리고 nums[j] 을 그 정렬되어 있는 배열에 잘 넣는다면 지속적으로 정렬된 배열을 가져가면서 갯수을 쉽게 구할 수 있을 것 같습니다.

일반적으로 이러한 자료구조는 Red-Black Tree, AVL Tree 같은 Self-balanced Tree 또는 Skip List 등으로 구현 할 수 있습니다. C++, Java 에서는 Map , Set 으로 구현 되어 있지만 Python 에서는 기본 자료구조가 아니기 때문에 sortedcontainer 을 임포트 해서 사용해야 합니다.

밑의 코드의 시간복잡도는 O(NlogN) 이 됩니다.

from sortedcontainers import SortedList
class Solution:
    def numTeams(self, rating: List[int]) -> int:
        ret=0
        # num 보다 왼쪽의 요소들로 만든 정렬된 배열
        sl_l = SortedList()
        # num 보다 오른쪽의 요소들로 만든 정렬된 배열
        sl_r = SortedList(rating)
        # 중간 num 을 구한다.
        for num in rating:
            sl_r.remove(num)
            # 왼쪽배열에서 num의 위치, 오른쪽배열에서 num의 위치을 구한다
            l_idx, r_idx = sl_l.bisect_left(num), sl_r.bisect_right(num)
            # 왼쪽배열에서 num보다 작은 요소의 갯수는 l_cnt
            # 오른쪽 배열에서 num보다 큰 요소의 갯수는 r_cnt
            l_cnt, r_cnt = l_idx, len(sl_r) - r_idx
            # (왼쪽 < num < 오른쪽) 의 갯수
            ret += l_cnt*r_cnt
            # (왼쪽 > num > 오른쪽) 의 갯수
            l_cnt, r_cnt = len(sl_l)-l_idx, r_idx
            ret += l_cnt*r_cnt
            sl_l.add(num)
        return ret

0개의 댓글