Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- hash table
- binary tree
- Python
- DP
- 리트코드
- recursive
- binary search
- 쉬움
- two pointers
- Medium
- 문자열
- dfs
- linked list
- 재귀
- matrix
- sorting
- 미디움
- 중간
- 이진트리
- math
- backtracking
- tree
- Array
- easy
- Binary
- string
- list
- leetcode
- HashTable
- Depth-first Search
Archives
- Today
- Total
부부의 코딩 성장 일기
LeetCode 11(Container With Most Water, python) 본문
1. 문제 링크
Container With Most Water - LeetCode
Can you solve this real interview question? Container With Most Water - You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]). Find two lines that toget
leetcode.com
2. 문제 설명
- 리트 코드의 문제 설명이 이상하다. 물의 양을 생각하면 헷갈림.
- 그냥 이렇게 생각하자. 일정 간격으로 높이가 제각각인 막대기들이 있음.
- 임의의 두 막대로 만들 수 있는 직사각형의 넓이의 최댓값 구하기. (직사각형의 높이는 두 막대 높이 중 min 값)
3. 처음 풀이
- 임의의 두 막대를 선택하는 경우를 모두 고려하면 시간복잡도가 O(n²)인데 이는 좋은 풀이가 아님
- two pointers 방법을 이용하면 O(n)으로 풀 수 있음.
- 첫 후보는 좌우 양 끝 막대를 고르는 것(가로가 제일 길기 때문에 적당한 후보임.)
- 이제 좌우 경계를 조금씩 안으로 좁히며 넓이의 최댓값을 업데이트하며 좌우 경계가 만날 때까지 탐색하면 O(n)으로 풀 수 있음.
- 좌우 경계를 안쪽으로 좁히는 방법.
- 두 막대기 중 높이가 크지 않은 값이 사각형의 높이가 됨.
- 막대기가 안쪽으로 가면 가로가 작아지므로 넓이가 커지려면 무조건 사각형의 높이가 커져야 함.
- 그렇다면 두 막대 높이의 min 값이 커져야하므로 둘 중 작은 막대가 안쪽으로 가면서 더 높은 막대가 되어야 함.
- 따라서 두 막대 중 작은 막대를 안쪽으로 옮기며 원래보다 높은 막대가 될 때까지 옮겨주고 이때 넓이를 구하여 업데이트. 반복.
- 이때 좌우 막대의 높이가 같을 때 어느 막대를 먼저 옮기는 지는 답에 영향을 미치지 않음.
- 왜냐하면 두 막대 높이가 같은 순간이 생겼을 때, 안쪽으로 왔을 때 더 큰 넓이가 발생하려면 좌우 모두 안쪽으로 왔을 때 높이가 커져야 함. 그렇다면 결국 무엇을 먼저 옮기든 나머지 하나도 그 다음에 옮겨짐.
class Solution:
def maxArea(self, height: List[int]) -> int:
result = (len(height)-1)*min(height[0],height[-1]) #처음 넓이
l = 0 #왼쪽 경계
length = len(height) #리스트 길이
r = length-1 #오른쪽 경계
while l < r : #두 경계를 점점 안쪽으로 이동하다가 만나거나 역전될 때까지 반복
heightLeft = height[l] #왼쪽 높이
heightRight = height[r] #오른쪽 높이
if heightLeft < heightRight: #두 경계 중 높이가 낮은 경계(지금 왼쪽)를 안쪽으로 이동
x = l
while heightLeft >= height[x] and x < length: #안쪽 경계가 더 낮아지면 넓이가 커질 수 없으므로 +1 칸 안쪽 이동
x += 1
l = x
else: #오른쪽 경계 높이가 더 낮다면 안쪽으로 이동
y = r
while height[y] <= heightRight and y > 0: #안쪽 경게가 더 낮아지면 넓이가 커질 수 없으므로 -1 칸 안쪽으로 이동
y -= 1
r = y
result = max(result, (r-l)*(min(height[l],height[r]))) #안쪽 경계가 높아졌다면 넓이 계산하여 최댓값 업데이트
return result
4. 다른 풀이
- 두 막대 중 낮은 막대를 안쪽으로 옮길 때 그냥 한칸씩 옮기며 모두 업데이트하는 풀이
class Solution:
def maxArea(self, height: List[int]) -> int:
start_point = 0
end_point = len(height)-1
output = 0
while(start_point != end_point):
if height[end_point] > height[start_point]:
area = height[start_point] * (end_point - start_point)
start_point += 1
else:
area = height[end_point] * (end_point - start_point)
end_point -= 1
if area > output:
output= area
return output
5. 배운 점
- two pointer 기법을 이용하면 O(n²)을 O(n)으로 단축할 수 있음.
- 포인터 두 개가 모두 왼쪽이 아니라 왼쪽 하나 오른쪽 하나에서 출발하는 경우는 처음 풀어봄.
'Algorithm > LeetCode' 카테고리의 다른 글
LeetCode 15(3Sum, Python) (0) | 2023.12.14 |
---|---|
LeetCode 12(Integer to Roman, Python) (0) | 2023.12.13 |
LeetCode 8(String to Integer (atoi), python) (1) | 2023.12.11 |
LeetCode 7(Reverse Integer, Python) (0) | 2023.12.10 |
LeetCode 6(Zigzag Conversio, Python) (0) | 2023.12.09 |