가장 작은 수 제거하기

나의 기록·2026년 6월 11일

코딩테스트

목록 보기
13/35

가장 작은 수 제거하기

문제 요약

정수 배열 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;
    }
}

뭘 몰랐나

1. 조건을 특정 값에 묶어버렸다

if(arr.length==1 && arr[0]==10)

예시 입력이 [10]이라서 arr[0]==10을 조건에 넣어버렸다.

근데 문제가 요구하는 건 값이 10일 때가 아니라 길이가 1일 때 (최솟값 제거 시 빈 배열이 되는 경우)다.

[5]가 들어오면 이 조건을 통과 못 하고 엉뚱한 결과가 나온다.

// 수정
if(arr.length==1){
    return new int[]{-1};
}

2. 최솟값 제거 로직이 없었다

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이 그대로 포함된다.

최솟값을 찾아서 제거하는 로직이 전혀 없었던 것.


3. answer 인덱스를 따로 관리해야 한다

최솟값을 건너뛰면서 새 배열에 담을 때, 원본 배열 인덱스 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부터 관리해야 한다.


4. O(n²) → O(n) 으로 개선

처음에 이중 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 하나로 조건에 맞는 것만 걸러낼 수 있다. 복잡하게 생각할 필요 없다.

profile
뭐든 남겨본다

0개의 댓글