0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 만들어내야 하는 문제입니다.
예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.
문제를 보고 먼저 든 생각은, 자릿수의 길이에 상관없이 해당 원소에서 자릿수가 큰 쪽부터 비교를 해야 한다고 생각했는데요!
예를 들어, [6, 10, 200]에서는 10에서 자릿수가 큰 수는 십의 자리로 1입니다. 그리고 200에서 자릿수가 큰 수는 백의 자리로 2입니다. 그래서 6, 1, 2를 비교해서 가장 큰 6을 맨 앞에 위치시켜야 하겠죠?!
각 자릿수의 수를 알아내는 방법
바로 str 함수를 사용하면 됩니다.
num = 342
str_num = str(num)
print(str_num[0]) # 출력 : 3
print(str_num[1]) # 출력 : 4
384라는 int 형을 문자열로 변환한 후 인덱스 0을 뽑아내면 3이 출력됩니다. 인덱스 1을 뽑아내면 4입니다.
첫 자릿수가 작은 수부터 정렬하는 방법
바로 str 함수를 통해 정렬하면 됩니다!
문자열은 사전순으로 정렬하기 때문에 숫자를 문자열로 변환하면 각 숫자의 첫 자릿수부터 비교가 이루어집니다.
예를 들어, 숫자 리스트 numbers가 [10, 2, 7, 56, 34]라고 가정해 보겠습니다. 이 리스트를 문자열로 변환하면 ['10', '2' , '7' , '56' '34']이 되고, 이를 정렬하면 사전순으로 정렬됩니다. 즉, [10, 2, 34, 56, 7] 순서로 정렬됩니다.
이를 통해 숫자의 첫 자릿수가 가장 작은 수부터 정렬할 수 있습니다!
코드로 나타내면 다음과 같습니다.
numbers = [10, 2, 34, 56, 7]
sorted_numbers = sorted(numbers, key=lambda x: str(x)[0])
print(sorted_numbers)
key=lambda x: str(x)[0]를 통해 각 숫자를 문자열로 변환한 후, 첫 번째 문자(자릿수가 가장 큰 문자)를 기준으로 정렬할 수 있습니다! [10, 2, 34, 56, 7]를 이 방법으로 정렬하면 [2, 34, 56, 7, 10] 순서로 정렬됩니다.
lambda 사용법은 아래에서 더 자세히 알려드리겠습니다!
문자열의 대소비교
여기서 문자열의 대소비교에 대해서 더 자세히 설명하자면 다음과 같습니다.
- 첫 번째 문자부터 순서대로 비교합니다.
- 만약 두 문자열이 같다면, 다음 문자를 비교합니다. 한 문자열을 끝 자릿수까지 탐색했는데도 다른 문자열과 같다면, 길이가 더 짧은 문자열이 더 작은 것으로 간주됩니다.
- 만약 두 문자가 다르다면, 그 문자의 아스키코드 값 또는 유니코드 코드 포인트 값을 비교하여 더 작은 값을 가진 문자열이 더 작은 것으로 간주됩니다.
9, 91, 910이라는 원소가 있을 때,
1. 9 vs 91
- 첫 번째 문자를 비교합니다. '9'와 '9'는 같습니다.
- 다음 문자가 없으므로 길이가 더 짧은 '9'가 '91'보다 작습니다.
- 따라서 '9' < '91'입니다.
2. 9 vs 910
- 첫 번째 문자를 비교합니다. '9'와 '9'는 같습니다.
- 다음 문자가 없으므로 길이가 더 짧은 '9'가 '91'보다 작습니다.
- 따라서 ' 9' < '910'입니다.
3. 91 vs 910
- 첫 번째 문자를 비교합니다. '9'와 '9'는 같습니다.
- 다음 문자를 비교합니다. '1'과 '1'은 같습니다.
- 문자열 '91'의 길이가 더 짧으므로 '91' < '910'입니다.
따라서, 9 < 91 < 910입니다.
역순으로 한다면 910 → 91 → 9입니다
lambda
람다(lambda) 함수는 파이썬에서 간단한 익명 함수를 만들 때 사용됩니다.
lambda arguments: expression
arguments는 함수의 매개변수를 나타내고, expression은 그 함수의 반환값을 계산하는 식입니다.
예를 들어,
lambda x: x * 2
위 함수는 하나의 인자 x를 받아서 그 인자를 2배로 만들 수 있습니다.
이를 토대로 위에서 제공한 코드를 해석하면
key=lambda x: str(x)[0]
여기서 x는 numbers 리스트에서 뽑아낸 각 숫자이며, 각 숫자 x를 str 함수를 통해 문자열로 변환한 후, 첫 번째 문자(자릿수가 가장 큰 문자)를 뽑아내는 함수라고 할 수 있습니다.
이후 sorted 함수를 통해 lambda 함수로 뽑아낸 첫 번째 문자(자릿수가 가장 큰 문자)를 기준으로 정렬할 수 있습니다.
위 코드는 상향식 정렬이기 때문에 첫 번째 문자가 점점 커지는 순으로 정렬됩니다.
첫 번째 문자가 큰 수부터 작아지는 순으로 정렬하기 위해선,
numbers = [10, 2, 34, 56, 7]
print(sorted(numbers, reverse=True, key=lambda x: str(x)[0]))
위와 같이 reverse=True를 사용하면 됩니다.
이하 위 코드를 역순코드라고 칭하겠습니다!
문제 풀이 아이디어
1. 문자를 4번 반복한다
[9, 910, 91]에 위 문자열 역순코드를 적용하면 [910, 91, 9]가 되지만 910이 아닌, 9가 더 앞에 와야 가장 큰 수가 만들어질 수 있습니다.
910909가 아닌 9 → 910 → 90으로 배치돼야 990910이 되어 더 커질 수 있기 때문입니다.
이러한 문제를 해결하기 위해 각 원소를 4번 반복하면 됩니다.
4번 반복하는 이유는 문제에서 원소의 입력 조건이 1000 이하이기 때문에 원소를 가장 큰 자릿수인 4로 맞추어 비교하기 위함입니다.
예를 들어, 1000, 100, 1이 주어졌을 때 역순코드로는 10001001이 되지만, 가장 큰 수를 만들어내기 위해선 11001000이 되어야 합니다. 이러한 문제를 각 원소를 4번 반복하여 자릿수를 맞추어 해결할 수 있습니다.
여기서 원소들을 4번 반복하면
1000 → 1000100010001000
100 → 100100100100
1 → 1111
입니다.
이를 큰 수부터 나열하면, 1111 → 1001 → 1000입니다. 이는 본래 1 → 100 → 1000으로 가장 큰 수 11001000을 만들어내기 위한 순서입니다!
즉, 4자리(제일 큰 입력조건의 자릿수)로 바꾸어 비교하면 가장 큰 수를 만들어낼 수 있는 것입니다.
2. 답을 숫자로 바꾸고 다시 문자열로
특이 케이스 [0, 0, 0, 0]을 해결하기 위함입니다!
0000이 원소로 주어진다면 나오는 값이 0000인데 이렇게 나오면 안 되고 0으로 나와야 합니다. 그 이유는 가장 큰 "수"를 return하는 문제이기 때문입니다. 0000이라는 수는 없으니 0으로 나와야 하는 것입니다.
이를 해결하기 위해 간단히 0000을 int 형으로 변환한 후, 문제에서 문자열로 return 하라고 했으니 다시 string 형으로 변환하면 됩니다.
str(int(''.join(nums)))
여기서 join 함수는 문자열을 합치는 데 사용됩니다.
문자열.join(반복 가능한 객체)
여기서 문자열은 이어붙일 때 사용할 구분자(예: 공백, 쉼표 등)입니다. 반복 가능한 객체는 문자열을 합치고자 하는 요소들을 포함하는 iterable 객체입니다.
예를 들어, 다음과 같이 문자열이 ", "라면
numbers = [1, 2, 3, 4, 5]
result = ", ".join(map(str, numbers))
print(result) # 출력 : "1, 2, 3, 4, 5"
위와 같이 활용할 수 있습니다
https://school.programmers.co.kr/learn/courses/30/lessons/42746
def solution(numbers):
# 자릿수를 뽑아내기 위해 모두 문자형으로 변경
nums = list(map(str, numbers))
# nums.sort(key=lambda x: x*4, reverse=True)
nums = sorted(nums, reverse=True, key = lambda x:x*4)
return str(int(''.join(nums)))
정렬... level 1은 너무 쉬워 보여서 level 2도 쉽게 풀 수 있을 줄 알았다. 사실 이 문제도 아이디어만 생각해 내면 쉽게 풀겠다 싶었지만,
아이디어 찾다가 머리 다 뽑을 뻔했다....ㅎ
아무튼 이해하고 풀어내서 다행이다.
lambda 식도 이번에 확실히 알게 되어서 좋다!
코드 만들면서 알게 된 지식도 이 글에 제대로 정리한 거 같아서 뿌듯하다~
'코딩 테스트 일지 📒' 카테고리의 다른 글
[이진탐색] 정렬된 배열에서 특정 수의 개수 구하기 (0) | 2024.03.22 |
---|---|
[이진탐색] 떡볶이 떡 만들기 + map, 리스트 컴프리헨션 (0) | 2024.03.21 |
[정렬] 두 배열의 원소 교체 + 입력받은 개수만큼 1차원 배열로, 리스트 원소값 서로 바꾸기, 리스트 원소의 합 (1) | 2024.03.19 |
[DFS & BFS] 프로그래머스_게임 맵 최단거리 & 나동빈_미로탈출 (1) | 2024.03.13 |
[DFS & BFS] 음료수 얼려먹기 + 2차원 리스트 생성 및 입력 방법 (0) | 2024.03.11 |