n의 음이 아닌 정수 a1,a1,,..an이 주어진다. 각각은 coordinate(i,ai) 를 나타내는 것임.
그 ai에서부터 수직선을 내려 긋는다.
가장 많은 물을 담고 있을 수 있는 컨테이너를 생성하는 두 개의 line을 찾아라.
먼저, 투 포인터로 풀어야 할 것 같다는 생각이 든다.
- container이기 때문에 x * y를 구해야 한다.
- 이 경우, 양 끝의 x에서 시작하여, 좀 더 높은 height를 가진 막대기를 찾는 과정에서, 필연적으로 x가 줄어든다.
일단, 투 포인터를 사용한다면, 포인터를 움직이는 것 자체가, x를 줄이는 과정이 된다.
따라서 무조건, 현재보다 높이가 높아질 수 있는 경우에만 포인터를 움직여야 한다.
- 따라서 min인 line을 변경하도록 포인터를 변경해야 한다.
- 즉, 항상 height는 높이도록 포인터를 움직이는데,
- 이 결과로 계산된 x y 가 기존의 것보다 작다면, 앞으로 더 큰 x y 가 나올 수 없음을 뜻하겠다.
현재, h[left]와 h[right]중 더 작은 높이를, 더 크게 만들 수 있는 경우에만 해당 포인터를 움직여 나간다.
왜냐하면, 포인터를 움직인다는 것은 , 이미 x축의 길이를 감소시키는 일이기 때문이다. 따라서 높이라도 더 높아지는 경우여야지 더 큰 container일 확률이 생기는 것이다.
따라서 투 포인터 문제였던 것이다.
투포인터의 시간 복잡도 : O(n)
class Solution {
public int maxArea(int[] height) {
int left = 0, right = height.length - 1, c = 0, max = 0;
// n은 2 이상
while(left<right){
c = Math.min(height[left],height[right])*(right-left);
max = Math.max(c,max);
// left or right를 움직인다
if(height[left] < height[right]) left++;
else{
right--;
}
}
return max;
}
}
class Solution {
public int maxArea(int[] height) {
int left = 0, right = height.length - 1, c = 0, max = 0;
// h[left]<h[right]인 경우, h[left]보다 큰 첫 번째 위치를 찾기 위해 사용할 cleft
// h[left]>h[right]인 경우, h[right]보다 큰 첫 번째 위치를 찾기 위해 사용할 cright
int cleft = left, cright = right;
// n은 2 이상
while(left<right){
c = Math.min(height[left],height[right])*(right-left);
max = Math.max(c,max);
// left or right를 움직인다
if(height[left] < height[right]) {
// height[left]보다 큰 height가 첫 번째로 등장하는 곳을 cleft로 찾는다.
cleft = left+1;
while(cleft<right){
if(height[cleft]<=height[left]) cleft++;
else break;
}
left = cleft;
}
else{
cright = right-1;
while(left < cright){
if(height[cright] <= height[right] )cright--;
else break;
}
right = cright;
}
}
return max;
}
}