백준 5073 삼각형과 세변 [JAVA]

Ga0·2023년 3월 29일
1

baekjoon

목록 보기
11/124

문제 해석

  • 한마디로 설명하자면 삼각형의 세변의 길이를 입력받아 변의 길이를 통해 어떤 삼각형인지 출력하면 되는 문제이다.
  • 콘솔에 0 0 0을 입력받기 전까지는 계속 반복문이 돌며 삼각형의 세변의 길이를 입력받는다.
  • 어떤 삼각형인지 판단하기 전에 알아야할 것이 있다!
    -> 세변의 길이 중 가장 긴 변이 나머지 두 변의 길이보다 작아야 삼각형에 부합한다. 하지만, 그렇지 않을 경우 삼각형이 될 수 없다. (이 경우, 변이 꼭짓점으로 만나지 못한다)
    • 위의 삼각형의 부합 여부를 통과했다면, 삼각형을 구분한다.
      1) 세 변의 길이가 모두 같은 경우 Equilateral
      2) 두 변의 길이만 같은 경우 Isosceles
      3) 세 변의 길이가 모두 다른 경우 Scalene
      -> 위와 같이 구분하고, 0 0 0을 입력받으면 저장했던 삼각형의 구분 정보를 출력하면 된다.

코드1

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

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


        while(true) {
            StringTokenizer token = new StringTokenizer(br.readLine());

            int [] array = {Integer.parseInt(token.nextToken()), Integer.parseInt(token.nextToken()), Integer.parseInt(token.nextToken())};

            if(array[0] == 0&& array[1] == 0 && array[2] == 0){
                break;
            }

            Arrays.sort(array); //작은 수부터 큰 수로 정렬

            if(array[2] >= array[0] + array[1]){ // 가장 긴변의 길이가 나머지 두변길이의 합보단 작아야함.
                bw.write("Invalid\n");
            }else {
                int [] disArray =  Arrays.stream(array).distinct().toArray();
                if(disArray.length == 1){
                    bw.write("Equilateral\n");
                }else if(disArray.length == 2){
                    bw.write("Isosceles\n");
                }else if(disArray.length == 3){
                    bw.write("Scalene\n");
                }
            }
        }
        br.close();
        bw.flush();
        bw.close();
    }
}
  • 일단 Arrays.sort() 메서드를 사용하여 배열을 작은 수 -> 큰 수로 정렬했다.
  • 어제처럼 HashSet을 사용할까 했지만, HashSet을 사용하기 위해선 ArrayList를 사용해야해서 distinct()이라는 메서드를 사용했다.

결과1

-> 그래서인지, 시간이 200이 넘는다...

참고하여 고친 코드2

import java.io.*;
import java.util.StringTokenizer;

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

        while(true) {
            StringTokenizer token = new StringTokenizer(br.readLine());
            
            //배열이 아닌 int형 변수 선언
            int a = Integer.parseInt(token.nextToken());
            int b = Integer.parseInt(token.nextToken());
            int c = Integer.parseInt(token.nextToken());

            if(a == 0&& b == 0 && c == 0){
                break;
            }

            if((a >= b+ c) || (b >= a+ c) || (c >= a+ b)){ //삼각형에 부합하지 않을 경우
                bw.write("Invalid\n");
            }else if(a ==b && b == c){ //세변이 같을 경우
                bw.write("Equilateral\n");
            }else if((a == b) || (a == c) || (b == c)){ //두변이 같을 경우
                bw.write("Isosceles\n");
            }else if((a != b) && (b != c) && (c != a)){ //세변이 전부 다를 경우
                bw.write("Scalene\n");
            }
        }
        br.close();
        bw.flush();
        bw.close();
    }
}

결과2

  • 일단 판단 미스였던 것은, 나는 변수를 3개 선언하는 것보다 배열을 선언하는 것이 메모리를 덜 먹을 줄 알았다.
  • 생각해보니,
    - 기본 타입(byte, int, double, boolean 등.. ) 배열은 각 항목에 직접 값을 가진다.
    - 참조 타입(클래스, 인터페이스) 배열은 각 항목에 객체의 번지(힙에 값이 저장)를 가진다.
    -> 사실, 힙을 사용하니까(?) 메모리를 더 먹나? 기본 타입은 여기서 지역변수로써 스택에 저장 잠깐 저장되고 끝이고, 배열은 스택엔 번지주소값을 가지고, 값은 힙에 저장하니까 메모리를 더 쓰나? 라고 추측을 하고 있는데, 아직 머리속으로 뭐가 더 빠른 코드인지 메모리를 덜 쓰는 코드인지 정리가 되지 않았다...
  • 그래서! 배열 버전으로 코드를 고쳐보았다.

배열버전 코드3

import java.io.*;
import java.util.StringTokenizer;

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

        while(true) {
            StringTokenizer token = new StringTokenizer(br.readLine());
            
            //배열로 선언
           int [] array = {Integer.parseInt(token.nextToken()),Integer.parseInt(token.nextToken()),Integer.parseInt(token.nextToken())};


            if(array[0] == 0&& array[1] == 0 && array[2] == 0){
                break;
            }

            if((array[0] >= array[1]+ array[2]) || (array[1] >= array[0]+ array[2]) || (array[2] >= array[0]+ array[1])){ //삼각형에 부합하지 않을 경우
                bw.write("Invalid\n");
            }else if(array[0] ==array[1] && array[1] == array[2]){ //세변이 같을 경우
                bw.write("Equilateral\n");
            }else if((array[0] == array[1]) || (array[0] == array[2]) || (array[1] == array[2])){ //두변이 같을 경우
                bw.write("Isosceles\n");
            }else if((array[0] != array[1]) && (array[1] != array[2]) && (array[2] != array[0])){ //세변이 전부 다를 경우
                bw.write("Scalene\n");
            }
        }
        br.close();
        bw.flush();
        bw.close();
    }
}

결과3

  • 이러니 시간은 더 줄었지만! 메모리를 좀 더 쓴다...
  • 만약, 지역에서 선언한 배열과 변수의 메모리 차이점을 아시는 분은 댓글로 꼭 남겨주셨으면 좋겠습니다...(우연히 포스트를 보게 된 😇님)

느낀점 & 정리

  • 일단 조건식안에 연산이 많으면 시간이 많이 소요될 것 같아서 Stream(다양한 데이터를 다루기 위한 라이브러리)에서 제공하는 distinct() 메서드를 사용하는 것이 더 빠를 것 같았는데, 라이브러리를 사용하는 것(=>불필요한 연산이 있을 수 있음)이 마냥 좋지 않다는 것을 깨달았다.
  • 아직까진 보기 좋은 코드가 좋은 코드라고만 생각하고 있지, 메모리와 시간을 따져서 코드를 짜는게 쉽지 않아서 어떻게 해야할지 모르겠다...

0개의 댓글