[BaekJoon] 2445번 - 별 찍기 - 8 (java)
1. 문제
👉 문제 바로가기
- 조건
| 시간 제한 | 메모리 제한 |
|---|---|
| 1초 | 128MB |
- 문제
예제를 보고 규칙을 유추한 뒤에 별을 찍어 보세요.
- 입력
첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.
- 출력
첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.
- 예제
| 입력 | 출력 |
|---|---|
| 5 | * * ** ** *** *** **** **** ********** **** **** *** *** ** ** * * |
2. 풀이
2-0. 알고리즘
조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문 작성;
}
이 문제는 이중 for 문 을 사용해야 한다.
일단 바깥쪽 for 문을 2개로 나눠 별이 감소하는 for 문과 증가하는 for 문을 따로 작성한다.
◾ 별이 감소하는 for 문은 int i = N 부터 i > 0 까지 loop를 돌린다.
◾ 별이 증가하는 for 문은 int i = 1 부터 i < N 까지 loop를 돌린다.
위의 for 문 안에 각각 또다른 2개의 for 문을 써줘야 한다.
별들이 가운데를 기준으로 나열되어 있어, 조건에 따라 “ “(공백)과 “*“을 함께 출력해야하기 때문이다.
1. 별이 증가하는 for 문
◾ 앞부분 “*” 출력의 경우이다.
첫째줄에서 i = 1 일 때 별이 1 개,
마지막줄에서 i = N 일 때 별이 N 개이기 때문에
int j = 0 부터 j < i 까지 loop 를 돌며 “*”을 출력한다.
◾ “ “(공백) 출력의 경우이다.
첫째줄에서 i = 1 일 때 공백이 2(N-1) 개,
둘째줄에서 i = 2 일 때 공백이 2(N-2) 개,
마지막줄에서 i = N 일 때 공백이 0 개이기 때문에
int j = 0 부터 j < 2*(N-i) 까지 loop 를 돌며 “ “(공백)을 출력한다.
◾ 뒷부분 “*” 출력의 경우는 앞부분 “*” 출력과 같다.
2. 별이 감소하는 for 문
◾ 앞부분 “*” 출력의 경우이다.
첫째줄에서 i = 1 일 때 별이 N-1 개,
마지막줄에서 i = N-1 일 때 별이 1 개이기 때문에
int j = 0 부터 j < N-i 까지 loop 를 돌며 “*”을 출력한다.
◾ “ “(공백) 출력의 경우이다.
첫째줄에서 i = 1 일 때 공백이 2 개,
둘째줄에서 i = 2 일 때 공백이 4 개,
마지막줄에서 i = N-1 일 때 공백이 2*i 개이다.
int j = 0 부터 j < 2*i 까지 loop 를 돌며 “ “(공백)을 출력한다.
◾ 뒷부분 “*” 출력의 경우는 앞부분 “*” 출력과 같다.
2개의 입력방식을 사용해서 결과를 출력해보자.
- Scanner 클래스
- 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=1;i<=N;i++){
for(int j=0;j<i;j++){
System.out.print("*");
}
for(int j=0;j<2*(N-i);j++){
System.out.print(" ");
}
for(int j=0;j<i;j++){
System.out.print("*");
}
System.out.println();
}
for(int i=1;i<=N-1;i++){
for(int j=0;j<N-i;j++){
System.out.print("*");
}
for(int j=0;j<2*i;j++){
System.out.print(" ");
}
for(int j=0;j<N-i;j++){
System.out.print("*");
}
System.out.println();
}
}
}
위와같이 객체를 생성할 때, Scanner(System.in) 에서
System.in은 입력한 값을Byte 단위로 읽는 것을 뜻한다.
int형 데이터를 입력받기 위해
nextInt()메서드를 사용한다.
System.out.println(); 는줄바꿈("\n")을 의미한다.
for-loop를 돌며 한 줄을 출력하고 줄바꿈한다.
[여기서 잠깐!]
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=1;i<=N;i++){
for(int j=0;j<i;j++){
System.out.print("*");
}
for(int j=0;j<2*(N-i);j++){
System.out.print(" ");
}
for(int j=0;j<i;j++){
System.out.print("*");
}
System.out.println();
}
for(int i=1;i<=N-1;i++){
for(int j=0;j<N-i;j++){
System.out.print("*");
}
for(int j=0;j<2*i;j++){
System.out.print(" ");
}
for(int j=0;j<N-i;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=1;i<=N;i++){
for(int j=0;j<i;j++){
bw.write("*");
}
for(int j=0;j<2*(N-i);j++){
bw.write(" ");
}
for(int j=0;j<i;j++){
bw.write("*");
}
bw.write("\n");
}
for(int i=1;i<=N-1;i++){
for(int j=0;j<N-i;j++){
bw.write("*");
}
for(int j=0;j<2*i;j++){
bw.write(" ");
}
for(int j=0;j<N-i;j++){
bw.write("*");
}
bw.write("\n");
}
bw.flush();
bw.close();
}
}
BufferedWriter 클래스의 write() 메소드는 데이터를 내부 버퍼에 저장하고,flush() 메소드를 사용해 버퍼를 비우고 데이터를 출력한다.
BufferedWriter 클래스의 write() 메소드는 단독으로 int 형 값만 넣을 경우 아스키 코드값으로 인식되기 때문에 다른 문자가 출력된다. 때문에반드시 문자열과 int 형을 함께 넣어줘야int 값을 제대로 출력할 수 있다.
[여기서 잠깐!]
BufferedReader/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=1;i<=N;i++){
for(int j=0;j<i;j++){
sb.append("*");
}
for(int j=0;j<2*(N-i);j++){
sb.append(" ");
}
for(int j=0;j<i;j++){
sb.append("*");
}
sb.append("\n");
}
for(int i=1;i<=N-1;i++){
for(int j=0;j<N-i;j++){
sb.append("*");
}
for(int j=0;j<2*i;j++){
sb.append(" ");
}
for(int j=0;j<N-i;j++){
sb.append("*");
}
sb.append("\n");
}
System.out.println(sb);
}
}
StringBuilder 클래스는 문자열을 동적으로 조작하기 위한 클래스로,append()를 사용해 문자열을 추가하여 새로운 문자열을 생성한다.
append()안에 “\n”를 더하기 연산하지 않고 위와 같이 분리해서 쓰면 타입 변환과 문자열 연결 연산이 추가적으로 발생하지 않고 StringBuilder에 직접 추가하기 때문에 보다 더 효율적이고 빠르다.
3. 성능 비교
위에서 부터 순서대로
BufferedReader + StringBuilder
BufferedReader + BufferedWriter
BufferedReader + System.out.println()
Scanner
위와같이 입력 메소드와 알고리즘 구현 방법에 따라 시간이 달라질 수 있다.
입력의 경우 숫자 하나만 입력받기 때문에 큰 차이가 없다.
출력의 경우 System.out.println() 와 나머지 2개 사이의 차이는 크다.
출력양이 많기 때문에 확실히 BufferedWriter 로 모아서 한번에 출력하는 것과 StringBuilder 로 문자열을 더하기 연산해서 출력하는 것이 훨씬 빠른 것을 볼 수 있다.
관련 페이지
Leave a comment