일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Queue
- 백엔드스쿨
- 탄력근무
- 개발자
- YBM전화영어
- 원격근무
- 제로베이스
- JavaScript
- 그래프탐색
- 전화영어
- BFS
- OAuth
- 최단경로문제
- OpenAPI프로젝트
- 프로젝트진행
- 탐색알고리즘
- Node.js
- array
- Spring
- 자바스크립트
- npm
- 자료구조
- 내돈내산
- 교육철학과 교육사
- 시급합니다
- webServlet
- 백엔드공부
- java
- maven
- 백엔드
- Today
- Total
개발자취
BOJ | Gold 4/1806/부분합 본문
1. 문제 이해
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
입력값이 길이가 N인 수열에 해당한다. 이 수열의 부분합을 구하는데, 또다른 입력 값인 S 이상이 되는 경우를 찾는다. 그 중에서 연속된 수의 길이 중 가장 짧은 길이를 구하는 것이다. 이때 부분합을 구하는 방법으로는 1차원 배열이므로 투포인터 알고리즘을 적용한다.
* 투포인터(Two Pointer) 알고리즘 : left와 right로 구분한 두 포인터를 좌우로 이동해가면서 요구조건에 맞는 답을 찾는 풀이법이다.
2. 로직
2-1) 로직 플로우
정수 배열은 수열의 길이는 N+1로 초기화 시킴(right의 index 때문, [그림 3] 참고). 정수배열로 입력 받을 때 입력받은 수열 전체의 합이 S이상이 되는 경우를 체크하기 위해 total 변수를 생성하고, total에 입력받은 값들을 누적시킨다. 그리고 두 개의 포인터를 사용하여 탐색하는 로직 직전, 입력받은 값들과 S가 일치하는지를 확인한다. 그리고 두 개의 포인터를 left, right로 지정하여 0으로 초기화 시킨 total에 누적시킨다. 이때 left와 right의 차이로 수열 길이의 최솟값을 구하고, 최솟값을 구하기 위해 모든 위치를 탐색해야한다. 그래서 누적합이 S보다 크거나 같으면 left를 증가시켜서 누적합에서 빼주고, 그렇지 않으면 right를 증가시키고 total에서 그 위치의 요소를 더한다.
2-2) 로직 상세
1) 입력 받은 데이터를 통해 수열을 저장하는 길이가 N+1인 배열을 생성 후 그 배열에 수열의 각 요소를 할당함
2) 입력 받는 동시에 수열의 전체 합(total)을 구하고, 입력이 끝난 뒤 S와 일치하는지를 확인
3) total을 0으로 초기화시킴, left는 0으로 초기화 시킴, right는 수열의 길이-1로 초기화 시킴, 수열의 길이 최솟값을 구할 min은 Integer.MAX_VALUE로 초기화함.
4) 두 포인터를 사용하여 누적합의 길이를 구하는 로직에 통과시킴.
5) 누적합이 S보다 크거나 같은 경우 left와 right의 차이를 min에 할당.
6) 누적합이 S보다 크면 left를 증가시킨 뒤 누적합에서 빼주고, 그렇지 않으면 right를 증가시켜 total에 그 위치의 요소를 누적합에 더함.
7) left와 right가 수열의 길이가 될 때까지 탐색을 반복.
8) min값이 초기화시킨 Integer.MAX_VALUE인지를 비교하여 true면 "0"을 출력 시키고, 그렇지 않으면 수열의 최솟값을 출력시킴.
3. 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
int[] nums = new int[n+1];
int total = 0;
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
nums[i] = Integer.parseInt(st.nextToken());
total += nums[i];
}
if(total == s) System.out.println(nums.length-1);
else {
int min = Integer.MAX_VALUE;
int left = 0;
int right = 0;
total = 0;
while (left <= n && right <= n) {
if (total >= s && min > right - left) {
min = right - left;
}
if (total >= s) total -= nums[left++];
else total += nums[right++];
}
if(min == Integer.MAX_VALUE) System.out.println("0");
else System.out.println(min);
}
}
}
https://www.acmicpc.net/problem/1806
직접 문제를 풀어봄으로써 위 내용을 확인하셨으면 좋겠습니다. 감사합니다 :)
'개발 > Dev | 코딩테스트' 카테고리의 다른 글
BOJ | Silver 1/5638/수문 (0) | 2023.07.22 |
---|---|
Leetcode | medium / 46.Permutations (0) | 2023.07.21 |
JAVA | Comparator 와 Comparable (0) | 2023.07.15 |
BOJ | Gold 4/11657/타임머신 (0) | 2023.07.14 |
BOJ | Silver 1/1932/정수 삼각형 (0) | 2023.07.05 |