난이도: ⭐
풀이 시간: 30분
시간 제한: 1초
메모리 제한: 128MB
기출: 핵심 유형
'공포도'가 높은 모험가는 쉽게 공포를 느껴 위험 상황에서 제대로 대처할 능력이 떨어진다. 공포도가 X인 모험가는 반드시 X명 이상으로 구성한 모험가 그룹에 참여해야 여행을 떠날 수 있도록 규정했다.
예를 들어 N=5이고, 각 모험가의 공포도가 2 3 1 2 2
라고 가정했을 때, 그룹 1에 공포도가 1,2,3인 모험가를 한 명씩 넣고, 그룹 2에 공포도가 2인 남은 두 명을 넣게 되면, 총 2개의 그룹을 만들 수 있다.
또한 몇 명의 모험가는 마을에 그대로 남아 있어도 되기 때문에, 모든 모험가를 특정한 그룹에 넣을 필요는 없다.
N명의 모험가에 대한 정보가 주어졌을 때, 여행을 떠날 수 있는 그룹 수의 최댓값을 구하는 프로그램을 작성하시오.
입력 조건
출력 조건
# 입력 예시
5
2 3 1 2 2
# 출력 예시
2
<내가 푼 방식>
n = int(input())
fear = list(map(int, input().split()))
result = 0
# 공포도가 큰 순서대로 정렬
fear = sorted(fear, reverse=True)
for i in range(n):
# 공포도가 1이면 혼자 가기
if fear[i] == 1:
#first_one = i
#result += n - i
result += 1
del fear[i]
# 공포도가 큰 순서대로 정렬했으므로 0번 인덱스가 공포도가 가장 큰 사람
max_fear = fear[0]
# 가장 큰 공포도 수 만큼 모험가를 한 그룹으로 묶어주기
while max_fear <= len(fear): # max_fear 수 보다 사람이 적으면 그룹 못 만듦
max_fear = fear[0]
del fear[0:max_fear]
result += 1
if len(fear) == 0: break
print(result)
<답안>
공포도가 오름차순으로 정렬되어 있다는 점에서, 항상 최소한의 모험가의 수만 포함하여 그룹 결성
➡️ 따라서 최대한 많은 그룹이 구성되는 방법이므로, 항상 최적의 해
를 찾을 수 있음
n = int(input())
data = list(map(int, input().split()))
data.sort()
result = 0 # 그룹 수
count = 0 # 현재 그룹에 포함된 모험가의 수
for i in data: # 공포도가 낮은 것부터 하나씩 확인하며
count += 1 # 현재 그룹에 해당 모험가를 포함시키기
if count >= i: # 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성
result += 1 # 총 그룹의 수 증가시키기
count = 0 # 현재 그룹에 포함된 모험가의 수 초기화
print(result)
난이도: ⭐
풀이 시간: 30분
시간 제한: 1초
메모리 제한: 128MB
기출: Facebook 인터뷰
각 자리가 숫자(0부터 9)로만 이루어진 문자열 S가 주어졌을 때, 왼쪽부터 오른쪽으로 하나씩 모든 숫자를 확인하며 숫자 사이에 'x' 혹은 '+' 연산자를 넣어 결과적으로 만들어질 수 있는 가장 큰 수를 구하는 프로그램을 작성하시오.
단, +보다 x를 먼저 계산하는 일반적인 방식과는 달리, 모든 연산은 왼쪽에서부터 순서대로 이루어진다고 가정한다.
입력 조건
출력 조건
예를 들어 02984라는 문자열이 주어지면, 만들어질 수 있는 가장 큰 수는 (((0 + 2) x 9) x 8) x 4) = 576이다.
또한 만들어질 수 있는 가장 큰 수는 항상 20억 이하의 정수가 되도록 입력이 주어진다.
# 입력 예시 1
02984
# 출력 예시 1
576
# 입력 예시 2
567
# 출력 예시 2
210
<내가 푼 방식>
s = list(map(int, input())) # 공백 없이 입력 받기
plus = 0 # 연속하는 두 수를 더한 경우의 값
mul = 0 # 연속하는 두 수를 곱한 경우의 값
result = s[0]
for i in range(1, len(s)):
plus = result + s[i]
mul = result * s[i]
if plus >= mul:
result = plus
else:
result = mul
print(result)
<답안>
📌 두 수 중에서 하나라도 1 이하인 경우에는 더하기, 두 수가 모두 2 이상인 경우에는 곱하기
data = input()
# 첫 번째 문자를 숫자로 변경하여 대입
result = int(data[0])
for i in range(1, len(data)):
# 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다는 더하기 수행
num = int(data[i])
if num <= 1 or result <= 1:
result += num
else:
result *= num
print(result)
난이도: ⭐
풀이 시간: 20분
시간 제한: 2초
메모리 제한: 128MB
기출: 핵심 유형
링크: https://www.acmicpc.net/problem/1439
다솜이는 0과 1로만 이루어진 문자열 S를 가지고 있다. 다솜이는 이 문자열 S에 잇는 모든 숫자를 전부 같게 만들려고 한다. 다솜이가 할 수 있는 행동은 S에서 연속된 하나 이상의 숫자를 잡고 모두 뒤집는 것이다.
예를 들어 S = 0001100일 때,
하지만, 처음부터 4번째 문자부터 5번째 문자까지 문자를 뒤집으면 한 번에 0000000이 되어서 1번 만에 모두 같은 숫자로 만들 수 있다.
문자열 S가 주어졌을 때, 다솜이가 해야 하는 행동의 최소 횟수를 출력하세요.
입력 조건
출력 조건
# 입력 예시
0001100
# 출력 예시
1
<내가 푼 방식> - ❗틀림❗
❗책의 예시는 맞았지만, 백준 예시에서 틀림
s = list(map(int, input()))
index = 0 # 앞 인덱스의 숫자와 이번 인덱스의 숫자가 다를 때, 이번 인덱스 저장
result = 0
for i in range(1, len(s)):
if s[i - 1] == s[i]:
continue
else:
if index == 0:
index = i
else:
if s[i] == 1:
for j in range(index, i):
s[j] = 1
else:
for j in range(index, i):
s[j] = 0
result += 1
print(result)
s = list(map(int, input()))
result = 0
for i in range(1, len(s)):
if s[i - 1] == s[i]:
continue
else: # 앞의 숫자와 현재 숫자가 다르면
if s[i] == 1:
for j in range(0, i): # 0번 인덱스부터 i-1까지 숫자 뒤집기
s[j] = 1
else:
for j in range(0, i):
s[j] = 0
result += 1
print(result)
<답안>
📌 전부 0으로 바꾸는 경우
와 전부 1로 바꾸는 경우
중에서 더 적은 횟수를 가지는 경우를 계산
data = input()
count0 = 0 # 전부 0으로 바꾸는 경우
count1 = 0 # 전부 1로 바꾸는 경우
# 첫 번째 원소에 대해서 처리
if data[0] == '1':
count0 += 1
else:
count1 += 1
# 두 번째 원소부터 모든 원소를 확인하며
for i in range(len(data) - 1):
if data[i] != data[i + 1]:
# 다음 수에서 1로 바뀌는 경우
if data[i + 1] == '1':
count0 += 1
# 다음 수에서 0으로 바뀌는 경우
else:
count1 += 1
print(min(count0, count1))
난이도: ⭐
풀이 시간: 30분
시간 제한: 1초
메모리 제한: 128MB
기출: K 대회 기출
N개의 동전을 이용하여 만들 수 없는 양의 정수 금액 중 최솟값을 구하는 프로그램을 작성하시오.
입력 조건
출력 조건
# 입력 예시
5
3 2 1 1 9
# 출력 예시
8
예를 들어, N=5이고, 각 동전이 각각 3원, 2원, 1원, 1원, 9원짜리 동전이라고 가정한다. 이때 만들 수 없는 양의 정수 금액 중 최솟값은 8원이다.
또 다른 예시로, N=3이고, 각 동전이 각각 3원, 5원, 7원짜리 동전이라고 가정한다. 이때 만들 수 없는 양의 정수 금액 중 최솟값은 1원이다.
<내가 푼 방식>
이렇게 풀면 안될듯...🙄
<답안>
📌 현재 상태를 1부터 target-1까지의 모든 금액을 만들 수 있는 상태
라고 했을때, 매번 target인 금액도 만들 수 있는지(현재 확인하는 동전의 단위가 target 이하인지) 체크하는 것. 만약 만들 수 있다면, target의 값을 업데이트(현재 상태를 업데이트)
n = int(input())
data = list(map(int, input().split()))
data.sort()
target = 1
for x in data:
# 만들 수 없는 금액을 찾았을 때 반복 종료
if target < x:
break
target += x
print(target)
난이도: ⭐
풀이 시간: 30분
시간 제한: 1초
메모리 제한: 128MB
기출: 2019 SW 마에스트로 입학 테스트
A,B 두 사람이 서로 무게가 다른 볼링공을 고르려고 한다. 볼링공은 총 N개가 있으며 각 볼링공마다 무게가 적혀 있고, 공의 번호는 1번부터 순서대로 부여된다. 같은 무게의 공이 여러 개 있을 수 있지만, 서로 다른 공으로 간주한다. 볼링공의 무게는 1부터 M까지의 자연수 형태로 존재한다.
두 사람이 볼링공을 고르는 경우의 수를 구하는 프로그램을 작성하시오.
입력 조건
출력 조건
# 입력 예시 1
5 3
1 3 2 3 2
# 출력 예시 1
8
# 입력 예시 2
8 5
1 5 4 3 2 4 5 2
# 출력 예시 2
25
예를 들어 N=5, M=3이며 각각의 무게가 차례대로 1,3,2,3,2일 때 각 공의 번호가 차례대로 1번부터 5번까지 부여된다. 이때 두 사람이 고를 수 있는 볼링공 번호의 조합을 구하면 아래와 같다.
(1번, 2번), (1번, 3번), (1번, 4번), (1번, 5번), (2번, 3번), (2번, 5번), (3번, 4번), (4번, 5번)
결과적으로 두 사람이 공을 고르는 경우의 수는 8가지!
<내가 푼 방식>
이중 반복문
안 반복문에서 현재 원소와 뒤에 있는 원소들을 비교해서 무게가 다르면 result 1 증가시킨다.
n, m = map(int, input().split())
k = list(map(int, input().split()))
result = 0
for i in range(n):
for j in range(i, n):
if k[i] != k[j]:
result += 1
print(result)
<답안>
무게마다 볼링공이 몇 개 있는지 계산한다.
A가 특정한 무게의 볼링공을 선택했을 때, 이어서 B가 볼링공을 선택하는 경우를 계산한다.
n, m = map(int, input().split())
data = list(map(int, input().split()))
# 1부터 10까지의 무게를 담을 수 있는 리스트
array = [0] * 11
for x in data:
# 각 무게에 해당하는 볼링공의 개수 카운트
array[x] += 1
result = 0
# 1부터 m까지의 각 무게에 대하여 처리
for i in range(1, m + 1):
n -= array[i] # 무게가 i인 볼링공의 개수(A가 선택할 수 있는 개수) 제외
result += array[i] * n # B가 선택하는 경우의 수와 곱해주기
print(result)
반복문 안에 있는 result += array[i] * n
을 위 문제의 예시를 기준으로 보면 아래와 같다.
1) A가 무게가 1인 공을 선택할 때의 경우의 수: 1
(무게가 1인 공의 개수) x 4
(B가 선택하는 경우의 수) = 4가지 경우
2) A가 무게가 2인 공을 선택할 때의 경우의 수: 2
(무게가 2인 공의 개수) x 2
(B가 선택하는 경우의 수) = 4가지 경우
3) A가 무게가 3인 공을 선택할 때의 경우의 수: 2
(무게가 3인 공의 개수) x 0
(B가 선택하는 경우의 수) = 0가지 경우
난이도: ⭐
풀이 시간: 30분
시간 제한: 1초
메모리 제한: 128MB
기출: 2019 카카오 신입 공채
링크: https://programmers.co.kr/learn/courses/30/lessons/42891
📍 이 문제는 기본 코드가 제공되므로 상기 링크를 통해서 풀어야 한다!
회전판에 먹어야 할 N개의 음식이 있다. 각 음식에는 1부터 N까지 번호가 붙어있으며, 각 음식을 섭취하는데 일정 시간이 소요된다. 무지는 다음과 같은 방법으로 음식을 섭취한다.
무지의 먹방을 시작한 지 K초 후에 네트워크 장애로 인해 방송이 잠시 중단되었다. 무지는 네트워크 정상화 후 다시 방송을 이어갈 때, 몇 번 음식부터 섭취해야 하는지를 알고자 한다.
각 음식을 모두 먹는 데 필요한 시간이 담겨 있는 배열 food_times, 네트워크 장애가 발생한 시간 K초가 매개변수로 주어질 때 몇 번 음식부터 다시 섭취하면 되는지 return 하도록 solution 함수를 완성하시오.
제한 사항
정확성 테스트 제한 사항
효율성 테스트 제한 사항
입출력 예시
food_times | k | result |
---|---|---|
[3,1,2] | 5 | 1 |
입출력 예시에 대한 설명
5초에서 네트워크 장애가 발생했다. 1번 음식을 섭취해야 할 때 중단되었으므로, 장애 복구 후에 1번 음식부터 다시 먹기 시작하면 된다.
<내가 푼 방식>
k초를 range로 반복문을 돌려서
현재 음식 번호에 해당하는 food_times의 원소의 시간을 -1
현재 음식 번호(answer)를 + 1씩 증가 => 마지막 번호를 벗어나면 다시 1로
현재 음식 번호에 해당하는 food_times의 원소 시간이 0이면
현재 음식 번호를 1 증가 => 원소 시간을 -1
for문 끝나고 현재 음식 번호에 시간이 0이 아니면 현재 번호 출력
0이면 0이 아닌 다음 번호 출력
def solution(food_times, k):
answer = 1 # 현재 음식 번호
for i in range(k + 1):
# 마지막 번호의 음식을 섭취한 후 다시 1번 음식
if answer > len(food_times):
answer = 1
# 현재 번호의 음식을 다 먹은 상태라면 남아있는 음식 번호 찾기
while(1):
if food_times[answer - 1] == 0:
answer += 1
else: break
# 네트워크 장애가 생겼을 때 중단
if i == k:
break
# 현재 번호의 음식을 섭취하고 시간을 -1
food_times[answer - 1] -= 1
# 회전판을 돌려 다음 음식을 가져오기
answer += 1
return answer
<해설>
📌 시간이 적게 걸리는 음식부터 확인하는 그리디
방식으로 해결
우선순위 큐
우선순위 큐를 구현하기 위해 heapq
를 이용 - 다익스트라 알고리즘 파트에 설명
step 0)
step 1)
step 2)
남은 시간 + 1
번째 음식 번호를 출력한다.import heapq
def solution(food_times, k):
# 전체 음식을 먹는 시간보다 k가 크거나 같다면 -1
if sum(food_times) <= k:
return -1
# 시간이 작은 음식부터 빼야 하므로 우선순위 큐를 이용
q = []
for i in range(len(food_times)):
# (음식 시간, 음식 번호) 형태로 우선순위 큐에 삽입
heapq.heappush(q, (food_times[i], i + 1))
sum_value = 0 # 먹기 위해 사용한 시간
previous = 0 # 직전에 다 먹은 음식 시간
length = len(food_times) # 남은 음식의 개수
# sum_value + (현재의 음식 시간 - 이전 음식 시간) * 현재 음식 개수와 k 비교
while sum_value + ((q[0][0] - previous) * length) <= k:
now = heapq.heappop(q)[0]
sum_value += (now - previous) * length
length -= 1 # 다 먹은 음식 제외
previous = now # 이전 음식 시간 재설정
# 남은 음식 중에서 몇 번째 음식인지 확인하여 출력
result = sorted(q, key=lambda x: x[1]) # 음식의 번호 기준으로 정렬
return result[(k - sum_value) % length][1]