|
| 1 | +"""TC: O(n), SC: O(1) |
| 2 | +
|
| 3 | +아이디어: |
| 4 | +높이 리스트 l이 주어졌다고 하자. 그리고 이 안에 있는 최대 수조 면적을 f(l)이라고 하자. |
| 5 | +
|
| 6 | + □ □ □ |
| 7 | + □ □ □ □ |
| 8 | + □ □ □ □ □ □ □ □ □ |
| 9 | +□ □ □ □ □ □ □ □ □ □ □ □ |
| 10 | +□ □ □ □ □ □ □ □ □ □ □ □ □ □ |
| 11 | +2,5,3,3,1,3,1,2,2,5,3,5,3,4 |
| 12 | + ^ |
| 13 | + l |
| 14 | +
|
| 15 | +
|
| 16 | +그러면 다음이 항상 성립한다. |
| 17 | +
|
| 18 | +- l의 양 끝의 값 중 작은 값 x가 앞쪽에 있었다고 해보자. x를 뺀 리스트 l`을 만든다. |
| 19 | + - 이때 작은 값이 뒷쪽에 있었어도 일반성을 잃지 않는다. |
| 20 | +
|
| 21 | + │□ □ □ |
| 22 | + │□ □ □ □ |
| 23 | + │□ □ □ □ □ □ □ □ □ |
| 24 | +□│□ □ □ □ □ □ □ □ □ □ □ |
| 25 | +□│□ □ □ □ □ □ □ □ □ □ □ □ □ |
| 26 | +2│5,3,3,1,3,1,2,2,5,3,5,3,4 |
| 27 | +^ ^ |
| 28 | +x l` |
| 29 | +
|
| 30 | +
|
| 31 | +- f(l)은 그렇다면 |
| 32 | + - f(l`)이거나(즉, x를 쓰지 않았거나) |
| 33 | + - x를 써서 만든 수조 면적 중에 있다. |
| 34 | +
|
| 35 | +- 그런데 x는 l의 양 끝 값 중에 작은 값이므로, 아래와 같은 분석을 할 수 있다. |
| 36 | + 1) x를 써서 만드는 수조의 높이는 아무리 높아도 x다. x보다 작아질 수는 있어도, x보다 커질 수는 없다. |
| 37 | + 2) x를 써서 만드는 수조의 폭은 l의 다른쪽 끝에 있는 높이를 선택했을때 최대가 된다. |
| 38 | +- 그러므로, x를 써서 만들 수 있는 수조의 최대 크기는 l의 다른쪽 끝에 있는 높이를 선택한 경우 나온다. |
| 39 | +
|
| 40 | +위의 내용을 아래의 설명을 통해 시각적으로 확인할 수 있다. |
| 41 | +
|
| 42 | +- 양 끝을 선택한 경우 x로 만들 수 있는 최대 면적이다. |
| 43 | +
|
| 44 | + │□ □ □ |
| 45 | + │□ □ □ □ |
| 46 | + │□ □ □ □ □ □ □ □ □ |
| 47 | +■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ |
| 48 | +■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ |
| 49 | +2│5,3,3,1,3,1,2,2,5,3,5,3,4 |
| 50 | +^ ^ |
| 51 | +
|
| 52 | +- x는 그대로 둔 채 다른쪽 끝을 안쪽으로 더 이동하면 수조 높이는 동일한데 폭은 더 작아진다. |
| 53 | +
|
| 54 | + │□ □ □ |
| 55 | + │□ □ □ □ |
| 56 | + │□ □ □ □ □ □ □ □ □ |
| 57 | +■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ □ □ |
| 58 | +■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ □ □ |
| 59 | +2│5,3,3,1,3,1,2,2,5,3,5,3,4 |
| 60 | +^ ^ |
| 61 | +
|
| 62 | +- 심지어 x보다 작은 높이 값을 선택한 경우 수조 높이도 작아지고 폭도 작아지는 일이 일어난다. |
| 63 | +
|
| 64 | + │□ □ □ |
| 65 | + │□ □ □ □ |
| 66 | + │□ □ □ □ □ □ □ □ □ |
| 67 | +□│□ □ □ □ □ □ □ □ □ □ □ |
| 68 | +■│■ ■ ■ ■ ■ ■ □ □ □ □ □ □ □ |
| 69 | +2│5,3,3,1,3,1,2,2,5,3,5,3,4 |
| 70 | +
|
| 71 | +
|
| 72 | +즉, 위의 내용을 종합하면 다음을 확인할 수 있다. |
| 73 | +- f(l) = max( (l의 양 끝 높이를 선택해서 만든 수조 넓이), f(l`) ) |
| 74 | +- 그런데 f(l`)도 f(l)을 구한 것과 같은 방식으로 구할 수 있다. 즉, 새로 만들어진 l`의 양 끝 높이 중 |
| 75 | + 짧은 쪽을 뺀 리스트 l``을 만들어서 위의 과정을 반복할 수 있다. |
| 76 | +- 즉, f(l)은 아래의 과정을 반복하여 구할 수 있다. |
| 77 | + - l의 양 끝 높이를 써서 수조 넓이를 구하고, 기존 최대 넓이와 비교하여 더 큰 값을 최대 넓이에 대입한다. |
| 78 | + - l에서 짧은 쪽 높이를 뺀다. |
| 79 | + - 위 과정을 l에 아이템이 하나만 남을 때까지 반복. |
| 80 | +
|
| 81 | +
|
| 82 | +SC: |
| 83 | +- 투 포인터를 써서 l의 시작, 끝 인덱스를 관리하면 O(1). |
| 84 | +- 수조 최대 넓이값 관리, O(1). |
| 85 | +- 종합하면 O(1). |
| 86 | +
|
| 87 | +TC: |
| 88 | +- 리스트의 양 끝 높이를 통해 면적 구하기, O(1). |
| 89 | +- 포인터 이동 O(1). |
| 90 | +- 포인터 이동시 두 포인터 사이의 거리가 1씩 항상 감소하므로 위 과정을 최대 n-2번 반복. |
| 91 | +- 종합하면 O(n). |
| 92 | +""" |
| 93 | + |
| 94 | + |
| 95 | +class Solution: |
| 96 | + def maxArea(self, height: List[int]) -> int: |
| 97 | + max_area = -1 |
| 98 | + s, e = 0, len(height) - 1 |
| 99 | + while s < e: |
| 100 | + max_area = max(max_area, (e - s) * min(height[s], height[e])) |
| 101 | + if height[s] > height[e]: |
| 102 | + e -= 1 |
| 103 | + else: |
| 104 | + s += 1 |
| 105 | + return max_area |
0 commit comments