정수 배열 arr에서 가장 작은 수를 제거한 배열을 리턴한다.
단, 결과가 빈 배열이면 [-1]을 리턴한다.
import java.util.Arrays;
class Solution {
public int[] solution(int[] arr) {
int[] answer = {};
if(arr.length==1 && arr[0]==10){
return new int[]{-1};
}else{
answer = new int[arr.length-1];
}
for(int i=0; i<arr.length-1; i++){
answer[i]=arr[i];
}
return answer;
}
}
if(arr.length==1 && arr[0]==10)
예시 입력이 [10]이라서 arr[0]==10을 조건에 넣어버렸다.
근데 문제가 요구하는 건 값이 10일 때가 아니라 길이가 1일 때 (최솟값 제거 시 빈 배열이 되는 경우)다.
[5]가 들어오면 이 조건을 통과 못 하고 엉뚱한 결과가 나온다.
// 수정
if(arr.length==1){
return new int[]{-1};
}
for(int i=0; i<arr.length-1; i++){
answer[i]=arr[i];
}
[4,3,2,1]은 최솟값이 마지막에 있어서 앞 3개만 잘라내면 우연히 맞았다.
근데 [1,3,2,4]를 넣으면?
→ [1,3,2]가 나온다. 최솟값인 1이 그대로 포함된다.
최솟값을 찾아서 제거하는 로직이 전혀 없었던 것.
최솟값을 건너뛰면서 새 배열에 담을 때, 원본 배열 인덱스 i를 그대로 쓰면 안 된다.
예를 들어 [1,3,2,4]에서 1을 건너뛰면:
arr[0]=1 → 스킵
arr[1]=3 → answer[1]=3 ← 인덱스가 1부터 시작해버림
arr[2]=2 → answer[2]=2
arr[3]=4 → answer[3]=4 ← answer 크기는 3인데 인덱스 3 접근 → ArrayIndexOutOfBoundsException
별도의 idx 변수를 0부터 관리해야 한다.
처음에 이중 for문으로 최솟값을 찾으려 했다.
// 처음 시도 - O(n²)
for(int i=0; i<arr.length; i++){
int cnt=0;
for(int j=0; j<arr.length; j++){
if(arr[i]>arr[j]) cnt++;
}
if(cnt>0){
answer[idx]=arr[i];
idx++;
}
}
모든 원소를 서로 비교하는 방식이라 불필요하게 복잡하다.
최솟값은 배열을 한 번만 순회하면서 찾을 수 있다.
// O(n)
int min = arr[0];
for(int i=1; i<arr.length; i++){
if(min > arr[i]) min = arr[i];
}
class Solution {
public int[] solution(int[] arr) {
if(arr.length==1){
return new int[]{-1};
}
int[] answer = new int[arr.length-1];
int idx = 0;
// 1. 최솟값 찾기 - O(n)
int min = arr[0];
for(int i=1; i<arr.length; i++){
if(min > arr[i]) min = arr[i];
}
// 2. 최솟값 제외하고 answer에 담기
for(int num : arr){
if(min < num){
answer[idx] = num;
idx++;
}
}
return answer;
}
}
for문 풀이 이후 Stream으로도 풀어봤다.
배열이 두 개 필요한지 고민했는데, filter 하나면 해결된다.
public int[] solution(int[] arr) {
if(arr.length == 1) return new int[]{-1};
int min = Arrays.stream(arr).min().getAsInt();
return Arrays.stream(arr)
.filter(n -> n != min)
.toArray();
}
min().getAsInt() — 스트림에서 최솟값 추출filter(n -> n != min) — 최솟값만 걸러냄toArray() — int[]로 반환예외처리(arr.length==1)는 스트림 밖에서 먼저 처리하는 게 가독성상 낫다.
| 문제 | 원인 | 해결 |
|---|---|---|
-1 조건이 [10]에만 동작 | 예시 값을 조건에 그대로 사용 | arr.length==1로 수정 |
| 최솟값이 제거 안 됨 | 최솟값 탐색 로직 자체가 없었음 | min 변수로 먼저 찾기 |
ArrayIndexOutOfBoundsException | 원본 i 인덱스를 그대로 사용 | 별도 idx 변수로 관리 |
| 이중 for문 O(n²) | 모든 원소를 서로 비교 | 단일 순회로 min 추출 → O(n) |
| 스트림에서 배열 두 개 필요? | filter 하나면 해결 | min 구하고 filter(n -> n != min) |
오늘의 교훈
예시 입력값을 조건에 하드코딩하지 말 것. 문제가 요구하는 본질적인 조건이 무엇인지 먼저 파악하자.
새 배열에 담을 때는 원본 인덱스가 아닌 별도 인덱스를 관리해야 한다.
스트림은filter하나로 조건에 맞는 것만 걸러낼 수 있다. 복잡하게 생각할 필요 없다.