본문 바로가기
JAVA/코딩테스트

Softeer 연습문제(JAVA) Level 1. 나무 심기

by Gina Sim 2024. 10. 22.

 

문제설명

남우는 나무를 2개 심으려고 합니다. 나무는 주어진 n개의 위치 중 서로 다른 두 곳에 꼭 심어야만 하며, 1번 위치부터 n번 위치까지 각 위치마다 토양의 비옥함에 해당하는 값 Fi가 주어졌을 때 남우는 나무가 심어지는 두 위치 a, b에서 토양의 비옥함의 곱인 Fa ∗ Fb가 최대가 되도록 나무를 심으려고 합니다. 남우가 적절한 위치에 나무를 심을 수 있도록 하는 프로그램을 작성해보세요.

 

만약 n이 3이고 다음과 같이 토양의 비옥함이 순서대로 5, -1, 4인 경우 5, 4 위치에 나무를 심으면 비옥함의 곱이 20으로 최대가 됩니다.

 

 

본 문제의 저작권은 (주)브랜치앤바운드에 있으며, 저작자의 동의 없이 무단 전재/복제/배포를 금지합니다.

 

 

제약조건

  • 2 ≤ n ≤ 100
  • -100 ≤ Fi ≤ 100
 

입력형식

첫 번째 줄에는 n이 주어집니다.
두 번째 줄에는 각 위치에서의 토양의 비옥함에 해당하는 정보 Fi가 각각 공백을 사이에 두고 주어집니다. Fi가 음수인 경우도 주어질 수 있음에 유의합니다.

 

출력형식

첫 번째 줄에 가능한 Fa ∗ Fb 값 중 최댓값을 출력합니다. 1 ≤ a, b ≤ n, a ≠ b 를 만족하는 경우 중 최대를 구해야 함에 유의합니다.

 

예제

입력예제1
2 1 -1

출력예제1
-1


입력예제2
2 -1 -1

출력예제2
1


입력예제3
3 5 -1 4

출력예제3
20


입력예제4
3 -5 1 -4

출력예제4
20

 

 

제출답안

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

public class Main {

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        int cnt = Integer.parseInt(br.readLine());
        int[] fertile = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int answer = 0;
        
        if(cnt>2){
            Arrays.sort(fertile);
            int case1 = fertile[0]*fertile[1];
            int case2 = fertile[cnt-2]* fertile[cnt-1];
            if(case1>case2){answer = case1;}else{answer = case2;}
        }else{
            answer = fertile[0]*fertile[1];
        }
        System.out.print(answer);
    }
}

 

 

회고

  • Scanner 대신 BufferedReader 사용
    • 확실히 처리 시간이 더 빨라진듯 함
    • BufferedReader를 사용할 경우 IOExceptio이 발생할 수 있어 main메서드에 throws IOException을 추가해야 함
더보기

IOException은 Java에서 입출력 작업 중에 발생할 수 있는 예외입니다. 예를 들어, 파일 읽기, 쓰기, 또는 네트워크 연결이 실패할 경우 IOException이 발생할 수 있습니다. BufferedReader로 입력을 받을 때도, 입력이 제대로 이루어지지 않거나 다른 입출력 오류가 발생하면 IOException이 발생할 수 있습니다.

 

하지만 일반적으로 표준 입력(System.in)을 사용할 때는 IOException이 잘 발생하지 않습니다. 그럼에도 불구하고, BufferedReader는 입출력 클래스이기 때문에 항상 IOException을 던질 가능성이 있고, 그래서 Java에서는 이를 명시적으로 처리하도록 요구합니다.

IOException이 발생하지 않게 하는 방법

BufferedReader를 사용하는 대신 Scanner 클래스를 사용할 수 있습니다. Scanner는 표준 입력으로 데이터를 받을 때 IOException을 던지지 않기 때문에, IOException을 처리할 필요가 없습니다. 이 방식으로 코드를 변경하면 예외 처리가 필요 없고, 코드가 더 간결해집니다.

  • 문자열을 Integer로 변환할 때 Integer.valueOf()와 Integer.parseInt() 차이점 확인
더보기

Java에서 Integer.valueOf()와 Integer.parseInt()는 모두 문자열을 정수로 변환하는 데 사용되지만, 두 메서드 간에는 중요한 차이점이 있습니다.

1. Integer.parseInt(String s):

  • 리턴 타입: int (기본형)/ 문자열을 변환한 후, 기본형 int 값을 반환합니다.
  • 설명: Integer.parseInt()는 문자열을 기본형 int로 변환합니다.
  • 특징: 변환된 값은 int로 반환되며, 기본형이므로 null을 저장할 수 없습니다.
  • 추가적인 메모리 할당 없음: 기본형은 객체가 아니므로 힙에 메모리를 할당할 필요가 없습니다.
  • 빠른 실행: 객체 생성이 없기 때문에, 이 메서드는 매우 빠릅니다.

2. Integer.valueOf(String s):

  • 리턴 타입: Integer (래퍼 클래스)/ 문자열을 변환한 후, Integer 객체를 반환합니다.
  • 설명: Integer.valueOf()는 문자열을 Integer 객체로 변환합니다.
  • 특징: 변환된 값은 Integer 객체로 반환되며, 이는 객체이므로 null 값을 저장할 수 있습니다. Integer.valueOf()는 또한 자주 사용되는 작은 값에 대해 캐싱을 제공하여 성능을 최적화할 수 있습니다. 
  • 캐싱: Integer.valueOf()는 -128부터 127 사이의 값을 캐싱합니다. 이 범위 내의 값은 새로운 객체를 생성하지 않고, 미리 생성된 객체를 반환합니다. 따라서 이 범위 안의 숫자를 처리하는 경우, Integer.valueOf()는 parseInt()와 거의 동일한 성능을 보일 수 있습니다.
  • 캐싱 범위 밖의 값: 127을 넘거나 -128 이하인 값은 캐싱되지 않기 때문에 새로운 Integer 객체가 생성됩니다. 이때 객체 생성 비용이 추가되며, Integer.parseInt()보다 상대적으로 느려질 수 있습니다.

주요 차이점 요약:

  1. 리턴 타입:
    • Integer.parseInt(): int (기본형)
    • Integer.valueOf(): Integer (객체)
  2. 성능:
    • Integer.valueOf()는 내부적으로 캐싱을 사용하여, 자주 사용되는 작은 범위의 정수를 효율적으로 처리할 수 있습니다. 반면, parseInt()는 항상 새로운 int 값을 반환합니다.
  3. null 처리:
    • Integer.parseInt()는 null을 처리할 수 없고, null 입력 시 예외를 발생시킵니다.
    • Integer.valueOf()는 null 입력 시 NullPointerException을 발생시키지만, 변환된 값이 Integer 객체이므로 null 할당이 가능합니다.

성능 차이 요약:

  • 작은 범위의 값 (-128 ~ 127): Integer.valueOf()는 캐싱된 값을 사용하므로 Integer.parseInt()와 거의 동일한 성능을 보입니다.
  • 캐싱 범위 밖의 값: Integer.valueOf()는 새로운 객체를 생성하므로 Integer.parseInt()보다 약간 느릴 수 있습니다.
  • 기본형 vs 객체: 기본형 int를 반환하는 parseInt()가 항상 더 가볍고 빠릅니다. 객체 생성이 없기 때문에 메모리와 CPU 사용 측면에서 더 효율적입니다.
  • 새로 알 게 된 것
    • Array 정렬 - Arrays.sort(배열) / 정렬함수가 직관적이고 간단해서 좋음

 

chatGPT를 이용한 에러핸들링

<오류 코드>

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

public class Main {

    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in
        
        int cnt = Integer.parseInt(br.readLine());
        Integer[] fertile = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        if(cnt>2){
            Arrays.sort(fertile);
            int case1 = fertile[0]*fetrile[1];
            int case2 = fertile[cnt-2]* fertile[cnt-1];
            if(case1>case2){answer = case1;}else{answer = case2;}
        }else{
            answer = fertile[0]*fertile[1];
        }
        System.out.print(answer);
    }
}

 

<chatGPT 답변>

코드에서 다음과 같은 오류와 문제들이 있습니다:

  1. mapToInt(Integer::parseInt)의 결과를 Integer[]에 저장하려고 함:
    • mapToInt(Integer::parseInt)는 기본형 int[] 배열을 반환합니다. 따라서 이를 Integer[] 배열에 바로 저장할 수 없습니다.
    • 해결 방법: Integer[]로 변환하거나, 기본형 int[]로 변수를 선언해야 합니다.
  2. fetrile 오타:
    • fetrile이라는 변수명이 잘못되어 있습니다. 이 변수는 fertile로 수정해야 합니다.
  3. 변수 answer의 선언이 없음:
    • answer 변수가 선언되지 않았습니다. 이 변수를 정수형으로 선언해야 합니다.

 

<수정 된 코드>

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

public class Main {

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

        int cnt = Integer.parseInt(br.readLine());
        int[] fertile = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int answer = 0;

        if(cnt >= 2){  // cnt가 2 이상인 경우만 처리
            Arrays.sort(fertile);
            int case1 = fertile[0] * fertile[1];  // 최소값 두 개 곱
            int case2 = fertile[cnt - 2] * fertile[cnt - 1];  // 최대값 두 개 곱
            
            answer = Math.max(case1, case2);  // 큰 값을 선택
        } else {
            answer = fertile[0]*fertile[1];
        }
        
        System.out.print(answer);
    }
}

 

<회고>

  • 알아서 주석으로 코드 설명 달아줘서 신기하고 좋음
  • 오타 때문에 불필요하게 애먹는 경우 많은데 찾아줘서 편함
  • case 두개를 비교하여 답을 출력할때, if else문 대신 math를 이용한 방법을 알려줘서 좋음.
  • else부분에서 예외처리 하는 코드를 줘서 해당 부분은 사용안함.
반응형

댓글