[백준] 11659_구간 합 구하기4 - JAVA

2023. 1. 27. 00:47·알고리즘/알고리즘 유형
반응형

구간 합

구간 합은 배열을 이용하여 시간 복잡도를 더 줄이기 위해 사용하는 알고리즘이다.

구간 합을 이용하려면 합 배열을 구해야 한다.

합 배열 만들기

S[i] = S[i-1] + A[i]
인덱스 0 1 2 3
A 10 10 10 10
S 10 20 30 40

이런 식으로 합 배열을 만든다. S 배열에 값을 계산해서 저장하는 for문의 변수 초기화는 1부터 시작해야한다.

반응형

구간 합 공식

S[j] - S[i-1]

1부터 3까지의 구간 합을 구한다치면 S[3] - S[1-1]이 된다. 40-10 = 30이 된다. A배열의 값이 모두 10이라 뭔가 헷갈릴 수 있으니 다른 배열로도 계산해보자.

인덱스 0 1 2 3
A 10 16 3 49
S 10 26 29 78

위 배열에서도 1부터 3까지의 합을 구해보자. 78-10 = 68이 된다.

 

백준_11659

 

11659번: 구간 합 구하기 4

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j

www.acmicpc.net

 

코드

  • 통과가 된 나의 허접한 코드
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();

        int[] arr = new int[n+1];

        for(int i = 1; i <= n; i++) {
            arr[i] = arr[i-1] + sc.nextInt();
        }

        for(int j = 0; j < m; j++) {
            int start = sc.nextInt();
            int end = sc.nextInt();
            System.out.println(arr[end] - arr[start-1]);
        }
    }
}

 

  • BufferedReader, StringTokenizer를 사용한 코드
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 bufferedReader =
                new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer =
                new StringTokenizer(bufferedReader.readLine());
        int suNo = Integer.parseInt(stringTokenizer.nextToken());
        int quizNo = Integer.parseInt(stringTokenizer.nextToken());
        long[] s = new long[suNo+1];
        stringTokenizer = new StringTokenizer(bufferedReader.readLine());
        for(int i = 1; i <= suNo; i++) {
            s[i] = s[i-1] + Integer.parseInt(stringTokenizer.nextToken());
        }
        for(int q = 0; q < quizNo; q++) {
            stringTokenizer = new StringTokenizer(bufferedReader.readLine());
            int i = Integer.parseInt(stringTokenizer.nextToken());
            int j = Integer.parseInt(stringTokenizer.nextToken());
            System.out.println(s[j] - s[i-1]);
        }
    }
}
반응형

 

제출 결과

첫 번째 제출이 BufferedReader와 StringTokenizer를 사용한 코드이고, 두 번째 제출이 내가 작성한 코드이다. 메모리나 시간 면에서 첫 번째 제출이 더 우수하게 나왔다. 일단 큰 차이는 Scanner와 BufferedReader에서 차이가 난다.

Scanner와 BufferedReader

익숙한 Scanner는 다양한 기능이 지원되기 때문에 무겁다보니 속도가 느리다. 반대로 문자열에 최적화 된 BufferedReader의 경우엔 버퍼를 이용해서 입력의 효율을 높이기 때문이 보다 더 빠르다. 다만 String 타입으로만 입력을 받아들여 String 외 다른 타입에 사용할 때는 변환이 추가적으로 필요하다. 그래서 내가 작성한 코드에 BufferedReader를 적용시켜봤다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] strArr = br.readLine().split(" ");
        int n = Integer.parseInt(strArr[0]);
        int m = Integer.parseInt(strArr[1]);

        int[] arr = new int[n+1];
        strArr = br.readLine().split(" ");
        for(int i = 1; i <= n; i++) {
            arr[i] = arr[i-1] + Integer.parseInt(strArr[i-1]);
        }

        for(int j = 0; j < m; j++) {
            strArr = br.readLine().split(" ");
            int start = Integer.parseInt(strArr[0]);
            int end = Integer.parseInt(strArr[1]);
            System.out.println(arr[end] - arr[start-1]);
        }
    }
}

시간이 줄긴 줄었지만 엄청나게 드라마틱하게 줄진 않았다. 그렇다면 또 다른 부분에서 성능 차이가 난다는 것이다. 그건 바로바로 두 번째 split과 StringTokenizer이다.

반응형

 

split과 StringTokenizer

익숙한 split()은 문자열을 토큰으로 잘라낸 결과를 배열에 담아 반환하고, StringTokenizer는 데이터를 토큰으로 바로바로 잘라서 반환하기 때문에 성능 차이가 난다.

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 m = Integer.parseInt(st.nextToken());

        int[] arr = new int[n+1];
        st = new StringTokenizer(br.readLine());
        for(int i = 1; i <= n; i++) {
            arr[i] = arr[i-1] + Integer.parseInt(st.nextToken());
        }

        for(int j = 0; j < m; j++) {
            st = new StringTokenizer(br.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            System.out.println(arr[end] - arr[start-1]);
        }
    }
}

처음 내가 작성했던 코드 시간은 2916ms였다. BufferedReader와 StringTokenizer를 사용하니 1888ms가 나왔다. 무려 1028ms나 차이났다! 앞으로는 BufferedReader와 StringTokenizer를 잘 사용해봐야겠다.

 

반응형
저작자표시 비영리 변경금지 (새창열림)
'알고리즘/알고리즘 유형' 카테고리의 다른 글
  • [백준] 1940_주몽 - JAVA
  • [백준] 2018_수들의 합5 - JAVA
  • [백준] 10986_나머지 합 - JAVA
  • [백준] 11660_구간 합 구하기5 - JAVA
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    토비의스프링부트
    react
    oracle
    토이프로젝트
    전자정부프레임워크
    에러해결
    프론트엔드
    springboot
    자바스크립트
    백준
    RESTful
    SpringBoot를 이용한 RESTful Web Service 개발
    SQL
    JPA
    Spring
    운영체제
    코딩테스트
    프로그래머스
    개발자
    방통대
    알고리즘
    Java
    IT
    egov
    인프런
    기출문제
    넥사크로
    스프링부트
    MSA
    QueryDSL
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
[백준] 11659_구간 합 구하기4 - JAVA
상단으로

티스토리툴바