백준 15552

YJ·2022년 4월 5일
0
post-thumbnail

- 문제




- 풀이 1




- 풀이 2




- 풀이 3

위 풀이에 대한 결과이다.
41522972 : 풀이3
41522880 : 풀이2
41522671 : 풀이1


Scanner와 System.out.println을 사용하지 않은 이유에 대한 링크
https://steady-coding.tistory.com/183


풀이 1, 3풀이 2는 출력되는 결과가 다르다. 즉, 답이 다르다. 같은 문제의 답이 아니다. 풀이 1, 3은 총 테스트 횟수 만큼 두 수를 입력 받은 후 입력 받은 숫자의 합을 버퍼에 쌓아뒀다가 한 번만 출력이 이루어진다. 반면 풀이 2는 두 수를 입력 받고, 입력 받은 숫자에 대한 합을 출력하는 것을 세트로 테스트 횟수 만큼 반복한다. 따라서 동일한 결과, 여러 풀이가 아닌 서로 다른 문제에 대한 풀이이다.



그렇다면 왜 세개의 방법으로 풀이가 진행 됐을까 ?

백준 15552번이 내게는 모호했기 때문이다.

백준 15552번 문제를 보면 이런 문장이 있는데, 이말은 '입력, 출력은 별개니까 입력을 모두 받은 뒤 출력할 필요 없이 받는 순간 하나하나 출력해도 된다.'는 의미로 해석됐다.

하지만 결과 값을 보면 이렇게 입력과 출력이 나뉘어져 있기 때문에 1, 3 번 풀이처럼 모두 입력을 받은 뒤 출력하는 방식의 답을 원하는 것 같았다.



결국 세 가지 방법을 모두 제출해봤다.

풀이 1, 2, 3을 보면 1번 방식(BufferedReader + Writer)이 가장 빨랐고, 3번 방식(BufferedReader + StringBuilder + System.out.println)이 조금 더 느렸고, 2번 방식은 시간초과가 났다.



여기서 두 가지 의문점이 들었다.


  1. 1번 풀이 방식과 2번 풀이 방식이 실제로도 속도 차이가 날까? 난다면 왜 날까? 2번 풀이 방식이 현저하게 느려서 시간초과가 난 것일까?

  2. StringBuilder가 빠를까? BufferedWriter가 빠를까?



따라서 세가지 방법으로 테스트 해보고 평균 5회의 시간을 측정했다.


  1. BufferedWriter + Write 1000만번 후 + 1번 flush



  1. BufferedWriter + Write 1000만번 flush 1000만번



  1. StringBuilder + 1번 System.out.println을 통한 출력

이렇게 1~50 사이 랜덤 값을 갖는 두 수의 합을 1000만번 출력하는 테스트를 만든 이유는 이와 같다.


기존 코드에서 BufferedReader, StringTokenizer 등을 모두 
제거한다면 StringBuilder, BufferedWriter 기능만 남게 될 
것이고, 이 것들만 사용한 상태에서 시간을 측정한다면 올바른
비교가 가능할 것이라고 판단했다.

다섯번씩 실행한 결과는 위의 이미지와 같다. 정리하자면,

  1. BufferedWriter를 사용하며 A+B한 결과 1000만개를 버퍼에 쌓아
    두었다가 한 번 flush를 통해 출력한 결과
    5회 평균 24739ms, 24s

  2. BufferedWriter를 사용하며 A+B를 버퍼에 담고, 바로 flush로
    출력하는 것을 세트로 1000만번 반복한 결과
    5회 평균 25349ms, 25s

  3. StringBuilder를 사용하여 A+B의 결과를 담아두었다가 println을 통해
    한번 출력한 결과
    5회 평균 25966.6ms, 25.4s


이 같은 결과에 앞서 가진 의문을 대입해보겠다.

  1. 2번 풀이 방식과 1번 풀이 방식이 실제로도 속도 차이가 날까?
    난다면 왜 날까? 2번 풀이 방식이 현저하게 느려서 시간초과가 난
    것일까?

일단 둘은 1000만번 기준 610ms, 0.6초 정도의 속도 차이가 난다.
이유를 정확하게 파악할 수는 없지만 버퍼에 모두 쌓은 후
한 번출력 하는 것과 비교해서 한번 반복할 때 마다 버퍼에 넣었다가 출력
하는 것을 세트로 반복 하는 것이 더 느릴 것이라고 직관적인 생각이 든다.
이런 이유에서 전자가 더 빠르지 않을까 추정한다. 오히려 놀라운 것은
로직이 간단해서 그런지 모르겠지만 둘 사이의 차이가 생각보다 크지
않다는 점이다.

또 위 결과들로 인해 백준에 코드 제출한 결과에 대한 의문이 생긴다.
1000만번 반복 기준 2번 방식은 3번 방식보다 속도가 더 빠른데,
오히려 2번 방식이 시간초과가 났다. 이유를 생각해본 결과 글의
초반부에 문제가 애매했다는 답변으로 정답은 1, 3번의 풀이이며,
결과가 다른 2번 풀이는 오답이기 때문에 이런 결과가 난 것으로
추정한다.


  1. StringBuilder가 빠를까? BufferedWriter가 빠를까?

위 결과에서 BufferedWriter가 더 빠른 것을 확인할 수
있다. 이 또한 이유를 정확하게 알수는 없다. 하지만
System.out.println을 통해 1회 출력 했고,
bw.flush로도 1회 출력 했으므로 이 둘 사이의 속도
차이가 없다고 감안해 StringBuilder보다 BufferedWriter를
사용한 출력이 조금 더 빠르다고 추정한다.

실제로 bufferedwriter를 통한 출력과 system.out.println
을 통한 출력의 속도 차이는 엄청나다. 하지만 여기서 말하는 부분은
1회씩만 사용했기 때문에 거의 미미한 차이일 것이므로 차이가 없다고
가정한 것이다.
profile
hi

0개의 댓글