리스트에 순차적으로 접근해야 할 때 두개의 포인터를 기록하면서 처리하는 알고리즘입니다.
투포인터 알고리즘을 사용하는 문제를 풀어봅시다.
A, B의 배열이 주어지면 공통된 원소를 구해서 반환하세요.
int[] a = {1,3,9,5,2};
int[] b = {3,2,5,7,8};
{2,3,5}
public static List<Integer> solution(int[] a, int[] b) {
// step 1.
Arrays.sort(a);
Arrays.sort(b);
int p1 = 0;
int p2 = 0;
List<Integer> answerList = new ArrayList<>();
//step 2.
while(p1 < a.length && p2 < b.length) {
if(a[p1] == b[p2]) { //step 2-1
answerList.add(a[p1]);
p1++;
p2++;
}else if(a[p1] > b[p2]) { //step 2-2
p2++;
}else{ //step 2-3
p1++;
}
}
return answerList;
}
p1, p2둘중 하나라도 각 배열의 길이보다 커질 시 while문은 종료가 되며 공통된 원소의 리스트가 완성됩니다.
시간복잡도는 O(N)입니다.
Two pointers처럼 구간을 훑으면서 지나간다는 공통점이 있으나 슬라이딩 윈도우는 어느 순간에도 구간의 넓이가 동일하다는 차이점이 있습니다.
아래 문제를 풀면서 이해해봅시다.
N일 동안의 매출기록이 저장되어 있는 배열 arr이 주어지면 이 중 에서 연속된 K일 동안의 최대 매출액이 얼마인지 구하시오.
int[] arr = {12, 15, 11, 20, 25, 10, 20, 19, 13, 15};
int k = 3;
56
public static int solution(int[] arr, int k){
int currSum = 0; // 현재 구간의 합계
//step 1.
for(int i = 0; i < k; i++){
currSum += arr[i];
}
//step 2.
int maxSum = currSum;
int lt = 1;
int rt = lt + k - 1;
//step 3.
while(rt < arr.length){
//step 3-1
currSum -= arr[lt- 1];
currSum += arr[rt];
//step 3-2
maxSum = Math.max(maxSum, currSum);
//step 3-3
lt++;
rt++;
}
return maxSum;
}
투포인터와 동일하게 시간복잡도는 O(N)입니다.
코딩테스트 문제에 가끔 등장하는 알고리즘이므로 모두 알아둡시다!!