소소한 컴퓨터 이야기

체육복

by Cori

문제

도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다.

 

예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다.

 

체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다. 전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

 

제한사항 

· 전체 학생의 수는 2명 이상 30명 이하입니다. 

· 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고, 중복되는 번호는 없습니다.

· 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고, 중복되는 번호는 없습니다.

· 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.

· 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이떄 이 학생은 체육복을 하나만 도난당했다고 가정하며,

  남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

 

입출력 예

n lost  reserve return
5 [2, 4] [1, 3, 5] 5
5 [2, 4] [3] 4
3 [3] [1] 2

풀이

1. Me .. 프로그래머스 강사님 코드이다. (나는 못 품)

def solution(n, lost, reserve):
    # 빌릴 필요 x 
    s = set(lost) & set(reserve)
    # 빌려야 함 
    l = set(lost) - s 
    # 빌려줄 수 o
    r = set(reserve) - s 
    
    for x in sorted(r):
        if x-1 in l:
            l.remove(x-1)
        elif x+1 in l:
            l.remove(x+1)
    
    return n - len(l)

set 자료형의 연산을 이용하여, 체육복을 빌릴 필요가 없는 학생, 빌려야 하는 학생, 빌려줄 수 있는 학생을 구하였다. (중복된 학생이 없기 떄문에, set 자료형을 사용할 수 있었음) 이후 빌려줄 수 있는 학생들의 집합을 탐색하며, 자신보다 1 앞선 번호 학생의 체육복이 없을 경remove() 함수를 이용하여 제거하고, 탐색을 마친 후 자신보다 1 뒷 번호 학생의 체육복이 없을 경우 remove() 함수를 이용하여 제거하였다. 마지막으로, 이 작업이 끝난 후에도 빌려야 하는 학생의 수를 전체 학생의 수에서 빼어 체육 수업을 들을 수 있는 최대 학생의 수를 구하였다. 

 

2. Others

def solution(n, lost, reserve):
    _reserve = [r for r in reserve if r not in lost]
    _lost = [l for l in lost if l not in reserve]
    for r in _reserve:
        f = r - 1
        b = r + 1
        if f in _lost:
            _lost.remove(f)
        elif b in _lost:
            _lost.remove(b)
    return n - len(_lost)

체육복을 가져온 학생들 중 체육복을 빌려줄 수 있는 학생들과, 체육복을 잃어버린 사람들 중 체육복을 빌려야 하는 학생들로 구분하였다. 위 강사님의 코드(set 자료형)를 리스트를 활용한 형태로 바꾼 것으로, list에서도 remove() 함수를 활용할 수 있다는 사실을 배워간다. 

def solution(n, lost, reserve):
    answer = 0
    for i in range(1, n+1):
        if i not in lost: #안 잃어버린 학생
            answer += 1
        else:
            if i in reserve: #잃어버렸지만 여분도 있는 학생
                answer += 1
                reserve.remove(i)
                lost.remove(i)

    for i in lost: #잃어버리고 여분도 없어서 빌려야 하는 학생
        if i-1 in reserve:
            answer += 1
            reserve.remove(i-1)

        elif i+1 in reserve:
            answer +=1
            reserve.remove(i+1)

    return answer

전체 학생을 탐색하며, 잃어버리지 않은 학생의 수와 잃어버렸지만 여분도 있는 학생의 수를 구하였다. 이후, 잃어버린 학생을 탐색하며, 잃어버린 학생의 바로 앞 번호 학생이 여벌의 체육복을 가지고 있는지 체크하고, 탐색이 끝나면 잃어버린 학생의 바로 뒷 번호 학생이 여벌의 체육복을 가지고 있는지 체크하여 총 학생의 수를 구하였다.


자료 정리

1. Set() 자료형

0) 정의

-> 집합 관련 처리를 하기 위해 만들어진 자료형. 순서가 없고, 중복되지 않는 고유한 요소들을 가지고 있는 자료형이다. 다음과 같은 형태로 선언할 수 있다.

s1 = set({1, 2, 3})
s2 = set([1, 2, 3])
s3 = {1, 2, 3}

# 비어있는 집합 생성 
s4 = set()

1) 집합 연산자

-> 합집합, 차집합, 교집합 등을 구할 수 있다.

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])

print(s1 & s2)  # 교집합, {4, 5}, s1.intersection(s2)
print(s1 | s2)  # 합집합, {1, 2, 3, 4, 5, 6, 7, 8}, s1.union(s2)
print(s1 - s2)  # 차집합, {1, 2, 3}, s1.difference(s2)

2) 파이썬 함수

-> set() 자료형에 대해서도 add, update, remove, discard, pop, clear, in, len 연산 등을 적용할 수 있다. 

s_n = {1, 2, 3}
s_a = {'a','b','c'}

s_n.add(4)  # {1, 2, 3, 4} 

s_a.update({'a','e','c'})  # 요소 여러개 추가(중복 자동 제거), {'a','b','c','e'}
s_a.update(['e','f'])  # {'a','b','c','e','f'}

s_n.remove(2)  # {1, 3, 4}, set 내부에 지우려는 값이 없으면 오류 발생 
s_n.discard(4)  # {1, 3}
s_n.discard(5)   # {1, 3}, set 내부에 지우려는 값이 없어도 오류 발생하지 x 

s_a.pop()  # {'b','c','e','f'}, 임의의 요소 (맨 앞)를 반환하고, 제거함 (없으면 오류 발생)

s_a.clear()  # set(), len()으로 집합의 길이 검사 시 0 

if 3 in s_n:  # in 연산자 사용 가능 
	print('True') 

len(s_n)  # 2

'CS > Coding Test' 카테고리의 다른 글

행렬의 덧셈  (0) 2021.08.23
K번째 수  (0) 2021.08.23
예산  (0) 2021.08.22
2016년  (0) 2021.08.22
가운데 글자 가져오기  (0) 2021.08.22

블로그의 정보

코딩하는 오리

Cori

활동하기