상세 컨텐츠

본문 제목

[PROGRAMMERS] 프로그래머스 코딩테스트 연습 > 정렬(sort) 파이썬 문제풀이

취준/2. 코딩테스트

by ranlan 2021. 9. 9. 04:47

본문

728x90

프로그래머스 코딩테스트 연습 > 고득점 kit > 정렬(sort) 파트 문제풀이 파이썬 https://programmers.co.kr/learn/courses/30/parts/12198

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

K번째 수 (Level 1)

무난한 난이도의 문제

 

 내 코드 

def solution(array, commands):
    answer = []
    
    for start, end, idx in commands:
        new_array = array[start - 1 : end]
        answer.append(sorted(new_array)[idx - 1])
        
    return answer

 

 다른 사람 코드 

def solution(array, commands):
    # commands의 각 요소를 이용하여 array의 구간을 자르고 정렬 후 인덱스로 꺼냄
    return list(map(lambda x:sorted(array[x[0]-1:x[1]])[x[2]-1], commands))

한줄로 끝내다니,, 대단,, 나도 람다함수 잘 사용하고싶당..

 

* map(함수, 데이터) : 리스트의 각 요소를 지정된 함수로 처리

# map 사용 예시

# 이전 코드
a = [1.2, 2.5, 3.7, 4.6]
for i in range(len(a)):
    a[i] = int(a[i])
    
# map 사용 후 
a = list(map(int, a))

 

 

가장 큰 수 (Level 2)

간단하게 만들 수 있는 모든 경우의 수의 자릿수가 같음으로 문자열로 변환하여 정렬했을 때 큰 숫자가 무조건 앞쪽에 오게 하여 문자열을 만들면 되겠구나 생각했었다.

하지만,, 뒤에 모두 00으로 끝나는 경우나 가장 큰 자리수와 마지막 자리수가 같을 경우 등등 여러 예외가 있어서.. 따로 정렬 규칙이 필요했다..!

 

참고한 규칙 순서 팁 > https://programmers.co.kr/questions/19905

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 내 코드 

def solution(numbers):
    answer = ''

    str_array = list(map(str, numbers))
    str_array.sort(key=lambda x: x*4, reverse=True)
    
    for s in str_array:
        answer += s

    return answer if int(answer) != 0 else "0"

for문으로 문자열을 합치는 부분을 join 메서드를 사용하여 아래처럼 한줄로 가능

answer = ''.join(str_array)

 

* 규칙 설명

숫자를 문자열로 바꾼 리스트를 정렬할 때 키값으로 x가 아닌 x*4를 넘겨준다.

 

참고한 코드 관련 댓글에서 가져온 댓글

" 숫자를 반복시키는 이유는 앞에서부터 같은 숫자패턴이 존재하는 숫자들의 비교를 위해서입니다. 기존 숫자를 반복시키게 되면 그 숫자가 앞에 왔을 때 만들 수 있는 최대 숫자를 만들 수 있습니다. (완전한 숫자는 아니구요. 비교가 가능한 범위까지 만들 수있어요) "

 

처음 문제를 풀때 그냥 문자열사이 크기비교를 했더니 입출력 예시 2번을 틀렸다.

3과 30이 있는데 크기순으로하면 30이 3보다 커서 정답인 "9534330"이 아니라 "9534303"이 나오게 된다.

 

3 vs 30 -> 3333 vs 30303030 로 바꿔주어 0이 붙거나 가장 큰 자릿수의 숫자와 같은 숫자로 끝날 때 등등 문자열 크기 비교로 잡을 수 없는 예외처리를 해줄 수 있다.

 

** 입력받는 숫자가 1000이하라 나는 *4를 해줬는데 *3도 정답처리가 된다.

 

 다른 사람 코드1 

def solution(numbers):
    numbers = list(map(str, numbers))
    numbers.sort(key=lambda x: x*3, reverse=True)
    return str(int(''.join(numbers)))

내 코드와 비슷한데 str -> int -> str 변환하여 0일때의 처리를 if문 안쓰고 할 수 있었다.

 

 다른 사람 코드 2

import functools

def comparator(a,b):
    t1 = a + b
    t2 = b + a
    return (int(t1) > int(t2)) - (int(t1) < int(t2)) 
    # t1 > t2 : 1 - 0 = 1 (t1이 더 클때)
    # t2 > t1 : 0 - 1 = -1 (t2가 더 클때)
    # t1 == t2 : 0 - 0 = 0 (두 값이 같을 때)

def solution(numbers):
    n = [str(x) for x in numbers] # 숫자 문자열로 변환
    n = sorted(n, key=functools.cmp_to_key(comparator), reverse=True) # 정렬함수comparator 기준 정렬

    answer = str(int(''.join(n)))
    return answer

 

* functools.cmp_to_key(func) : 정렬함수 key 매개변수에 함수 전달하여 크기 비교 로직을 직접 구현 가능 (참고 https://wikidocs.net/109303)

   여기서 정렬함수는 클 때 양수, 작을 때 음수, 같을 때 0을 반환하는 크기비교 함수여야함

import functools

def xy_compare(n1, n2):
    if n1[1] > n2[1]:         # y 좌표가 크면
        return 1
    elif n1[1] == n2[1]:      # y 좌표가 같으면
        if n1[0] > n2[0]:     # x 좌표가 크면
            return 1
        elif n1[0] == n2[0]:  # x 좌표가 같으면
            return 0
        else:                 # x 좌표가 작으면
            return -1
    else:                     # y 좌표가 작으면
        return -1

src = [(0, 4), (1, 2), (1, -1), (2, 2), (3, 3)]
result = sorted(src, key=functools.cmp_to_key(xy_compare))
# [(1, -1), (1, 2), (2, 2), (3, 3), (0, 4)]

 

1을 반환하면 두번째 인자가 더 크다고 판단, -1을 반환하면 첫번째 인자가 더 크다고 판단, 0은 둘이 같다고 판단하여 결과로 나온 크기순으로 정렬

 

 

H-Index (Level 2)

이 문제 또한 문제 설명과 실행예시가 난해하다....... 

참고하면 좋을만한 질문 https://programmers.co.kr/questions/12096

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

리스트의 있는 값 중 하나가 답이 되는줄 알았는데 리스트는 정답의 범위만 정해주는 것이지 그 안에 꼭 답이 있는 것은 아니다.

리스트의 최대값을 반복문 돌릴때 최대값으로 잡고 점점 줄여나가며 조건에 맞는 최대값을 찾는 문제이다.

 

테스트 케이스 추가

입력 출력
 [5, 5, 5, 5]  4
 [5, 5, 5, 5, 5]  5
 [0, 0, 0]  0
 [0, 1, 2]  1

 

 내 코드 

def solution(citations):

    for h in range(max(citations), -1, -1):
        cited_more = list(c for c in citations if c >= h) # h번 이상 인용된 논문
        if len(cited_more) >= h: # h편 이상일때
            return h

첫 시도때 for문에서 두번째 인자는 범위에 포함되지 않는다는 것을 까먹고 max, 0을 인자로 줘서 테스트케이스 1개만 통과하지 못하였다ㅠㅠ

바로 쉽게 해결!

 

 다른 사람 코드 

def solution(citations):
    citations.sort(reverse=True)
    answer = max(map(min, enumerate(citations, start=1)))
    return answer

코드 작성 방법과 알고리즈들이 정말 다양한듯 하다.......... 난 아직 갈길이 멀었다..

 

728x90

관련글 더보기

댓글 영역