728x90
문제
접근 방식
분명 이전 투포인터 문제들과 비슷한 문제라 쉽게 풀 수 있을거라 생각했는데
반환값의 범위를 잘못 생각해서 맞왜틀을 시전하느라 시간을 날려먹었다.
수열이 수의 범위가 1 ~ 100,000까지인 10만개의 수들로 이루어져 있어서
결과가 인트형으로 될줄 알았는데 혹시 싶어 long으로 바꿔보니 맞았다...
(왜 10만 * 10만을 10억으로 생각하고 있었지...새벽이라 정신줄을 놓고 했나보다)
{1, 2, 3, 2, 1, 1, 2, 3, 2, 1, 1, 2, 3, 2, 1}
위와 같은 수열이 주어졌을 때 중복되지 않는 수로만 이루어지는 경우를 살펴보자
{1, 2, 3, 2, 1, 1, 2, 3, 2, 1, 1, 2, 3, 2, 1}
// i[0]
1, 12, 123
// i[1]
2, 23
// i[2]
3, 32, 321
// i[3]
2, 21
// i[4]
1
// i[5]
1, 12, 123
// i[6]
2, 23
...
각 시작점을 기준으로 숫자들의 등장 여부를 기록해두면서
다음 숫자가 기존에 등장했던 숫자일 경우에는 중복된 숫자이기 때문에
이 시점을 브레이크 포인트로 잡고 현재 까지 연속된 부분 수열의 길이를
결과를 저장할 변수에 누적해서 더해주면 된다.
위에서도 언급했지만 이 때 결과를 저장할 변수를 long 타입으로 해야한다...
1 > 2 > 3 > 2(기존에 등장함)
즉, 1에서 출발 했을 때, 4번째 탐색한 숫자는 중복되기 때문에
저 시점에서 멈춘 후 현재 까지의 부분 수열인 {1, 2, 3}의 길이만큼
결과 변수에 합해준다.
2 > 3 > 2 (기존에 등장함)
3 > 2 > 1 > 1 (기존에 등장함)
2 > 1 > 1 (기존에 등장함)
1 > 1 (기존에 등장함)
1 > 2 > 3 > 2 (기존에 등장함)
2 > 3 > 2 (기존에 등장함)
...
이제 1로 시작하는 경우는 구했으니 시작 포인터를 1 증가 시킨 후에
위의 과정들을 반복하면 된다.
풀이
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
boolean[] isUsed = new boolean[100001];
long sum = 0;
int end = 0;
for (int start = 0; start < n; start++) {
while (end < n) {
if (isUsed[arr[end]]) break;
isUsed[arr[end++]] = true;
}
sum += end - start;
isUsed[arr[start]] = false;
}
System.out.println(sum);
}
}
'Java > Algorithms' 카테고리의 다른 글
[백준] 2531번 : 회전 초밥 (1) | 2023.12.17 |
---|---|
[백준] 22862번 : 가장 긴 짝수 연속한 부분 수열 (large) (0) | 2023.12.16 |
[백준] 1644번 : 소수의 연속합 (1) | 2023.12.15 |
[백준] 1806번 : 부분합 (0) | 2023.12.15 |
[백준] 2230번 : 수 고르기 (0) | 2023.12.15 |