2023. 6. 1. 23:41ㆍ백준
https://www.acmicpc.net/problem/11659
11659번: 구간 합 구하기 4
첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j
www.acmicpc.net
array[]에서 i 부터 j 까지 의 수들을 더하면 된다.
아무생각 없이 그냥 이중for문 썼는데
이렇게 시간 초과가 뜬다.
시간 복잡도를 줄이려면 당연히 이중for문을 없애야 되겠지
구간 합을 구하는 공식으로 풀면 된다.
사실 문제 제목 자체가 '구간 합 구하기'니까 당연한 소리다.
예시로 주어진 배열 A는 [ 5, 4, 3, 2, 1 ]이다.
합 배열을 만들어주면
배열 S[ 5, 9, 12, 14, 15 ]가 만들어진다.
합 배열을 만드는 공식은
S[ i ] = S[ i - 1 ] + A[ i ]
이다.
이해가 되는가?
아 그러면 배열A와 합 배열S를 만들어서 구하면 되는 건가?
땡이다.
아니다.
굳이 불필요하게 배열을 하나 더 만들 필요 없다.
쓸 데 없이 for문 하나 추가하여 계산 시간을 늘릴 필요는 없다.
그러면 이제 i에서 j까지의 합을 구하는 공식을 알아보자
S[ j ] - S [ i - 1]이다.
2를 구하고 싶다면 5(전체)에서 3(나머지)을 빼면 된다.
해당 공식도 똑같다.
전체 합 ( j )에서 시작할 부분 이전 ( i )을 빼주면 된다.
이게 끝이다.
하지만 굳이 배열A를 만들어 줄 필
이전 코드
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(bf.readLine());
int arrayCount = Integer.parseInt(st.nextToken());
int repeatCount = Integer.parseInt(st.nextToken());
Integer[] array = new Integer[arrayCount];
st = new StringTokenizer(bf.readLine());
for (int i = 0; i < arrayCount; i++) array[i] = Integer.parseInt(st.nextToken());
int start;
int end;
int sum;
for (int i = 0; i < repeatCount; i++) {
st = new StringTokenizer(bf.readLine());
sum = 0;
start = Integer.parseInt(st.nextToken()) - 1;
end = Integer.parseInt(st.nextToken()) - 1;
for (int j = start; j < end + 1; j++) sum += array[j];
bw.write(String.valueOf(sum));
bw.newLine();
}
bw.flush();
bw.close();
}
문제를 읽어보니 N의 범위로 보아 int로는 안 되어 long으로 바꿔주었다.
수정 후 코드
import java.io.*;
import java.util.*;
public class Main {
private static long[] array;
private static long[] subArray;
private static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine());
int arrayCount = Integer.parseInt(st.nextToken());
int repeatCount = Integer.parseInt(st.nextToken());
array = new long[arrayCount];
subArray = new long[arrayCount + 1];
st = new StringTokenizer(bf.readLine());
for (int i = 1; i <= arrayCount; i++) buildSubArray(i, Integer.parseInt(st.nextToken()));
int startIndex;
int endIndex;
for (int i = 0; i < repeatCount; i++) {
st = new StringTokenizer(bf.readLine());
startIndex = Integer.parseInt(st.nextToken());
endIndex = Integer.parseInt(st.nextToken());
findSubBySection(startIndex, endIndex);
}
bw.flush();
bw.close();
}
private static void buildSubArray(int i, Integer element) {
subArray[i] = subArray[i - 1] + element;
}
private static void findSubBySection(int i, int j) throws IOException {
long sub = subArray[j] - subArray[i - 1];
bw.write(String.valueOf(sub));
bw.newLine();
}
}
'백준' 카테고리의 다른 글
[ 백준 ] [ JAVA ] 1018 체스판 다시 칠하기 (0) | 2023.06.04 |
---|---|
[ 백준 ] [ JAVA ] 1193 분수 찾기 (0) | 2023.06.01 |
[ 백준 ] [ JAVA ] 1236 성 지키기 (0) | 2023.05.30 |
[ 백준 ] [ JAVA ] 1110 더하기 사이클 (0) | 2023.05.30 |