Skip to content

Commit 40a40db

Browse files
authored
Update Two Pointer Algorithm.md
1 parent aaa734e commit 40a40db

File tree

1 file changed

+61
-49
lines changed

1 file changed

+61
-49
lines changed

Algorithm/Two Pointer Algorithm.md

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,74 @@
11
# 투 포인터 알고리즘(Two Pointer Algorithm)
22

3+
34
### 정의
4-
배열 또는 리스트에서 두 개의 포인터를 사용하여 원하는 조건을 만족하는 구간을 찾거나 값을 계산하는 알고리즘
5+
투 포인터 알고리즘(Two Pointer Algorithm)은 배열 또는 리스트에서 두 개의 포인터를 사용하여 원하는 조건을 만족하는 구간을 찾거나 값을 계산하는 알고리즘
6+
57
대개 배열이나 리스트가 정렬되어 있을 때 사용되며, 배열의 시작과 끝 지점을 가리키는 두 개의 포인터를 이용하여 특정한 조건을 만족하는 부분을 찾음
68

79
---
810

911
### 동작 방식
10-
1. 배열이나 리스트가 정렬되어 있을 때, 각각의 포인터를 시작과 끝 지점에 위치시킴
11-
2. 두 포인터가 가리키는 값을 비교하여 원하는 조건을 만족하는지 확인
12-
3. 조건을 만족하면 필요한 작업을 수행하고, 조건을 만족하지 않으면 포인터를 이동하여 새로운 구간을 탐색
13-
4. 모든 조건이 만족할 때까지 위의 과정을 반복
1412

15-
---
13+
N칸의 1차원 배열이 있을 때, 부분 배열 중 그 원소의 합이 M이 되는 경우의 수를 구하는 것이다. 모든 경우의 수를 다 테스트 해보면 구간 합을 구간 배열로 O(1)만에 구한다고 해도 경우의 수는 O(N^2)이 된다. 따라서 문제를 풀 수 없다. N의 최대 범위가 너무 크기 때문이다.
14+
15+
이 문제에서 각 원소는 자연수이고 M 또한 자연수인데, 이 조건이 성립하면 사용할 수 있는 알고리즘은 다음과 같다.
16+
17+
포인터 2개를 준비한다. 시작과 끝을 알 수 있도록 start, end 라고 한다.
18+
맨 처음에는 start = end = 0이며, 항상 start<=end을 만족해야 한다.
19+
2개의 포인터는 현재 부분 배열의 시작과 끝을 가리키는 역할을 한다.
20+
s=e일 경우 그건 크기가 0인, 아무것도 포함하지 않는 부분 배열을 뜻한다. 다음의 과정을 s < N인 동안 반복한다.
21+
22+
만약 현재 부분합이 M 이상이거나, 이미 e = N이면 s++
23+
그렇지 않다면 e++
24+
현재 부분합이 M과 같으면 결과 ++
25+
쉽게 이해하자면, start와 end 를 무조건 증가시키는 방향으로만 변화시켜가면서 도중에 부분 배열의 합이 정확히 M이 되는 경우를 세는 것이다.
26+
27+
Ex) M = 5인 경우를 살펴보자.
28+
29+
30+
31+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/ad2755ef-ea1e-4e77-ab37-6f098b62f4cd)
32+
33+
초기 상태이며, 빨간색 포인터 : start, 파란색 포인터 : end이다. S : 합
34+
35+
end가 뒤로 움직일 때는 새로 포함한 원소를 S에 더하고, start가 뒤로 움직일 때는 새로 넘긴 원소를 S에서 빼는 식으로 현재 [start, end)의 합 S를 매번 쉽게 구할 수 있음
36+
37+
38+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/b54e4de2-a5ad-44b1-8664-2765d1cd5024)
39+
40+
처음에는 이렇게 end만 증가하게 된다. S가 계속 M보다 작기 때문! 마지막엔 S>=M이 되었으므로 아래와 같다.
41+
42+
43+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/863ee281-183e-4847-940a-c7fcaf266997)
44+
45+
start를 한 칸 옮겼는데, 동시에 S = 5인 경우를 만났다. 이때 결과를 1 증가시켜 준다.
46+
47+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/fe135122-f38c-4a7e-bafe-ac30010172b7)
48+
49+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/afcd22e0-0057-49c9-a7c4-b4819c0d82ad)
50+
51+
52+
이런 식으로 포인터들이 움직이게 된다. 여기서 2번째로 S = 5인 지점을 만났으므로 결과를 1 증가시켜 준다.
53+
54+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/ce2629e9-1525-4468-bcfa-ff90d38e9f8d)
55+
56+
그 직후, start가 1 증가하면서 start = end인 경우가 나온다.
57+
58+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/c5a314a3-1269-412f-8c3f-cfab665ffd94)
59+
60+
계속 가다 보면 세 번째로 S = 5인 지점을 만난다.
61+
62+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/783e8eac-e8c4-4138-90d7-b444549ca433)
63+
64+
65+
그 이후 조건에 맞춰 포인터를 증가시키다 보면, end가 배열 끝을 가리키게 되어 더이상 증가할 수 없는 상태가 된다.
66+
67+
![image](https://github.com/yeoseojeong/cpp-study/assets/121150215/b90c4c18-cb77-4c92-9eeb-4f10738eb34f)
68+
69+
그렇게 되면 그냥 start만 증가시켜 가다가 start 역시 배열 끝에 다다르면 종료해도 되고, 그냥 그 자리에서 루프를 끝내버려도 된다. 이렇게 해서 S = 5인 경우는 3개 발견되었다.
70+
1671

17-
```C++
18-
19-
#include <iostream>
20-
#include <vector>
21-
using namespace std;
22-
23-
// 투 포인터 알고리즘을 사용하여 합이 target이 되는 두 요소의 인덱스를 찾는 함수
24-
vector<int> twoSum(vector<int>& nums, int target) {
25-
int left = 0; // 왼쪽 포인터 초기화
26-
int right = nums.size() - 1; // 오른쪽 포인터 초기화
27-
28-
while (left < right) {
29-
int sum = nums[left] + nums[right]; // 현재 두 요소의 합 계산
30-
if (sum == target) {
31-
return {left, right}; // 합이 target과 일치하는 경우 현재 인덱스 반환
32-
} else if (sum < target) {
33-
left++; // 합이 target보다 작으면 왼쪽 포인터를 오른쪽으로 이동
34-
} else {
35-
right--; // 합이 target보다 크면 오른쪽 포인터를 왼쪽으로 이동
36-
}
37-
}
38-
39-
// 합이 target과 일치하는 두 요소가 없는 경우 빈 벡터 반환
40-
return {};
41-
}
42-
43-
int main() {
44-
vector<int> nums = {2, 7, 11, 15};
45-
int target = 9;
46-
47-
vector<int> result = twoSum(nums, target);
48-
49-
if (result.size() == 2) {
50-
cout << "Indices of the two elements whose sum is equal to target:" << endl;
51-
cout << result[0] << " " << result[1] << endl;
52-
} else {
53-
cout << "No such elements found!" << endl;
54-
}
55-
56-
return 0;
57-
}
58-
59-
```
6072

6173
---
6274

0 commit comments

Comments
 (0)