레벨 2부터 벽을 느끼는 나..
역시 물 실버였다.
-내 코드-
def solution(array, commands):
answer = []
for cmd in commands:
i, j, k = cmd
array_processed = sorted(array[i-1:j])
answer.append(array_processed[k-1])
return answer
딱 눈에 보이고 이해되는 대로 풀었다.
-신박한 풀이-
def solution(array, commands):
return list(map(lambda x:sorted(array[x[0]-1:x[1]])[x[2]-1], commands))
허허.. 차근차근 알아보자
array를 [i-1 : j]까지 슬라이스, 정렬한다.
그렇게 정렬된 배열의 인덱스가 k-1인 값(k번째 값)을 찾는다.
이 원리로, lambda를 이용해서 commands에 있는 x([2,5,3], [4,4,1], [1,7,3])을 매핑하고
리스트로 변환해서 반환한다.
-내 코드-
def solution(citations):
cit = sorted(citations) #citations을 정렬한다.
n = len(citations)
for i in range(n):
if cit[i] >= n-i: #정렬된 cit에서 한칸씩 가다가 그 값이 나머지 길이보다 크거나 같다면
return n-i #그 편수가 h다.
return 0 #n = 1일 때
처음에는 정렬하고 역순으로 탐색하는 식으로 생각하다가,
오름차순으로 하는게 정배겠구나 싶었다.
-신박한 풀이-
def solution(citations):
citations.sort(reverse=True)
answer = max(map(min, enumerate(citations, start=1)))
return answer
내가 해석한 바로는 이렇다.
문제 이해 능력 & 코딩 능력이 어마무시한 사람들이구나 싶다..
-틀린 내 코드-
lst = [3, 30, 34, 5, 9]일 때,
sorted(lst) - 정수형으로 lst를 받기 때문에, 정렬해주면 큰 숫자 순서대로 정렬한다.
list(map(str, lst)) - 문자열로 바꿔준다.
sorted(lst, reverse=True) 역순으로 정렬한다.
(이 때, 문자열을 기준으로 정렬하게 되면 각 원소의 첫 글자의 ascii코드 값만으로 정렬한다.)
그 다음 for문을 이용해서,
lst를 쭉 돌아가면서 만약 다음 원소를 뒤에 붙인 수가 앞에 붙인 수보다 작다면
그 둘의 위치를 바꿔준다.
위 lst에서는 '30'과 '3'의 경우에 서로 위치를 바꿔주는 것이었다.
(303 < 330)
answer = 그렇게 바뀐 lst를 공백없이 쭉~ 붙여서 쓴 것이고,
answer = '000'같은 경우를 제거하기 위해서 int로 바꿨다가 다시 str형으로 바꾼다.
(제출을 문자열로 해야하므로)
그리고 그렇게 해서 냈는데..
알았다.
내가 해놓은 for문은 '한번' 돌아가는 것 밖에 안 된다.
즉, 바뀌고난 후에도 최적의 수가 있을 수 있는데 그걸 반영을 못 하는 것이다.
그럼.. 어케해야하지?
찾아보았다.
문자열에서 인덱스에 따라 같은 값이라면 그 다음 문자의 ascii값을 비교한다.
맨 앞의 index 값부터 ascii 값으로 비교하기 때문에, False가 나온다.
'34'까지는 같지만 그 뒤의 '5'와 '4'를 비교했을 때 다르므로 False가 나온다.
이를 이용해서 입력되는 수의 상한이 1000이므로, 숫자로 이루어진 문자열에 *3을 이용한다.
왜 *3 일까?
예를들어, 121과 12가 있다고 치자.
'12' '121'이 나와야 가장 큰 수인데,
121121121과 121212를 따져보면,
앞의 '121'까지는 똑같고, 그 다음에서 '1'과 '2'로 갈리기 때문에, 어떤 것이 앞에 와야하는 지 알 수 있기 때문이다.
만약 *2 였다면?
9과 991이 있다고 쳐보자.
'9' '991'이 되어야 가장 큰 수인데,
99
991991
위 꼴에서는 '99'를 기준으로 991이 앞으로 오기 때문에, *3을 해주는 것이다.
(일의 자리 수를 세 자리수와 비교하기 위함.)
-수정한 코드-
def solution(lst):
lst = list(map(str, lst))
lst.sort(key = lambda x : x*3, reverse=True)
answer = str(int((''.join(lst))))
return answer
아.. 어렵다
++
import functools
def comparator(a,b):
t1 = a+b
t2 = b+a
return (int(t1) > int(t2)) - (int(t1) < int(t2)) # t1이 크다면 1 // t2가 크다면 -1 // 같으면 0
def solution(numbers):
n = [str(x) for x in numbers]
n = sorted(n, key=functools.cmp_to_key(comparator),reverse=True)
answer = str(int(''.join(n)))
return answer
내가 사용했던 아이디어로 푼 코드를 찾았다.
functools는 뭘까?
cmp_to_key == comparater to key
내가 만든 함수를 key로 이용할 수 있게 끔 해주는 것이다.
return 값을 1, 0, -1의 값으로 반환해줘야 한다.
이게 머선소리지?
혼자 공부하는 파이썬 38강 - 콜백, 람다, map, filter
cmp_to_key(내 비교기 - mycmp)를 쓰면,
class K를 (내 비교기)한테 멕여주는데,
(내 비교기)의 비교값에 따라 bool형태로 반환해주는 것 같다.
sorted의 매개변수로 key를 사용하면, 그 key 값의 조건에 맞게 오름차순으로 정렬한다.
(원소들이 문자열이므로 ascii 값 순으로 정렬)
functools.cmp_to_key(comparator)에 따라,
-1 ~ 1 순서로, 즉 (t1 < t2) ~ (t1 > t2)값으로 정렬해주는 것이다.
(문자열이더라도 쓰인 숫자가 다 다르니 return이 0인 값은 없다)
어쨌든.. 어떤 식으로 굴러가는지가 좀 궁금한데..
cmp_to_key(mycmp)의 return 값이 1, 0 일 때는 그대로, -1일 때는 역순으로 정렬을 하는 것 같다.
무슨 메커니즘으로 숫자를 정해서 비교하는 건지는 잘 모르겠지만,
어쨌든 1,0과 -1을 이용해서 정/역으로 구분하고 있다는 건 알겠다.
아마 초록색 구간으로 닫히면 한 번 해보고
그 다음에 기본 순서대로 가다가
또 다시 초록색 구간으로 닫히면 해보되 이미 시행한 수라면 패스
이런 느낌이 아닐까 싶다.
lambda와 enumerate 그리고 cmp_to_key 생각할 여지를 많이 줬다.
코딩 방법과 스킬을 아느냐 모르냐의 차이도 그렇고, 어떻게 구현할 지에 대한 문제의 이해도 주요한 것 같다.
여러 개 찾아보고 풀면서 늘려야지.
'PS > 프로그래머스' 카테고리의 다른 글
(프로그래머스, 파이썬) 힙 - [더 맵게, 디스크 컨트롤러, 이중우선순위큐] (0) | 2022.10.26 |
---|---|
(프로그래머스, 파이썬) 해시 - 베스트 앨범 (0) | 2022.10.26 |