백준 알고리즘 3단계

5 minute read

📖 백준 알고리즘 3단계

❗ 3단계 풀이

2022-02-13 백준알고리즘

Q.2739

2739.png

제출 코드

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt();
		sc.close();

		for(int i = 1; i < 10; i++) {
			System.out.println(a+" * " + i +" = " + a*i);
		}
	}
}

Q.10950

10950.png

제출 코드

1.번

import java.util.Scanner;

public class Main {
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int c = sc.nextInt(); // 몇 개의 수를 출력할건지 설정
		int[] arr = new int[c]; // 입력한 수를 배열로 받아주기

		for(int i = 0; i < c; i++) {
			int a = sc.nextInt(); // a 값 입력
			int b = sc.nextInt(); // b 값 입력
			arr[i] = a + b; // 0번 인덱스부터 a + b의 값을 배열에 저장
		}
		for(int j = 0; j < c; j++) {
			System.out.println(arr[j]); // arr배열에 저장된 값들을 인덱스 순으로 출력
		}sc.close();
	}
}

2번

import java.util.Scanner;

public class Main {
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int c = sc.nextInt(); // 몇 개의 수를 출력할건지 설정
		int[] arr = new int[c]; // 입력한 수를 배열로 받아주기

		for(int i = 0; i < c; i++) {
			int a = sc.nextInt(); // a 값 입력
			int b = sc.nextInt(); // b 값 입력
			arr[i] = a + b; // 0번 인덱스부터 a + b의 값을 배열에 저장
		}
		sc.close();
		for(int j : arr) {  // arr에 담긴 값들인 j를 하나씩 선택
			System.out.println(j); // arr에 담긴 값들인 j를 하나씩 출력
		}
	}
}

💡 배열 부분에서 2가지의 방법 존재

Q.8393

8393.png

제출 코드

import java.util.Scanner;

public class Main {
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		sc.close();
		int sum = 0;
		for(int i = 1; i <= n; i++) {
			sum += i; // sum = sum + i
		}
		System.out.println(sum);
	}
}

❗️ Q.15552

15552.png

✏️ 이전의 방법과는 다르게 Scanner와 System.out.println을 사용 할 수 없다.

💡 문제

  1. 시간제한이 1.5초 즉 1500ms 이내여야 한다.
  2. Scanner와 System.out.print를 사용하면 시간 초과
  3. Scanner와 System.out.print 보다 빠른 BufferedReader와 BufferedWriter를 이용해야 한다.

1. 그렇다면 BufferedReader가 Scanner보다 빠른 이유는?

버퍼를 이용하기 때문

buffer.png

입력도 사용자가 키보드에 누를 때 마다 전달을 하는 것이 아니라 버퍼에 용량만큼 모았다가 전달해주는 것이다.

생각해보면 내가 현재 위치에서 10m 떨어진 곳에서 어떤 물건을 옮겨야하는데 하나씩 옮기는 것보단 한번에 최대로 옮길 수 있는 만큼을 옮겨야 덜 힘들고 빠를 것이다.

출력도 마찬가지로 버퍼를 거쳐서 간접적으로 출력장치로 전달되기에 시스템의 데이터처리 효율성을 높여주며 버퍼스트림을InputStreamReader / OutputStreamWriter를 같이 사용하여 버퍼링을 하게 되면 입출력 스트림으로부터 미리 버퍼에 데이터를 갖다 놓기 때문에 보다 효율적인 입출력이 가능하다.

buffer2.png

2. BufferedReader

Scanner를 통해 입력을 받을경우 Space Enter를 모두 경계로 인식하기에 입력받은 데이터를 가공하기 매우 편리하다. 하지만 그에비해 BufferedReader는 Enter만 경계로 인식하고 받은 데이터가 String으로 고정되기때문에 입력받은 데이터를 가공하는 작업이 필요할경우가 많다(Scanner에 익숙한 나는 적응 기간이 필요하다). 하지만 많은 양의 데이터를 입력받을경우 BufferedReader를 통해 입력받는 것이 효율면에서 훨씬 낫다.

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

public class Test{
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();
        int i = Integer.parseInt(s);

    }
  1. BufferedReader의 readLine()을 사용하면 데이터를 라인 단위로 읽을 수 있다. Scanner에서 nextLine()과 같다. readLine 함수의 리턴 값은 String으로 고정되기 때문에 String이 아닌 다른 타입으로 입력을 받으려면 형변환을 꼭 해줘야 한다.
  2. 예외처리를 꼭 해주어야한다. readLine을 할때마다 try & catch를 활용하여 예외처리를 해주어도 되지만 대개 throws IOException을 통하여 작업한다.

3. 그러면 알고리즘 풀다보면 한 줄에 입력을 여러개 받아야 하는 상황이라면?

그때는 StringTokenizer 클래스 또는 String 클래스의 메소드인 Splite을 이용해서 공백을 기준으로 나누면 된다.

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

public class Test{
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();   // 입력을 5 4 로 받음
        StringTokenizer st = new StringTokenizer(s);
        int a = Integer.parseInt(st.nextToken());  //5
        int b = Integer.parseInt(st.nextToken());  //4

        String[] ary = s.split(" ");
        System.out.println(a);  //5
        System.out.println(b);  //4

        for (String k : ary) {
            System.out.println(k);   //5 와 4가 나옴
        }

    }
}

readLine()메소드를 이용해서 입력을 받으면 한 줄을 입력으로 받기 때문에 5 4 와 같이 공백을 넣어서 입력을 해도 공백을 포함해서 버퍼에 넣는다. 그래서 공백을 기준으로 나누기 위해서는 첫번째로 StringTokenizer 클래스를 이용하고 두번째로 Splite(“ “)메소드를 이용해서 입력받은 문자를 나눈다.

4. BufferedWriter

System.out.print(“”);와 같이 동일한 기능인 출력을 하는 메소드이다. BufferedWriter 함수 또한 버퍼를 이용하기 때문에 성능이 print메소드 보다 좋다. 알고리즘 풀 때 처럼 많은 양의 출력이 필요하다면 BufferWriter를 사용하는 것이 좋다.

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

public class Test{
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();   // 입력을 5 4 로 받음
        StringTokenizer st = new StringTokenizer(s);
        int a = Integer.parseInt(st.nextToken());  //5
        int b = Integer.parseInt(st.nextToken());  //4

        String p = "abcedf";
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        bw.write(p + "\n");


        // write한다고 해서 바로바로 출력되지 않는다.
        // 직접 출력 stream에 반영되는 것이 아니라 성능을 위해 buffer에 저장해두었다가
        // BufferedWriter가 flush되거나 close되었을 때 한번에 출력 stream에 반영하기 때문이다.
        bw.flush();
        bw.write("3");

        // close는 stream을 닫아버리기 때문에 계속 출력하고자 한다면 flush 사용한다.
        // bw.close();

        // 출력내용에 줄바꿈이 필요하다면 newLine 함수를 사용한다.
        bw.write(String.valueOf(b));  // write는 String형만 출력이 가능하므로 정수는 String으로 변환해야함

        bw.flush();
        bw.close();
    }
}
  • 여기서 write() 메소드는 String형으로만 출력이 가능하기 때문에 정수를 출력하려면 String.valueOf() 메소드를 이용해서 String으로 변환을 한 후에 출력을 해야한다.
  • BufferedWriter 의 경우 버퍼를 잡아 놓았기 때문에 반드시 flush() / close() 를 반드시 호출해 주어 뒤처리를 해주어야한다. 그리고 bw.write에는 System.out.println();과 같이 자동개행기능이 없기때문에 개행을 해주어야할 경우에는 \n를 통해 따로 처리해주어야 하는점 잊지말자.

5. Q.15552의 제출코드

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

public 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());

		StringTokenizer st;

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine()," ");
			bw.write((Integer.parseInt(st.nextToken()) + Integer.parseInt(st.nextToken()))+ "\n");
		}
		br.close();

		bw.flush();
		bw.close();

	}
}
  • 모든 입력은 BufferedReader.readLine() 으로 받는다.
  • 테스트 케이스에서 주어지는 두 정수는 문자열 분리를 위해 매 반복마다 StringTokenizer 을 생성과 동시에 문자를 입력받는다. ( st = new StringTokenizer(br.readLine(), “ “);
  • 또한 다음 열에서 각 StringTokenizer 의 토큰 (분리되어있는 문자)을 반환하며, 반환되는 타입은 String 이므로 Integer.parseInt를 통해 int형으로 바꾸어 준다. 이렇게 바꾼 두 토큰을 더해준 값을 BufferedWriter.write() 에 넣어준다. ( bw.write((Integer.parseInt(st.nextToken())+Integer.parseInt(st.nextToken()))+ “\n”); )
  • 필수적으로 버퍼를 비운 뒤(flush) 닫아줘야한다(close).

✏️처음보는 문법과 개념 이기에 15552번은 다시보기

🔍 Information

Categories:

Updated:

Leave a comment