문제
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
풀이
연속된 수들의 부분합이기 때문에 두개의 포인터를 이용해서 구했다.
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
이렇게 배열이 있다면, left = 0 right = 0 부터 시작해서 S보다 크거나 같으면 left 값을 빼주고 s 보다 작다면 right값을 더해주는 방식으로 풀었다.
while(true) {
if(sum >= s) {
sum -= arr[left++];
}
else if(right >= arr.length) {
break;
}
else if(sum < s) {
sum += arr[right++];
}
if(sum >= s){
min = Math.min(min, right - left);
}
}
위 코드를 보면 이해하기 쉬울 것이다.
S 이상이 됐을 때, 최소갯수를 구하는 것이 문제이므로 그때 최솟값을 저장해준다.
시간복잡도를 줄이는 것이 어려워 보이지만 두 포인터를 이용한 완전탐색을 알고있었다면 반복문을 여러개 사용하지 않고 풀 수있다.
<전체코드>
import java.io.*;
import java.util.*;
public class Main {
static StringBuilder sb = new StringBuilder();
static int n, s;
static long[] arr;
public static void main(String[] args) throws IOException{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
n = Integer.parseInt(st.nextToken());
s = Integer.parseInt(st.nextToken());
st = new StringTokenizer(bufferedReader.readLine());
arr = new long[n];
for(int i = 0 ; i < n ; i++) {
arr[i] = Long.parseLong(st.nextToken());
}
int left = 0, right = 0;
long sum = 0;
int min = Integer.MAX_VALUE;
while(true) {
if(sum >= s) {
sum -= arr[left++];
}
else if(right >= arr.length) {
break;
}
else if(sum < s) {
sum += arr[right++];
}
if(sum >= s){
min = Math.min(min, right - left);
}
}
if(min == Integer.MAX_VALUE) {
min = 0;
}
System.out.println(min);
}
}
'알고리즘 공부 > 완전탐색' 카테고리의 다른 글
[프로그래머스] 보석쇼핑 (0) | 2021.05.06 |
---|---|
[프로그래머스] 소수찾기 (0) | 2021.05.05 |
백준 1759 (암호 만들기) - 조합알고리즘 (0) | 2021.04.14 |
백준 2447 (별 찍기 -10) (0) | 2021.04.14 |
프로그래머스 완전탐색 Level 2 (카펫) (0) | 2021.04.07 |