본문 바로가기
Study/Algorithm & Data structure

[프로그래머스] 가장 큰 수 정렬문제 python (200713)

by 후이 (hui) 2020. 7. 13.
728x90
반응형

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

 

코딩테스트 연습 - 가장 큰 수

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요. 예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 ��

programmers.co.kr

 

1. 문제 

 

1)  문제 설명

 

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.

예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.

0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요. 

 

 

2) 제한 사항

 

  • numbers의 길이는 1 이상 100,000 이하입니다.
  • numbers의 원소는 0 이상 1,000 이하입니다.
  • 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

 

3) 입출력 예

 

[6, 10, 2] 6210
[3, 30, 34, 5, 9] 9534330

 

2. 풀이 

case 1 : [3, 30, 34, 5, 9]  두자리 숫자까지 나온 경우 

case 2: [999, 9, 998] 세자리 숫자까지 나온 경우 

특이 case : [0,0,0,0] 다 0인경우 

 

 

1) Insertion sort 컨셉 적용해서 풀어봄 (오답)  --> 두자리 까지만 고려함..

1
2
3
4
5
6
7
8
9
10
11
def solution(numbers):
    str_numbers = sorted(list(map(str,numbers)),reverse = True)
    for idx in range(len(numbers)-1):
        while (idx > 0and ((str_numbers[idx][0== str_numbers[idx+1][0]) and (len(str_numbers[idx]) > len(str_numbers[idx+1]))):
            if str_numbers[idx][1>= str_numbers[idx+1]:
                pass
            else:
                str_numbers[idx], str_numbers[idx+1= str_numbers[idx+1], str_numbers[idx]
            idx-=1
    return " ".join(str_numbers)
 
cs

 

이 경우 case 1은 통과가 되지만 case 2는 통과하지 못한다. 

str_numbers[idx][1>= str_numbers[idx+1] 로 두번째 자리 수만 비교하는 과정이 있기 때문에.  

 

 

 

2) 숫자 반복 후 대소비교 (일부 정답, 접근법은 맞음 ) 

1
2
3
4
def solution2(numbers):
    str_numbers = sorted(list(map(str, numbers)), reverse=True, key = lambda x:x*3)
    return " ".join(str_numbers)
 
cs

 

그럼 case 2 와 같은 경우는 어떻게 통과할까. 세번째 자리 수를 비교하는 과정을 추가하면 될지는 모르겠지만, (시도안해봄)

더 쉬운 방법은 숫자의 길이를 늘여 보는 것이다.

 

가령 [3,300,31,387] 라는 숫자 리스트가 있다면 가장 큰 조합은 --> 387 3 31 310 이다. 

가장 작은 수가 3 이더라도, 첫째자리 숫자 "3"은  310 31 의 두번째 자리 숫자 "1" 보다 크기 때문에, 3은 310 31 보다 앞에 나온다. 

또 31은 31의 두번째 자리숫자 "1" 이 310 의 세번째 자리 숫자 "0" 보다 크기 때문에, 310 보다 앞에 나온다. 

 

 

3 >31, 310 31 >310

3 
31
310

31
310

따라서 비교 하는 숫자들의 자리수를 맞춰?서 비교를 해보기 위해 문자열 곱셈을 하여 숫자의 길이를 늘렸다. 

3 ----> 3 3 3
3-->  3 1 3 1 3 1
310 -> 3 1 0 3 1 0 3 1 0

 

3번씩 써서 늘리는 이유는 문제 조건에서 입력되는 숫자의 최대 크기가 1000미만이라 제시했기 때문이다.

따라서 입력되는 숫자의 최소길이는 1자리 최대길이는 3자리 일것이고, 1자리 숫자를 3자리로 불려줌으로써 

문자형태의 숫자를 대소비교한다.

333>313>310   --> 3 > 31> 310 순으로 나열 

이렇게 했을 때 확실히 문제에서 요구되는 방식으로 정렬이 되는 것을 확인 할 수 있다.

 

하지만!!  위의 코드로 돌릴경우 딱하나의 테스트 케이스를 통과하지 못한다.  바로 특이 케이스 [0,0,0,0] 이다. 

 

 

3) 숫자 반복 후 대소비교 (정답, 특이 케이스 해결) 

 

1
2
3
def solution3(numbers):
    str_numbers = sorted(list(map(str, numbers)), reverse=True, key = lambda x:x*3)
    return str(int(" ".join(str_numbers)))
cs

 

2) 의 경우에서 [0,0,0,0]을 입력했을 때 나오는 값은 0000이다. 이는 0을 숫자가 아닌 문자로 리스트에 담고 join 했기 때문이다. 

따라서 join 했던 "0000" 을 숫자로 한번 바꿔주고

다시 문자로 출력하는 과정을 거치면 0 으로 바뀐 뒤 출력이 된다.

이 과정만 추가하면 11번 케이스를 통과한다. 

 

 

 

3. 정리 

 

프로그래머스 문제들은 답을 보면 정말 짧고 쉬워서 허무하다. 

뭔가 자료형에 대한 깊은 이해도 필요한 거 같고, 비슷한 문제가 나왔을때 잘 풀어보고 싶다.  

문자형태의 숫자 정렬은 이런식으로 진행되는 것 기억하쟈.!

728x90
반응형

댓글