ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스 2단계] 알고리즘 22. 정수 내림차순으로 배치하기
    레거시/레거시-알고리즘(3) 2018. 4. 6. 12:55
    반응형

    문제 출처는 프로그래머스 알고리즘 연습 에서 볼 수 있습니다!(https://programmers.co.kr/learn/challenges)


    알고리즘 22. 정수 내림차순으로 배치하기

    reverseInt 메소드는 int형 n을 매개변수로 입력받습니다. n에 나타나는 숫자를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를들어 n이 118372면 873211을 리턴하면 됩니다. n은 양의 정수입니다.


    public class ReverseInt {
        public int reverseInt(int n){
            
            return 0;
        }
        // 아래는 테스트로 출력해 보기 위한 코드입니다.
        public static void main(String[] args){
            ReverseInt ri = new ReverseInt();
            System.out.println(ri.reverseInt(118372));
        }
    }


    풀이 : 

    역시 자바는 자바8으로 풀어야지! 하하하 실제로 학생들에겐 도움이 안 될수도 있다. 왜냐하면 자바8은 개발자가 직접 알고리즘을 짠다기 보다는 이미 짜여진 알고리즘을 활용하여 문제를 푸는 방식이기 때문에 그래도 난 함수형으로 문제 푸는 것을 좋아하기 때문에 함수형으로 간다. 이번 문제를 함수형으로 풀기 위해서는 2가지를 고민해봐야한다. 먼저 입력 받은 int를 어떻게 스트림으로 만들지, 그 후에 스트림 요소를 어떻게 정수형으로 만들지, 차차 풀어가면서 생각해보자. 먼저 입력받은 n을 각 자릿수마다 리스트로 만들어야한다. 나는 n을 먼저 문자열로 만든 후 문자열 리스트로 만들려고 한다.


    Integer.toString(n).split("")


    이러면 입력받은 숫자를 문자열 배열로 만들 수 있다. split("")은 해당 문자열을 한 글자 한 글자로 나눠준다. 그리고 Stream을 이용하기 위해서 List로 바꿔줘야 한다. 따라서 이렇게 만들면 최종적으로 입력받은 정수 n의 자릿수를 원소로 가진 리스트 List<String> 으로 만들 수 있다. 


    Arrays.asList(Integer.toString(n).split(""))


    그 후 리스트를 스트림으로 바꿔준다.


    .stream()


    이제 숫자를 거꾸로 반환해야하기 때문에 리스트로 역순으로 정렬하자. stream은 sorted메소드로 정렬할 수 있고 Comparator.reverseOrder()를 넘겨주면 역순으로 정렬 할 수 있다.


    .sorted(Comparator.reverseOrder())


    그 후 요소를 모으는 방법에는 2가지가 있는데 먼저 역순으로 정렬된 스트림을 다시 String으로 바꾼 후 숫자로 바꿔주는 것이다. 그러기 위해서는 stream의 collect메소드와 Collectors.joining("")이 필요하다. 


    .collect(Collectors.joining(""));


    이렇게 전달하면 역순으로 정렬된 문자열 요소들을 하나의 문자열을 붙일 수 있다. 만약 스트림 요소가 "1" "2" "3" 이라면 이 방식을 취했을 때 "123"이라는 결과를 얻을 수 있다. 그리고 이렇게 해서 얻은 문자열을 Integer.parseInt()로 정수로 바꿔주면 된다. 이렇게 풀었을 때 코드의 전문은 이렇다.


    public int reverseInt(int n){
    //1. int -> String -> String[] -> Stream<String> -> String -> int
    String s = Arrays.asList(Integer.toString(n).split(""))
    .stream()
    .sorted(Comparator.reverseOrder())
    .collect(Collectors.joining(""))
    return Integer.parseInt(s);
    }


    다른 방법으로는 그 스트림 요소들을 문자열에서 정수로 매핑한 후 하나의 숫자로 모아주면 된다. 코드의 전문은 이렇다.


    public int reverseInt(int n){
    //2. int -> String -> String[] -> Stream<String> -> Stream<Integer> -> Integer
    return Arrays.asList(Integer.toString(n).split(""))
    .stream()
    .sorted(Comparator.reverseOrder())
    .map(Integer::parseInt)
    .reduce(0, (a, b) -> {
    a *= 10;
    a += b;
    return a;
    });
    }


    map으로 String에서 Integer 형으로 요소들을 바꿔주고 reduce()를 이용하여 집계한다. 합칠 때 자릿수를 합쳐주는 사실을 기억하자! 만약 값이 "1" "2" "3" 이라면 123이 되어야 하니까 내 코드에 따르면 이렇게 된다.


    초기값 0


    첫번째 누적

    a = 0 * 10 (a = 0)

    a += 1     (a = 1)


    두번째 누적

    a = 1 * 10 (a = 10)

    a += 2     (a = 12)


    세번째 누적

    a = 12 * 10 (a = 120)

    a += 3       (a = 123)


    이렇게 해서 원래의 자릿수를 복원할 수 있다. 함수형으로 풀면 이렇게 간단하고 멋지게 풀 수 있다. 다만 어떻게 효율적으로 함수를 적용해야 할지 이건 온전하게 개발자의 몫이다. 결론 자바8 하세요! 

Designed by Tistory.