one-way search인줄 알았던 투 포인터(two pointer)
one-way search인줄 알았던 투 포인터(two pointer) — #LeetCode #one-waysearch #개발자의도구들 #투포인터 #twopointer only 파이썬 목표 참고 : 여기 one-wa...
#LeetCode#Naver Blog
#LeetCode #one-waysearch #개발자의도구들 #투포인터 #twopointer
- only 파이썬
- 목표 참고 : 여기
one-way search 응용하기
LeetCode(medium 11. Container With Most Water) 57.2%
- 이전글에서 공부했었던 O(n²)인 것 같은데 O(n)으로 해결 가능한 문제이다.
- 문제에서 요구하는 최대, 최솟값을 어떻게 활용할지 잘 파악하는게 중요하다.
🤔 O(n²)으로 빠르게 구현이가능하다. 하지만 입력값이 10만이다.
>>> 이런 경우 보통 O(nlogn)으로 변환하는데 이 문제는 이걸 요구하는게 아니다.
>>> 한번의 search로 문제에서 요구하는 것을 구해야한다.
특징을 파악해보자.
[1,8,6,2,5,4,8,3,7]
>>>>>> 이동하면서 문제에서 요구되는 값을 갱신해야한다.
✅ 요구사항: 넓이 x 높이가 최대가 되는 값은?
✅ 특징정리:
>>> 넓이: 1씩 증가한다 (자동으로)
>>> 높이: 최소값을 기준으로 갱신된다.
⚒️ 예시 체크
넓이 : idx 값의 차이
높이 : 최소 높이
# 1 (init)
[1,8,6,2,5,4,8,3,7]
n m
width = 1
height = 1(1) = min(s,e)
result = width * height
# 2 (idx = 2)
v
[1,8,6,2,5,4,8,3,7]
n m
>>> have 2 case
v
[1,8,6,2,5,4,8,3,7]
result = max(1 * 2, 6 * 1)
is it best option ? maybe...
# 3 (idx = 3)
v
now :[1,8,6,2,5,4,8,3,7]
m n
>>> 2 case
[1,8,6,2,5,4,8,3,7]
m n
m n
result = max(result, 2 * 2, 2 * 1)
# 4 (idx = 4)
v
now: [1,8,6,2,5,4,8,3,7]
m n
>>>
m n
n m
result = max(result, 3 * 5, ❌2 * 1 -> max값을 변경할 이유가 없다.)
# 5
v
now: [1,8,6,2,5,4,8,3,7]
m n
>>>
m n
result = max(result, 4 * 4)
# 6
n v
now: [1,8,6,2,5,4,8,3,7]
m n
>>>
m n
result = max(result, 5 * 8)
# 7
v
now : [1,8,6,2,5,4,8,3,7]
m n
>>>
result = max(result, 6 * 3)
# 8
v
now : [1,8,6,2,5,4,8,3,7]
m n
>>> m n
result = max(result, 7 * 7)
result = 49
1차 결론
✅ init
>>> result
>>> min
>>> max 설정
✅ max는 언제 초기화되는가?
>>> max의 초기화는 의미가 없는 듯하다.
>>> 어차피 max를 초기화해도 min값이 높이를 결정하기 때문
>>> max보다는 fixed로 정하는게 나은거 같다.
✅ min은 언제 초기화 되는가?
>>> min은 그 값을 손해보더라도, 늘어나는 width값이 그 차이를 메꿀 수 있다면 언제든 초기화할 것
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
# init
min_height = min(height[0], height[1])
cur_width = 1
acc_width = 0
fixed = 0
result = cur_width * min_height
for i, h in enumerate(height):
print("i:", i)
# skip first
if i == 0 or i == 1:
continue
# test
# current, width + 1 min set , width, min_set
result = max(result, (cur_width + 1 ) * min(min_height, h), cur_width * h)
if result == (cur_width + 1 ) * min(min_height, h):
min_height = h
cur_width += 1
elif result == cur_width * h:
min_height = h
print(min_height, cur_width)
return result
- 틀렸다...
- 접근 자체가 잘못된 것 같다.
Two pointer
feat. gpt-o3
이 문제는 Two Pointer 문제였다. 계속 한방향 탐색에 집착한 나머지 이상항 수학공식을 억지로 만들다가 결국 실패했다...
✅ 양쪽 끝에서 시작한다.
✅ 갱신이 되어야할 대상 = 최소 height 값이다.
>>> 작은쪽의 point를 계속해서 옮기고, 두 포인터가 겹칠때 까지 계속한다.
수학으로 증명하기
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
# init
l = 0
r = len(height) - 1
result = 0
while l != r:
width = r - l
result = max(result, width * min(height[l], height[r]))
print(result)
if height[l] > height[r]:
r -= 1
else:
l += 1
return result
- claer time: 2hour...
- time beats: 5.04% 1297ms
배열 탐색 정리
여러 배열 탐색을 풀어보면서 여러가지 전략들을 떠올릴 수 있을 것 같다. 마치 드래곤볼을 모으듯이 말이다.
- O(n²)이 가능한지?
- 입력값이 충분히 작아야한다.
- O(nlogn)
- 정렬이 의미가 있는 경우
- O(n)
- 최대, 최소값을 업데이트 해가면서 구한다.
- 눈치가 중요하다.
- two pointer 기법이 있다.
- palindrome인 경우
- linkeList면 recursive로 reverse 시켜야함
- 가장 긴걸 찾으려면
- 전용 알고리즘 (hard)
후기
기존에 접하지 않은 전략들을 맛보닌깐 많이 당황스럽다. 그래도 포기하지는 말자. 하나씩 해결법을 모으는게 중요하다.