https://programmers.co.kr/learn/courses/30/lessons/42746
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 > 0) and ((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 |
따라서 비교 하는 숫자들의 자리수를 맞춰?서 비교를 해보기 위해 문자열 곱셈을 하여 숫자의 길이를 늘렸다.
3 ----> 3 3 3
31 --> 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. 정리
프로그래머스 문제들은 답을 보면 정말 짧고 쉬워서 허무하다.
뭔가 자료형에 대한 깊은 이해도 필요한 거 같고, 비슷한 문제가 나왔을때 잘 풀어보고 싶다.
문자형태의 숫자 정렬은 이런식으로 진행되는 것 기억하쟈.!
'Study > Algorithm & Data structure' 카테고리의 다른 글
[프로그래머스][stack/queue] 프린터 python (200719) (0) | 2020.07.19 |
---|---|
[프로그래머스][stack/queue] 다리를 지나는 트럭 python (200717) (0) | 2020.07.17 |
[프로그래머스][hash] 전화번호목록 python (200715) (0) | 2020.07.15 |
[프로그래머스][hash] 베스트앨범 python (200715) (0) | 2020.07.15 |
[프로그래머스] H-index 정렬문제 python (200713) (1) | 2020.07.13 |
댓글