문제
N개의 수로 이루어진 수열이 주어집니다.
이 수열에서 연속부분수열의 합이 특정숫자 M이 되는 경우가 몇 번 있는지 구하는 프로그램을 작성하세요.
만약 N=8, M=6이고 수열이 다음과 같다면
1 2 1 3 1 1 1 2
합이 6이 되는 연속부분수열은 {2, 1, 3}, {1, 3, 1, 1}, {3, 1, 1, 1}로 총 3가지입니다.
▣ 입력설명
첫째 줄에 N(1≤N≤100,000), M(1≤M≤100,000,000)이 주어진다.
수열의 원소값은 1,000을 넘지 않는 자연수이다.
▣ 출력설명
첫째 줄에 경우의 수를 출력한다.
▣ 입력예제 1
8 6
1 2 1 3 1 1 1 2
▣ 출력예제 1
3
풀이
two pointer, lt와 rt를 두고 왼쪽 인덱스에서 오른쪽 덱스까지의 합이 m과 같은지 계속 체크해가면서 인덱스를 이동하는 sliding window 문제이다.
처음에 풀 때 아이디어는 맞았는데, 세부 조건들이 헷갈려서 계속 틀렸다. 특히 while문으로 lt를 계속 이동시킬 수도 있다는 거랑, sum 값이 조건에 따라 계속 변동하면서 다시 체크해야 한다는 게 조금 어려웠다.
- sum == m이면
answer++;
(답 카운트) - sum >= m 이 아닐때까지 while문 돌림.
sum -= 맨 왼쪽값;
(lt 우측한칸 이동)- sum값이 바뀌었으므로 다시 체크, sum==m이면
answer++;
(답 카운트)
- sum값이 바뀌었으므로 다시 체크, sum==m이면
* while문을 쓰는 이유는, 예를 들어 1 (lt) , 1, 1, 1 ,1, 5(rt) 일 경우 lt부터 rt까지의 합이 m과 같거나 클때까지 lt를 계속 이동시켜야 하기 때문이다.
자세한 풀이는 주석으로 달아놓았다.
코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();//배열 개수
int m = in.nextInt();//합이 m이 되는 연속부분수열 몇가지인지 구하기
int[] arr = new int[n];
for(int i=0; i<n; i++) {
arr[i] = in.nextInt();
}
int answer = 0, sum = 0;
int lt = 0;
for(int rt=0; rt<n; rt++){ //(1) rt 증가
sum += arr[rt]; // (2) rt 인덱스 값 누적합
if(sum == m) answer++; //(3) sum이 m과 같으면 카운트
//주의!!!
while(sum >= m) { //(4) (3)을 거친 sum이 m보다 크거나 같으면
sum-= arr[lt++]; //맨 왼쪽 값 빼고
if(sum == m) answer++; //m과 같으면 카운트
}
}
System.out.print(answer);
}
}
'PS(Java) > 인프런 강의 문제' 카테고리의 다른 글
[PS] 인프런 강의 - Two Pointers, Sliding window, Math 6. 최대 길이 연속부분수열 (0) | 2022.10.24 |
---|---|
[PS] 인프런 강의 - Two Pointers, Sliding window, Math 5. 연속된 자연수의 합 (0) | 2022.10.24 |
[PS] 인프런 강의 - Two Pointers, Sliding window, Math 3. 최대 매출 (0) | 2022.10.23 |
[PS] 인프런 강의 - Two Pointers, Sliding window, Math 2. 공통원소 구하기 (0) | 2022.10.23 |
[PS] 인프런 강의 - Two Pointers, Sliding window, Math 1. 두 배열 합치기 (0) | 2022.10.21 |