Day 4 학습 내용 정리
오늘 학습 내용은 코딩테스트 문제 풀이 위주이다.
마라톤에 참여한 선수들의 이름 배열 participants와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 리턴하는 문제
# Best sol
def solution(participant, completion):
dic = {}
for i in participant:
# 키 i가 존재하면 1, 아니면 0 이후 + 1처리
dic[i] = dic.get(i, 0) + 1
for i in completion:
dic[i] -= 1
dnf = [k for k, v in dic.items() if v > 0]
answer = dnf[0]
return answer
# 나의 풀이
def solution(participant, completion):
member = {}
value = 0
for i in participant:
member[hash(i)] = i
value += hash(i)
for i in completion:
value -= hash(i)
return member[value]
< 풀이 과정 >
'key'를 기준으로 매핑되는 해시 자료구조를 이용한 풀이.
member라는 dictionary를 만들어 준 후, hash함수를 이용해 member[hash(i)] = i 로 저장하고 value는 각 이름마다 고유 해시번호가 다르기에 + 해준다.
이후 완주한 선수들에 한해 value에서 각 해시값을 빼준다면 결과적으로 member딕셔너리에서 남은 value를 키에 넣는다면 완주하지 못한 선수만 남게 된다.
앞 단계에서의 선택이 이후 단계에서의 동작에 의한 해의 최적성에 영향 X
현 상태에서 최선 고르는 기법
전체 학생 수 n, 체육복을 도난 당한 학생들 번호가 담긴 lost, 여벌 체육복을 가져온 학생의 번호가 담긴 배열 reseve가 있을 때 체육 수업을 들을 수 있는 학생의 최댓값을 구하는 문제
# Best Sol
def solution(n, lost, reserve):
# 체육복 있는데 도난 당한 경우
s = set(lost) & set(reserve)
# 빌려야 하는 애들
l = set(lost) - s
# 빌려줄 수 있는 애들
r = set(reserve) - s
# O(klogk)에 비례 하게 됌
for i in sorted(r):
if i-1 in l:
l.remove(i-1)
elif i+1 in l:
l.remove(i+1)
return n - len(l)
< 풀이 과정 >
시간 복잡도, set형으로 인한 복잡도 감소 등 위 풀이를 보고 감탄을 했다.✍️
문제에서 체육복을 가져왔는데 도난 당할 수도 있다고 했다. 따라서 이를 활용하여 다음과 같이 표현한다.
이후 for문으로 학생들 번호가 오름차순 정렬된 r에 대해 순회를 진행하며 i-1, i+1이 빌려야 하는 집합 l에 포함되면 remove해주고 최종적으로 학생 수 - l에 속한 수 를 리턴한다.
문자열 형식으로 숫자 number가 주어지고 제거할 수의 개수 k가 주어졌을 때 가장 큰 숫자를 문자열 형태로 리턴하는 문제
# Best Sol
def solution(number, k):
collected = []
for i, num in enumerate(number):
while len(collected) > 0 and collected[-1] < num and k > 0:
collected.pop()
k -= 1
if k == 0:
collected = list(number[i:])
break
collected.append(num)
collected = collected[:-k] if k > 0 else collected
answer = ''.join(collected)
return answer
# 나의 풀이
def solution(number, k):
answer = []
# 모든 문자 순회
for num in number:
# answer 리스트가 비어있으면 추가하고 한 문자씩 확인 위해 continue
if not answer:
answer.append(num)
continue
# 제거해야할 수가 존재하면
if k > 0:
# answer에 넣은 수와 다음 수 비교해서, 다음 수가 더 큰 경우에 한해 pop, -1 진행
while answer[-1] < num:
answer.pop()
k -= 1
# answer가 비어있거나, 제거해야할 수가 없다면 중단
if not answer or k <= 0:
break
# 제거하고 남은 숫자들 추가
answer.append(num)
# 제거가 다 안된 경우 ex) 98765와 같은 내림차순 정렬된 리스트, 0 ~ -k번까지만 뽑기
if k > 0:
answer = answer[:-k]
else:
answer
# 원소만 합쳐서 리턴
return ''.join(answer)
풀이 참고
위 링크를 참고하면 된다! (어제 풀었던 문제이기에 PASS)
sorted(리스트명, key = lambda x : x~, reversed = True)
위 함수를 이해한다면 링크를 가볍게 보고 넘어가도 된다!