[인터돌™] 공부 해보자!! 열심히~~~

반응형

문제 : https://www.acmicpc.net/problem/2003

 

문제
N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i]+A[i+1]+…+A[j-1]+A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.

입력
첫째 줄에 N(1≤N≤10,000), M(1≤M≤300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.

출력
첫째 줄에 경우의 수를 출력한다.

 

예제 입력, 출력

  예제 입력 예제 출력
1 4 2
1 1 1 1
3
2 10 5
1 2 3 4 2 5 3 1 1 2
3

 

사용 알고리즘

Two Pointer

 

코드 (자바)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

// 수들의 합 2 : https://www.acmicpc.net/problem/2003
// 투포인터

/*

샘플 입력
10 5
1 2 3 4 2 5 3 1 1 2


샘플 출력
3

 */

public class Main {
	
	public static void main(String[] args) throws Exception{
		int N = 0;	// 숫자의 개수
		int M = 0;	// 주어진 합계
		int[] num;	// 주어진 숫자 배열
		
		// 입력값 처리
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		
		st = new StringTokenizer(br.readLine());
		num = new int[N+1];
		for (int i = 1 ; i<=N ; i++) {
			num[i] = Integer.parseInt(st.nextToken());
		}
		
//		System.out.println(Arrays.toString(num));
		
		// 투포인터로 배열 탐색 (이중으로 for 를 돌리면 시간 초과 나올 듯)
		int pointerA = 1;	// 초기 시작 지점 설정
		int pointerB = 1;	// 초기 시작 지점 설정
		int cnt = 0;		// 숫자의 합이 입력받은 M 과 일치한 횟수를 저장
		int sum = num[pointerA];	// 시작 포인터의 값을 초기 sum 에 더하고 시작
		
		// 두개의 포인터가 배열 끝에 도착할 때 까지 반복
		while (pointerB <= N){
			
//			System.out.println("pointerA : " + pointerA + " pointerB : " + pointerB + " cnt : " + cnt + " sum : " + sum+ " M : " + M);
			
			if (sum > M) { // 합계가 더 큰 경우 A에 있는 값을 sum 에서 빼고 A포인터를 오른쪽으로 이동 
				sum -=num[pointerA];
				pointerA++;
			}else if (sum == M) {
				cnt++; // 합계와 문제에서 주어진 값이 같은 경우 결과 카운트 1 증가
				pointerB++;			// B 포인터를 오른쪽으로 이동
				if (pointerB <= N) { // B 포인터가 배열을 벗어나지 않은 경우에만
					sum +=num[pointerB]; // sum에 현재 배열의 값을 합산
				}
			}else if (sum < M) {
				pointerB++;			// B 포인터를 오른쪽으로 이동
				if (pointerB <= N) { // B 포인터가 배열을 벗어나지 않은 경우에만
					sum +=num[pointerB]; // sum에 현재 배열의 값을 합산
				}
				
			}else {
				System.out.println("이런 경우는 없어요");
			}
		}
		
		System.out.println(cnt);	
	}
}

 

 

 

 

 

 

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band