백준 JAVA - 3단계 for 활용하기 (2) (feat. 별 찍기, x보다 작은 수)
2021.09.29 - [알고리즘 공부] - JAVA - 3단계 for 활용하기 (1) (feat.Buffer, StringTokenizer, String.split 사용)
이번에는 for문 알고리즘 문제 2편입니다(1편은 위에 링크로)
지난 글에 이어서 2742번부터 10871번까지 풀어보았다.
다만 문제 유형에 맞춰 2742 ~ 11022 번까지와 2438 ~ 10871 번으로 나누어 적도록 하겠다.
1. 2742 ~ 11022 까지 풀이!!
여기 문제는 이전 문제를 풀었다면 크게 문제없을 정도의 난이도! 입력-출력의 반복이라는 점과 BufferedWriter 로 입력받았을 때 나누는 방법만 알면 크게 문제 될 것은 없어보인다.
package baekJoon;
import java.io.*;
public class Q10_3 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Q_2742();
Q_11021();
Q_11022();
}
static void Q_2742() 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=N; i>=1; i--) {
bw.write(i+"\n");
}
br.close();
bw.flush();
bw.close();
}
static void Q_11021() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int t = Integer.parseInt(br.readLine());
int i=0;
String num="";
int result=0;
for(i=1; i<=t; i++) {
num = br.readLine();
String[] str = num.split(" ");
result = Integer.parseInt(str[0])+Integer.parseInt(str[1]); // 입력받은 값 나눠서 더하기
bw.write("Case #"+i+": "+result);
bw.newLine();
}
br.close();
bw.flush();
bw.close();
}
static void Q_11022() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int t = Integer.parseInt(br.readLine());
int i=0;
String num="";
int result=0;
for(i=1; i<=t; i++) {
num = br.readLine();
String[] str = num.split(" ");
result = Integer.parseInt(str[0])
+Integer.parseInt(str[1]);
bw.write("Case #"+i+": "+str[0]+" + "+str[1]+" = "+result);
bw.newLine();
}
br.close();
bw.flush();
bw.close();
}
}
2. 2438 ~ 10871 까지 풀이!
여기는 별찍기 2438 문제와 10871 번 문제는 크게 어렵지 않게 넘어갔는데, 별찍기 2439번 문제에서 상당히 고민했다. 물론 이렇게 고민한거는 내가 이중 for문에 대해서 제대로 이해하지 못했기 때문...이라고 생각한다. 해당 문제를 어떻게 풀었는지는 아래에 더 적도록 하겠다.
package baekJoon;
import java.io.*;
public class Q10_3 {
public static void main(String[] args) throws IOException {
Q_2438();
Q_2439();
Q_10871();
}
static void Q_2438() 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 문은 몇 줄을 반복할 것인지(행)
for(int k=1; k<=i; k++) { // 안쪽 for 문은 몇 칸을 반복할 것인지(열)
bw.write("*");
}
bw.newLine();
}
br.close();
bw.flush();
bw.close();
}
static void Q_2439() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
// 방법1.println
// for(int i=1; i<=n; i++) {
// for(int j=n; j>i; j--) {
// System.out.print(" ");
// }
// for(int k=1; k<=i; k++) { // 열
// System.out.print("*");
// }
// System.out.println();
// }
// 방법2. buffer
for(int i=1; i<=n; i++) {
for(int j=n; j>i; j--) {
bw.write(" ");
}
for(int k=1; k<=i; k++) { // 열
bw.write("*");
}
bw.newLine(); // 빈줄 추가
}
br.close();
bw.flush();
bw.close();
}
static void Q_10871() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String N = br.readLine();
String[] X = N.split(" "); // 입력받은 2개의 값을 공백 기준으로 분리
int a = Integer.parseInt(X[0]); // 첫번째 입력받은 값 int 로 변환
int b = Integer.parseInt(X[1]); // 입력받은 두번째 값을 int 로 변환
String num = br.readLine();
String[] result = num.split(" ");
for(int i=0; i<a; i++) {
if(b>Integer.parseInt(result[i])) { // 두번째 입력받은 값을 기준으로 result[i] 값을 비교
bw.write(result[i]+" "); // 두번째 값보다 작으면 result[i] 출력
}
}
br.close();
bw.flush();
bw.close();
}
}
2438 결과
*
**
***
****
*****
2439 결과
*
**
***
****
*****
별찍기를 활용한 이중 for 문에 대해 요약하자면 이중 for 문에서 바깥 for 문은 행, 안쪽 for 문은 열 을 의미한다고 생각하면 편하다. 더 구체적으로는 바깥 for문 = 행 = 세로크기 = row, 안쪽 for문 = 열 = 가로크기=col 이라고 생각하면 된다.
이를 생각하면서 별찍기 2438 문제를 보자
static void Q_2438() 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 k=1; k<=i; k++) { // 열 = 가로크기
bw.write("*");
}
bw.newLine();
}
br.close();
bw.flush();
bw.close();
}
<출력 결과>
(출력 결과를 보면 함수 좌표의 모양이 일반적인 수학의 그것과 다른데 이는 컴퓨터에서 출력하면 첫째줄부터 출력되기 때문이라고 생각하면 된다)
y1 *
y2 * *
y3 * * *
y4 * * * *
y5 * * * * *
x1 x2 x3 x4 x5
1. 출력되어야하는 결과를 생각해보면 y 값은 1에서 n까지이다. 마찬가지로 x 값은 1~n까지이다. 여기서 함수 좌표의 모양이 일반적인 수학의 그것과 다른데 이는 컴퓨터에서 출력하면 첫째줄부터 출력되기 때문이라고 생각하면 된다. 따라서 첫째줄이자 맨 윗줄이 y1 이 되는 것이다.
2. 이렇게 한 뒤에 생각해보면 y 값이 증가함에 따라서 x값도 증가하는 것을 볼 수 있다. 정확히는 y1 일 때 x1 , y2 일 때 x2 이런식으로 증가한다. 이걸 정리하자면 y가 n번째 행 일 때 x는 y개가 찍히게 된다.
3. 최종적으로 바깥 for 문의 i값은 입력받은 n 을 기준으로 하고, 안쪽 for 문의 k 값은 해당 y 만큼만 * 을 찍는다.
for(int i=1; i<=n; i++) { // 행 = 세로크기 = row = 입력받은 n 만큼 증가함
for(int k=1; k<=i; k++) { // 열 = 가로크기 = col
bw.write("*");
}
bw.newLine();
}
별찍기 2439 문제는 2438 문제의 응용이다.
for(int i=1; i<=n; i++) { // 행
for(int j=n; j>i; j--) { // 열1
bw.write(" "); // 공백은 행이 늘어날수록 감소!!
}
for(int k=1; k<=i; k++) { // 열2
bw.write("*"); // * 은 행이 늘어날수록 증가!!
}
bw.newLine();
}
<결과 출력>
// 공백은 감소, * 은 증가
*
**
***
****
*****
결국 중요한 것은 공백은 감소하고 * 은 증가하는 것을 아는것이다.
1. 정확히는 y가 한줄한줄 증가 할 수록 공백으로 이루어진 칸은 감소하고 * 로 이루어진 칸은 증가하는 것이다(어쩌면 y 값에 따라서 x값이 2개라고 생각하면...편하려나?)
2. 이에 따라서 행을 이루는 바깥 for 문안에 안쪽 for 문을 2개를 두어 각각 증가하는 모양 감소하는 모양으로 넣어두면 이번 문제를 쉽게 풀 수 있다.
번외로 BufferedWriter 을 사용했을 때와 println 을 사용했을 때의 출력 시간 차이는 약 2배정도...확실히 buffer이 빠르다.
※ 다만 알아두어야 할 점은 함수로 x 값 y 값해서 푸는거는 본인이 해당 문제를 풀면서 고민하다가 얻어낸 방법입니다. 기존 이중 for문에 대해서 완벽히 이해를 못했기 때문에 이러한 방법을 생각해냈다고 봐서...그냥 이렇게 생각할 수도 있구나 하고 봐주셨으면 합니다.