[BaekJoon] 2444번 - 별 찍기 - 7 (java)

1. 문제

👉 문제 바로가기

- 조건

시간 제한 메모리 제한
1초 128MB


- 문제

예제를 보고 규칙을 유추한 뒤에 별을 찍어 보세요.

- 입력

첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.

- 출력

첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.

- 예제

  입력      출력  
5
***
*****
*******
*********
*******
*****
***





2. 풀이



2-0. 알고리즘

for (초기식; 조건식; 증감식) {
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문 작성;
}



이 문제는 이중 for 문 을 사용해야 한다.
일단 바깥쪽 for 문을 2개로 나눠 별이 증가하는 for 문과 감소하는 for 문을 따로 작성한다.

◾ 별이 증가하는 for 문은 int i = 0 부터 i < N 까지 loop를 돌린다.
◾ 별이 감소하는 for 문은 int i = N - 1 부터 i > 0 까지 loop를 돌린다.


위의 for 문 안에 각각 또다른 2개의 for 문을 써줘야 한다.
별들이 가운데를 기준으로 나열되어 있어, 조건에 따라 “ “(공백)과 “*“을 함께 출력해야하기 때문이다.

1. 별이 증가하는 for 문
◾ “ “(공백) 출력의 경우이다.
첫째줄에서 i = 0 일 때 공백이 N-1 개,
둘째줄에서 i = 1 일 때 공백이 N-2 개,
마지막줄에서 i = N-1 일 때 공백이 0 개이다.
int j = 1 부터 j < N - i 까지 loop 를 돌며 “ “(공백)을 출력한다.

◾ “*” 출력의 경우이다.
첫째줄에서 i = 0 일 때 별이 1 개,
둘째줄에서 i = 1 일 때 별이 3 개,
마지막줄에서 i = N-1 일 때 별이 2 * i + 1 개이다.
int j = 0 부터 j < 2 * i + 1 까지 loop 를 돌며 “*”을 출력한다.


2. 별이 감소하는 for 문
◾ “ “(공백) 출력의 경우이다.
첫째줄에서 i = N-1 일 때 공백이 1 개,
둘째줄에서 i = N-2 일 때 공백이 2 개,
마지막줄에서 i = 1 일 때 공백이 N-i 개이기 때문에
int j = 0 부터 j < N-i 까지 loop 를 돌며 “ “(공백)을 출력한다.

◾ “*” 출력의 경우이다.
첫째줄에서 i = N-1 일 때 별이 2 * i - 1 개,
마지막줄에서 i = 1 일 때 별이 1 개이기 때문에
int j = 0 부터 j < 2 * i - 1 까지 loop 를 돌며 “*”을 출력한다.





2개의 입력방식을 사용해서 결과를 출력해보자.

  1. Scanner 클래스
  2. BufferedReader 클래스



2-1. Scanner 클래스

import java.util.Scanner;

public class Main{

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

        for(int i=0;i<N;i++){
            for(int j=1;j<N-i;j++){
                System.out.print(" ");
            }
            for(int j=0;j<2*i+1;j++){
                System.out.print("*");
            }
            System.out.println();
        }
        
        for(int i=N-1;i>0;i--){
            for(int j=0;j<N-i;j++){
                System.out.print(" ");
            }
            for(int j=0;j<2*i-1;j++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

위와같이 객체를 생성할 때, Scanner(System.in) 에서 System.in 은 입력한 값을 Byte 단위로 읽는 것을 뜻한다.

int형 데이터를 입력받기 위해 nextInt() 메서드를 사용한다.

System.out.println(); 는 줄바꿈("\n") 을 의미한다.
for-loop를 돌며 한 줄을 출력하고 줄바꿈한다.



[여기서 잠깐!]

Scanner에 대해 더 자세히 알고싶다면 여기 를 클릭하세요




2-2. BufferedReader 클래스 사용

3가지 출력 방식으로 문제를 풀어보고 비교해보자.

     ① System.out.println()
     ② BufferedWriter
     ③ StringBuilder





① BufferedReader + System.out.println()

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

public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        int N = Integer.parseInt(br.readLine()); 

        for(int i=0;i<N;i++){
            for(int j=1;j<N-i;j++){
                System.out.print(" ");
            }
            for(int j=0;j<2*i+1;j++){
                System.out.print("*");
            }
            System.out.println();
        }
        
        for(int i=N-1;i>0;i--){
            for(int j=0;j<N-i;j++){
                System.out.print(" ");
            }
            for(int j=0;j<2*i-1;j++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

Integer.parseInt()을 사용해 br.readLine()으로 읽어온 String형 데이터를 int형으로 변환시켜준다.





② BufferedReader + BufferedWriter

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

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

        for(int i=0;i<N;i++){
            for(int j=1;j<N-i;j++){
                bw.write(" ");
            }
            for(int j=0;j<2*i+1;j++){
                bw.write("*");
            }
            bw.write("\n");
        }
        
        for(int i=N-1;i>0;i--){
            for(int j=0;j<N-i;j++){
                bw.write(" ");
            }
            for(int j=0;j<2*i-1;j++){
                bw.write("*");
            }
            bw.write("\n");
        }
        bw.flush();
        bw.close();
    }
}

BufferedWriter 클래스의 write() 메소드는 데이터를 내부 버퍼에 저장하고, flush() 메소드 를 사용해 버퍼를 비우고 데이터를 출력한다.

BufferedWriter 클래스의 write() 메소드는 단독으로 int 형 값만 넣을 경우 아스키 코드값으로 인식되기 때문에 다른 문자가 출력된다. 때문에 반드시 문자열과 int 형을 함께 넣어줘야 int 값을 제대로 출력할 수 있다.



[여기서 잠깐!]

BufferedWriter 클래스에 대해 더 알아보고 싶으면 여기를 클릭하면 된다.





③ BufferedReader + StringBuilder

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

public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        int N = Integer.parseInt(br.readLine()); 

        for(int i=0;i<N;i++){
            for(int j=1;j<N-i;j++){
                sb.append(" ");
            }
            for(int j=0;j<2*i+1;j++){
                sb.append("*");
            }
            sb.append("\n");
        }
        
        for(int i=N-1;i>0;i--){
            for(int j=0;j<N-i;j++){
                sb.append(" ");
            }
            for(int j=0;j<2*i-1;j++){
                sb.append("*");
            }
            sb.append("\n");
        }
        System.out.println(sb);
    }
}

StringBuilder 클래스는 문자열을 동적으로 조작하기 위한 클래스로, append() 를 사용해 문자열을 추가하여 새로운 문자열을 생성한다.

append() 안에 “\n”를 더하기 연산하지 않고 위와 같이 분리해서 쓰면 타입 변환과 문자열 연결 연산이 추가적으로 발생하지 않고 StringBuilder에 직접 추가하기 때문에 보다 더 효율적이고 빠르다.





3. 성능 비교

image

위에서 부터 순서대로

BufferedReader + StringBuilder
BufferedReader + BufferedWriter
BufferedReader + System.out.println()
Scanner

위와같이 입력 메소드와 알고리즘 구현 방법에 따라 시간이 달라질 수 있다.

입력의 경우 숫자 하나만 입력받기 때문에 큰 차이가 없다.

출력의 경우 System.out.println() 와 나머지 2개 사이의 차이는 크다.
출력양이 많기 때문에 확실히 BufferedWriter 로 모아서 한번에 출력하는 것과 StringBuilder 로 문자열을 더하기 연산해서 출력하는 것이 훨씬 빠른 것을 볼 수 있다.





관련 페이지

Categories:

Updated:

Leave a comment