우당탕탕 자바 알고리즘

그냥 일단 해보기.

진짜 하나도 모르는 사람이라서…

문제 : 집합 (백준 11723)

문제를 자세히 보면 “node.js 사용불가”가 써있어서 컴퓨터에 깔려있는 아무 언어로 풀어야지 라는 마음으로 가볍게 시작한 문제

import java.util.Arrays;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    boolean[] S = new boolean[21];
    int N;

    N = sc.nextInt();
    sc.nextLine();

    StringBuilder sb = new StringBuilder();

    for (int i= 0 ; i < N ; i++) {
      String line = sc.nextLine();
      String cmd;

      String[] tmp  = line.split(" ");
      int target = -1;

      cmd = tmp[0];
      if (tmp.length > 1) {
          target = Integer.parseInt(tmp[1]);
      }

      switch (cmd) {
        case "add":
         if (!S[target]) {
          S[target] = true;
        }
          break;

        case "check":
          sb.append(S[target]? 1 : 0).append("\n");
          break;

        case "remove":
          if (S[target]) {
            S[target] = false;
          }
          break;

        case "toggle":
          S[target] = !S[target];
          break;

        case "all":
          Arrays.fill(S, true);
          break;

        case "empty":
           Arrays.fill(S, false);
          break;
      }
    }
    sc.close();
    System.out.println(sb.toString());
  }
}

어떻게 어떻게 열심히 풀기는 했는데 엄청나게 오랜 시간이 걸렸다.

문제

어렵지 않음.

그냥 조건별로 구현해주면 됨!

심지어 20개의 숫자로 고정되어 있기에 true false 만 인덱스로 접근해서 변경해주는 방향으로 진행했다.

Scanner ?

속도가 느린 것 처럼 보임…

생각보다 다양한 타입의 데이터를 쉽게 불러오는 것 같다.

그리고 nextInt 로 받고 나서 \n이 남아있던 것 같음.

찾아보니 개행문자는 버퍼에 남아있다고 한다. 아이고야

해결 그냥 nextLine() 한 번더 호출해서 개행문자 비워줌

출력도 느린 것 같은데…?

System.out.println로 계속 하나씩 출력하니까 느린 것 처럼 보임… 그래서 StringBuilder를 사용하기로 했다.

사실 그렇게 많이 다른건 없는 것 같은데?

진짜로요

  • for : 그냥 자스랑 똑같았다!

대신 import 부분은 좀 접근성이 떨어지는 것 같은데 자바의 패키지? 구조를 좀 생각해봐야 할 듯

내가 왜 닫아야하는데

  • sc.close() : 어릴떄 로봇 만지던 재미. 이정도는 애교라고 생각합니다.

성능을 개선해보자.

  1. Scanner 대신 BufferedReader 사용하기
  2. StringBuilder로 한번에 출력하기

시간 단축

코드는 다음과 같다.

  • throws IOException 추가.
    • 안그러면 에러가 있었음…
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.io.IOException;

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

    boolean[] S = new boolean[21];
    int N = Integer.parseInt(br.readLine());



    StringBuilder sb = new StringBuilder();

    for (int i= 0 ; i < N ; i++) {
      String line = br.readLine();
      String cmd;

      String[] tmp  = line.split(" ");
      int target = -1;

      cmd = tmp[0];
      if (tmp.length > 1) {
          target = Integer.parseInt(tmp[1]);
      }

      switch (cmd) {
        case "add":
         if (!S[target]) {
          S[target] = true;
        }
          break;

        case "check":
          sb.append(S[target]? 1 : 0).append("\n");
          break;

        case "remove":
          if (S[target]) {
            S[target] = false;
          }
          break;

        case "toggle":
          S[target] = !S[target];
          break;

        case "all":
          Arrays.fill(S, true);
          break;

        case "empty":
           Arrays.fill(S, false);
          break;
      }
    }
    br.close();
    System.out.println(sb.toString());
  }
}

IOException이라는 복병

BufferedReader를 사용하며 br.readLine() 메서드가 IOException을 던질 수 있다는 경고를 계속 봤는데 어떻게 처리해야하는지 영 모르겠었다.

자바스크립트는 런타임에 에러가 나면 터지지만, 자바는 컴파일 시점에 이런 예외를 개발자가 미리 처리하게 강제하는 모양.

결국 public static void main(String[] args) throws IOException 처럼 메서드 시그니처에 throws를 추가해서 해결 - Solidity야 고마워!

그리고 java.io.IOException도 import 해줘야 한다…

결론

오히려 공부하면 나름 금방 익숙해질 것 같다.

이렇게 된거 하루에 같은 문제를 두번 풀어보기로~