문제설명
남우는 나무를 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()보다 상대적으로 느려질 수 있습니다.
주요 차이점 요약:
- 리턴 타입:
- Integer.parseInt(): int (기본형)
- Integer.valueOf(): Integer (객체)
- 성능:
- Integer.valueOf()는 내부적으로 캐싱을 사용하여, 자주 사용되는 작은 범위의 정수를 효율적으로 처리할 수 있습니다. 반면, parseInt()는 항상 새로운 int 값을 반환합니다.
- 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 답변>
코드에서 다음과 같은 오류와 문제들이 있습니다:
- mapToInt(Integer::parseInt)의 결과를 Integer[]에 저장하려고 함:
- mapToInt(Integer::parseInt)는 기본형 int[] 배열을 반환합니다. 따라서 이를 Integer[] 배열에 바로 저장할 수 없습니다.
- 해결 방법: Integer[]로 변환하거나, 기본형 int[]로 변수를 선언해야 합니다.
- fetrile 오타:
- fetrile이라는 변수명이 잘못되어 있습니다. 이 변수는 fertile로 수정해야 합니다.
- 변수 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부분에서 예외처리 하는 코드를 줘서 해당 부분은 사용안함.
'JAVA > 코딩테스트' 카테고리의 다른 글
Softeer 연습문제(JAVA) Level 1. [한양대 HCPC 2023] Tren del Fin del Mundo (0) | 2024.10.22 |
---|---|
Softeer 연습문제(JAVA) Level 1. 연탄 배달의 시작 (0) | 2024.10.21 |
Softeer 연습문제(JAVA) Level 1. [한양대 HCPC 2023] 개표 (0) | 2024.10.21 |
Softeer 연습문제(JAVA) Level 1. 주행거리 비교하기 (0) | 2024.10.21 |
Softeer 연습문제(JAVA) Level 1. 근무시간 (0) | 2024.10.21 |
댓글