5 minute read

2023-06-28

3단계 - 반복문



목차



25314 번 문제


문제

오늘은 혜아의 면접 날이다. 면접 준비를 열심히 해서 앞선 질문들을 잘 대답한 혜아는 이제 마지막으로 칠판에 직접 코딩하는 문제를 받았다. 혜아가 받은 문제는 두 수를 더하는 문제였다. C++ 책을 열심히 읽었던 혜아는 간단히 두 수를 더하는 코드를 칠판에 적었다. 코드를 본 면접관은 다음 질문을 했다. “만약, 입출력이 $N$바이트 크기의 정수라면 프로그램을 어떻게 구현해야 할까요?”

혜아는 책에 있는 정수 자료형과 관련된 내용을 기억해 냈다. 책에는 long int는 $4$바이트 정수까지 저장할 수 있는 정수 자료형이고 long long int는 $8$바이트 정수까지 저장할 수 있는 정수 자료형이라고 적혀 있었다. 혜아는 이런 생각이 들었다. “int 앞에 long을 하나씩 더 붙일 때마다 $4$바이트씩 저장할 수 있는 공간이 늘어나는 걸까? 분명 long long long int는 $12$바이트, long long long long int는 $16$바이트까지 저장할 수 있는 정수 자료형일 거야!” 그렇게 혜아는 당황하는 면접관의 얼굴을 뒤로한 채 칠판에 정수 자료형을 써 내려가기 시작했다.

혜아가 $N$바이트 정수까지 저장할 수 있다고 생각해서 칠판에 쓴 정수 자료형의 이름은 무엇일까?


입력

첫 번째 줄에는 문제의 정수 $N$이 주어진다. $(4\le N\le 1\, 000$; $N$은 $4$의 배수 $)$ 


출력

혜아가 $N$바이트 정수까지 저장할 수 있다고 생각하는 정수 자료형의 이름을 출력하여라.



import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

class Main{
    public static void main(String args[]) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int input = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        
        for(int i = 0; i<input/4; i++){
            sb.append("long ");
        }
        sb.append("int");
        System.out.println(sb);
    }
}
정답


메모리 시간
14180 KB 124 ms





15552 번 문제


문제

본격적으로 for문 문제를 풀기 전에 주의해야 할 점이 있다. 입출력 방식이 느리면 여러 줄을 입력받거나 출력할 때 시간초과가 날 수 있다는 점이다.

C++을 사용하고 있고 cin/cout을 사용하고자 한다면, cin.tie(NULL)과 sync_with_stdio(false)를 둘 다 적용해 주고, endl 대신 개행문자(\n)를 쓰자. 단, 이렇게 하면 더 이상 scanf/printf/puts/getchar/putchar 등 C의 입출력 방식을 사용하면 안 된다.

Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.

Python을 사용하고 있다면, input 대신 sys.stdin.readline을 사용할 수 있다. 단, 이때는 맨 끝의 개행문자까지 같이 입력받기 때문에 문자열을 저장하고 싶을 경우 .rstrip()을 추가로 해 주는 것이 좋다.

또한 입력과 출력 스트림은 별개이므로, 테스트케이스를 전부 입력받아서 저장한 뒤 전부 출력할 필요는 없다. 테스트케이스를 하나 받은 뒤 하나 출력해도 된다.

자세한 설명 및 다른 언어의 경우는 이 글에 설명되어 있다.

이 블로그 글에서 BOJ의 기타 여러 가지 팁을 볼 수 있다.


입력

첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.


출력

각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다..



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

class Main{
    public static void main(String args[]) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine());
        
        for(int i = 0; i<n; i++){
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            bw.write(Integer.parseInt(st.nextToken())+Integer.parseInt(st.nextToken())+"\n");
            bw.flush();
        }
        
    }
}
시간 초과



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

class Main{
    public static void main(String args[]) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine());
        
        for(int i = 0; i<n; i++){
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            bw.write(a+b+"\n");
        
        }
        bw.flush();
        
    }
}
정답


메모리 시간
236556 KB 872 ms



flush()는 마지막에 한번만 써야하나 보다. Bufferedwriter에 대해서 좀 더 알아봐야겠다.


BufferedWriter란?



모범 답안들을 보니 가장 적은 시간이 걸린 답안은 봐도 잘 모르겠고, 가장 많이 쓴 답안들은 모두 똑같았는데, 어디 공식으로 나와있는 문제인가 보다. 변수 명까지 똑같이 한걸 보면..



import java.io.*;

public class Main {
    public static void main(String... args) throws IOException {
        int testCases = sumUntilNewLine();
        StringBuilder answer = new StringBuilder();
        while (testCases-- > 0) {
            answer.append(sumUntilNewLine()).append('\n');
        }
        System.out.print(answer.toString());
    }

    public static int sumUntilNewLine() throws IOException {
        int sum = 0;
        int buf = 0;
        int c;
        while((c = System.in.read()) != '\n') {
            if (c == ' ') {
                sum += buf;
                buf = 0;
            } else {
                buf = (buf * 10) +(c - '0');
            }
        }
        sum += buf;
        return sum;
    }
}
모범답안


메모리 시간
32000 KB 428 ms



모범 답안의 코드를 한번 살펴보자. 모범답안은 나와는 다르게 StringTokenizer와 BufferedReader, BufferedWriter 모두 쓰지않았다. 기존 내장 객체인 System.in을 사용했다.

while((c = System.in.read()) != '\n') {
    if (c == ' ') {
        sum += buf;
        buf = 0;
    } else {
        buf = (buf * 10) +(c - '0');
    }
}
sum += buf;         


이 부분이 이해가 잘 안됐었다.

buf = (buf * 10) +(c - '0');       

특히나 이 부분이 이해가 잘 안 됐었다. 위 코드는 입력받은 아스키 코드를 정수형으로 받는 코드이다.

여기서 핵심으로 알아야할 것은 c -‘0’ 을 하는 이유이다.

먼저 문자 ‘0’의 ASCII 코드는 48이다. 그리고 ‘9’까지 ASCII코드는 순차적으로 1씩 증가 한다.

그래서 c가 받아온 문자의 ASCII코드에서 ‘0’의 ASCII코드 값을 빼면 정수가 되는 것이다.

그리고 c는 System.in.read()를 통해 한 문자 씩 받아온다. 그래서 처음 입력된 정수가 여러자리 수 인 경우 이전 buf값에 *10을 해줘서 한자리씩 높이는 것이다.


그러다가 공백을 만나면 sum값에 buf값을 저장해 놓고 buf값을 0으로 초기화 한다. 그리고선 그 다음 정수를 다시 buf에 저장하는 것이다.





11021 번 문제


문제

두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오


입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다.

각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)


출력

각 테스트 케이스마다 “Case #x: “를 출력한 다음, A+B를 출력한다. 테스트 케이스 번호는 1부터 시작한다.



import java.io.*;
class Main{
    public static void main(String args[]) throws IOException{
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int a;
        int i = 1;
        
        while(n-- >0){
            a = sum();
            bw.write("Case #"+i+": "+a+"\n");
            i++;
        }
        bw.flush();
        bw.close();
    }
    public static int sum() throws IOException{
        int sum = 0;
        int buf = 0;
        int c = 0;
        
        while((c = System.in.read()) != '\n'){
            if(c == ' '){
                sum += buf;
                buf = 0;
            } else {
                buf = (buf*10)+(c-'0');
            }   
        }
        sum += buf; 
        return sum;
    }
}
시간 초과



import java.io.*;
import java.util.StringTokenizer;

class Main{
    public static void main(String args[]) throws IOException{
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        int n = Integer.parseInt(br.readLine());

        for(int i = 1 ; i<n+1 ; i++){
            st = new StringTokenizer(br.readLine(), " ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            bw.write("Case #"+ i + ": "+(a+b));
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}
정답


메모리 시간
16020 KB 156 ms