1차원 배열이 주어졌을 때, 특정 연속된 구간의 합이 M이 되는 경우의 수를 구하려면 어떻게 해야 할까?

가장 단순하게 생각해볼 수 있는 방법은 2중 반복문을 돌리는 것이다.

public class Main {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 2, 5, 3, 1, 1, 2}; // 크기가 10인 1차원 배열
int m = 5; // 연속된 구간의 합이 5인 경우를 찾는다.
int count = 0;
for (int i = 0; i < 10; i++) {
int sum = arr[i];
for (int j = i + 1; j < 10; j++) {
if (sum == m) {
count++;
} else if (sum > m) {
break;
} else {
sum += arr[j];
}
}
}
}
}

 

당연히 위의 방법과 같이 이중 반복문을 돌리게 되면 시간 복잡도가 O(N2) 으로 배열의 크기가 커지면 커질수록 느려진다.

1차원 배열의 연속된 구간에 대해 2중 반복문을 개선하기 위해 나온 것이 투 포인터 알고리즘이다.

 

 

 

투 포인터(Two Pointers) 알고리즘


아래와 같은 1차원 배열이 있다.

[그림 1] 예시 1차원 배열

 

위의 1차원 배열에 대해 연속된 구간의 합이 5인 것의 경우의 수를 구해보자.

위의 2중 반복문과 큰 차이는 없는데, Right를 우측으로 하나씩 옮기면서 arr[left] + ... + arr[right]의 값이 5보다 크다면 더이상 right를 우측으로 옮기는건 무의미하다. right를 우측으로 옮겨봤자 마찬가지로 5보다 크기 때문이다. 따라서, 이 경우 left를 우측으로 옮긴다.

 

코드로 살펴보자.

public class Main {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 2, 5, 3, 1, 1, 2}; // 크기가 10인 1차원 배열
int m = 5; // 연속된 구간의 합이 5인 경우를 찾는다.
int count = twoPointers(arr, m);
}
private static int twoPointers(int[] arr, int m) {
int sum = 0, count = 0;
int left = 0, right = 0;
while (true) {
if (sum > m) { // 1. left를 우측으로 옮기는 경우
sum -= arr[left++];
} else if (right == arr.length - 1) { // right를 우측으로 옮기기 전에 배열의 끝을 가리키는지 확인한다.
break;
} else { // 2. right를 우측으로 옮기는 경우
sum += arr[right++];
}
if (sum == m) count++;
}
return count;
}
}

 

댓글

댓글을 사용할 수 없습니다.