[알고리즘] 정수 내림차순으로 배치

DongGyu Jung·2021년 10월 13일
0
post-thumbnail

※ 본 사진과 해당 게시글 내용의 문제 모두 프로그래머스[Programmers]사이트에 발췌해왔습니다.

❓ 문제

함수 solution은 정수 n을 매개변수로 입력받습니다. 
n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 
예를들어 n이 118372면 873211을 리턴하면 됩니다.

제한 조건 : n은 1이상 8000000000 이하인 자연수입니다.

<입출력 >
n	| return
118372	| 873211

❗ 풀이

My Code

def solution(n):
    str_n = list(str(n))
    sort_n = sorted(str_n, reverse=True)
    answer = int(''.join(sort_n))
    return answer

이번 알고리즘은 단계적이고 순차적인 계산을 통해 전개하지 않고
파이썬 내장 함수인 sorted() 함수를 사용했다.
str()함수를 통해 입력값을 문자열로 변환해주고
list()함수를 통해 str_n이라는 변수 안에는 입력된 수의 각 자릿수가 문자열 로서 이루어지는 리스트가 담기게 된다.

위 과정으로 숫자를 하나씩 나누었고
숫자들이 문자열로 바뀌더라도 int데이터의 경우와 동일하게 대소관계를 가지기 때문에
sorted()라는 함수를 통해 정렬하고 reverse=True라는 매개변수 값을 입력해
내림차순으로 정렬하여 반환했다.
이후 ''.join(sort_n)으로 정렬된 숫자들을 합치는 마무리 작업을 작성하였다.
공백''으로 .join([List]) 합치는 명령이다.

❣ 다른 풀이

(1)

def merge(left, right):
    result = []
    while len(left) > 0 or len(right) > 0:
        if len(left) > 0 and len(right) > 0:
            if left[0] >= right[0]:
                result.append(left[0])
                left = left[1:]
            else:
                result.append(right[0])
                right = right[1:]
        elif len(left) > 0:
            result.append(left[0])
            left = left[1:]
        elif len(right) > 0:
            result.append(right[0])
            right = right[1:]
    return result

def mergeSort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]

    left = mergeSort(left)
    right = mergeSort(right)

    return merge(left, right)

def solution(n):
    arr = list(str(n))
    n = int(''.join(mergeSort(arr)))
    return n

많이 길긴하지만 이렇게 과정 하나하나를 쪼개 분석해낸 것이 멋있는 것 같다.
이 성실함과 끈기가 정말 대단한 것 같다.

우선 구성을 살펴보면 3개의 함수를 정의하였는데 순서대로 살펴보자.
첫 번째
merge(left, right) 함수,
result라는 "빈 리스트 "를 선언하고
while len(left) > 0 or len(right) > 0 :으로 len()함수를 설정한 것을 보니
변수로 리스트나 문자열 등을 받아올 것으로 예상하고 입력받은 두 값 중 한 값의 길이가 0이 될 때까지 수행하는 루프(Loop)문을 걸었다.

이후 3가지의 조건문을 작성했는데

  1. if len(left) > 0 and len(right) > 0 : ( 두 값의 길이가 모두 0보다 클 때)
    • 내부 조건문
      - if left[0] >= right[0] : (left의 첫번째 값이 right의 첫번째 값보다 크거나 같을 때)
      : 그 left 값을 result 리스트에 append하고 left를 첫 번째 값 이후의 값들로 이루어진 리스트로 재선언한다.
      else의 경우는 위 과정을 right로 대상을 바꾸어 동일하게 수행한다.


  2. elif len(left) > 0 : ( left 값의 길이만 0보다 클 때) -> 1번 내부조건문의 "if식"
  3. elif len(right) > 0 : ( right 값의 길이만 0보다 클 때) -> 1번 내부조건문의 "else식"

2, 3번 조건문의 수행명령은 각 각 1번 조건문의 내부조건문의 수행명령과 같다.

두 번째 함수는
mergeSort(arr)이다.
변수명을 보면 직관적으로 행열데이터를 받는 것을 알 수 있다.
(미리 마지막 solution함수의 식을 살펴보자면 저 arr에는 입력된 수의 list(str())식을 통한 문자열 리스트가 될 것이다.😁)
첫 조건식은 if len(arr) <= 1 : return arr인데 한 자리수일 경우를 대비하여 바로 return시키는 명령이다.
위에 해당하지 않는 값들에 대해
우선적으로
mid라는 변수에 (입력된 값의 자릿수) // 2로 중앙 위치 숫자의 index값을 지정해준다.
그 후 leftright라는 변수에 중앙 기준으로 나눠진 리스트를 넣어준 후,
함수 자기 자신을 실행하는 재귀호출 식을 작성해주었다. 그리고 마무리 return merge(left, right)
이렇게 첫 조건식에 걸릴 때까지 반복하여 내려가고
앞서 선언했던 merge(left,right)로 return되는 각 단계만다 정렬된 result들에 다시 반복적인 merge()함수를 수행하는 병합 정렬로 마지막에 완성된 내림차순 정렬 리스트를 가져온다.

마무리인 세 번째 함수이자 울타리 같은 큰 틀 함수인
solution함수로 입력 값을 문자열 리스트로 만들어
위 과정들을 수행하여 가져온 내림차순 정렬 리스트int(''.join(mergeSort(arr)))로 다시 합쳐주며 정수값으로 변환하여 return시킨다.


(2)

def solution(n):
    ls = list(str(n))
    ls.sort(reverse = True)
    return int("".join(ls))

내가 사용한 독립함수 sorted()가 아닌 List 상속함수 .sort()함수를 사용한 풀이이며 역순배치를 위한 reverse=True와 리스트 요소들을 merge하는 "".join() 동일하게 사용하였다.
과정이 단축되어 보다 깔끔한 모습이 인상적이다.

0개의 댓글