Language/JAVA

[프로그래머스] 제일 작은 수 제거하기

paran21 2022. 1. 19. 00:43

https://programmers.co.kr/learn/courses/30/lessons/12935

이 문제를 풀면서 까다로운 점은 다음 2가지였다.

  • 배열 순서 그대로 출력해야 한다.
  • 가장 작은 수가 여러 번 있는 경우 모두 제거해주어야 한다.

제한 조건(인덱스)에 의해 배열 내 수 중복은 없다!!

따라서 answer의 길이는 (arr.length가 1인 경우를 제외하고) arr-1이다.따라서 굳이 ArrayList를 쓰지 않고 배열로도 해결이 가능하다.

 

이를 해결 하기 위해

  • 최소값을 구하는 과정에서 정렬을 사용하기 위해 배열의 복사본을 이용
  • 인덱스마다 최소값과 비교하여 원하는 값만 새로운 배열에 추가

또한 배열의 크기 변화가 필요하여 List배열을 이용하였다.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Solution {
    public int[] solution(int[] arr) {
        //add를 사용하기위해 ArrayList 배열 선언
        List<Integer> group = new ArrayList<>();

        //최소값을 구하는 과정
        int[] arr2 = arr.clone();  //복사본 만들기
        Arrays.sort(arr2); //오름차순 정렬
        int min = arr2[0]; //인덱스0 값을 최소값으로 지정

        //List배열인 group에 add를 이용하여 출력할 값을 담음
        if (arr.length == 1) {
            group.add(-1);
        } else {
            //최소값보다 큰 경우 group에 add
            for (int i = 0; i < arr.length; i++) {
                if(arr[i] > min) {
                    group.add(arr[i]);
                }
            }
        }
        //return값인 answer선언 : 크기 반드시 지정해야함
        int[] answer = new int[group.size()];
        //ArrayList를 int[]로 변환
        for (int i = 0; i < group.size(); i++) {
            answer[i] = group.get(i);
        }
        return answer;
    }
}

+코드리뷰 후 답안 수정(ArrayList 사용안한 방식)

크기가 다른 배열이 두 개가 동시에 for문을 돌기 때문에 각각 인덱스 설정을 잘 해주는게 중요했다.

class Solution {
    public int[] solution(int[] arr) {
        int min = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr.length == 1) { //예외처리
                int[] answer = {-1};
                return answer;
            } else {
                min = Math.min(min, arr[i]); //최소값구하기
            }
        }
        int[] answer = new int[arr.length-1];
        int k = 0;
        for (int j = 0; j < arr.length; j++)
        {
            if(arr[j] > min) {
                answer[k] = arr[j];
                k++;
            }
        }
        return answer;
    }
}

 

 

크기 비교가 가능한 char을 사용할 생각도 했는데 우선 변환이 너무 많이 필요했고(int[], String, String[], char 등등)

주어진 배열이 int[]이라서 String으로 변환시 대괄호[]와 ,까지 모두 String으로 변환되었다.

입력값과 출력값이 모두 int[]라면 가급적 int[] + List나 IntStream정도 내에서 필요한 모든 처리를 완료하는 편이 나은 것 같다.

 

여러 이유로 배열을 직접 처리할 수 없을 때 복사본을 활용하거나,

다른 답안에서 본 것 처럼 배열의 크기를 구하기 위해 for문 밖에 int를 선언하고, 요소가 추가될 때마다 int++를 하는 방법은 유용하게 활용할 수 있을 것 같다.

 

array.clone()

  • 단순히 =을 사용하면 객체의 주소값만을 복사(얕은 복사, Shallow Copy) → 값이 같이 변경됨
  • clone()을 사용하면 실제 대상이 두 개 생기는 것(깊은 복사, Deep Copy) → 각자 값이 변경됨
  • 참고 : https://coding-factory.tistory.com/548

 

다른 답안 : Stream 활용

import java.util.Arrays;
import java.util.stream.Stream;
import java.util.List;
import java.util.ArrayList;

class Solution {
  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(i -> i != min).toArray();
  }
}

Stream 정리 : https://paran21.tistory.com/48