이것이 코딩테스트다 with 파이썬

🌼 Greedy Algorithm (탐욕 알고리즘)

  • 현재 상황에서 지금 당장 좋은 것만 고르는 방법
  • 일반적인 상황에서 그리디 알고리즘은 최적의 해를 보장할 수 없다. >> 정당성 분석이 중요!
  • 그러나 코테 문제에서는 일반적으로 탐욕법으로 얻은 해가 최적의 해가 되는 상황에서 이론 추론해야 풀리도록 출제
  • 대표적인 그리디 알고리즘 문제 - 거스름돈 문제

 

📄 <문제1> 1이 될 때까지: 문제 설명

어떠한 수 N이 1이 될 때까지 다음의 두 과정 중 하나를 반복적으로 선택하여 수행하려고 함.

단, 두 번째 연산은 N이 K로 나누어 떨어질 때만 선택할 수 있음.

1. N에서 1을 뺀다.

2. N을 K로 나눈다.

ex) N이 17, K가 4라고 가정. 이때 1번의 과정을 한 번 수행하면 N은 16이 된다. 이후에 2번의 과정을 두 번 수행하면 N은 1이 된다. 결과적으로 전체 과정을 실행한 횟수는 3 이 된다. 

N과 K가 주어질 때 N이 될 때 까지 1번 혹은 2번의 과정을 수행해야 하는 최소 횟수를 구하는 프로그램 작성

# N, K을 공백을 기준으로 구부낳여 입력 받기
N, K = map(int, input().split())

result = 0

while True:
	# N이 K로 나누어 떨어지는 수가 될 때까지 빼기
    target = (N // K) * K
    result += (n - target)
    
    n = target
    # N이 K보다 작을 때(더 이상 K로 나눌 수 없을 때) 반복문 탈출
    if N < K:
    	break
        
    # K로 나누기
    result += 1
    N //= K
# 마지막으로 남은 수에 대하여 1씩 빼기
result += (N -1)
print(result)

 

 

📄 <문제2> 곱하기 혹은 더하기: 문제 설명

각 자리가 숫자(0부터 9)로만 이루어진 문자열 S가 주어졌을 때, 왼쪽부터 오른쪽으로 하나씩 모든 숫자를 확인하며 숫자 사이에 'x' 혹은 '+' 연산자를 넣어 결과적으로 만들어질 수 있는 가장 큰 수를 구하는 프로그램 작성

단, +보다 x를 먼저 계산하는 일반적인 방식과는 달리, 모든 연산은 왼쪽에서부터 순서대로 이루어진다고 가정

ex) 02984 라는 문자열로 만들 수 있는 가장 큰 수는 ((((0+2) * 9) * 8) * 4) = 576입니다. 또한 만들어질 수 있는 가장 큰 수는 항상 20억 이하의 정수가 되도록 입력이 주어진다.

 

  • 대부분의 경우 '+' 보다는 'x'가 더 값을 크게 만듬.
  • 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다 더하기를 수행하는 것이 효율적
  • 따라서 두 수에 대하여 연산을 진행할 때, 두 수 중에서 하나라도 1 이하인 경우에는 더하며, 두 수가 모두 2 이상인 경우에는 곱하면 정답
strings = list(map(int, input().strip()))

result = 0

for s in strings:
    if s <= 1 or result <= 1:
        result += s
    else:
        result *= s
print(result)

 

 

📄 <문제3> 모험가 길드: 문제설명

한 마을에 모험가가 N명이 있다. 모험가 길드에서는 N명의 모험가를 대상으로 '공포도'를 측정했는데, '공포도'가 높은 모험가는 쉽게 공포를 느껴 위험 상황에서 제대로 대처할 능력이 떨어진다.

모험가 길드장인 00이는 모험가 그룹을 안전하게 구성하고자 공포도가 X인 모험가는 반드시 X명 이상으로 구성한 모험가 그룹에 참여해야 여행을 떠날 수 있도록 규정했다.

  • 풀이 방법
    1. 공포도 오름차순 정렬
    2. 앞에서부터 공포도를 하나씩 확인하며 '현재 그룹에 포함된 모험가의 수'가 '현재 확인하고 있는 공포도' 보다 크거나 같다면 이를 그룹으로 설정하면 된다.
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)
728x90

단속카메라

문제 설명

고속도로를 이동하는 모든 차량이 고속도로를 이용하면서 단속용 카메라를 한 번은 만나도록 카메라를 설치하려고 합니다.

고속도로를 이동하는 차량의 경로 routes가 매개변수로 주어질 때, 모든 차량이 한 번은 단속용 카메라를 만나도록 하려면 최소 몇 대의 카메라를 설치해야 하는지를 return 하도록 solution 함수를 완성하세요.

제한 사항

  • 차량의 대수는 1대 이상 10,000대 이하입니다.
  • routes에는 차량의 이동 경로가 포함되어 있으며 routes[i][0]에는 i번째 차량이 고속도로에 진입한 지점, routes[i][1]에는 i번째 차량이 고속도로에서 나간 지점이 적혀 있습니다.
  • 차량의 진입/진출 지점에 카메라가 설치되어 있어도 카메라를 만난것으로 간주합니다.
  • 차량의 진입 지점, 진출 지점은 -30,000 이상 30,000 이하입니다.

입출력 예

-5 지점에 카메라를 설치하면 두 번째, 네 번째 차량이 카메라를 만납니다.
-15 지점에 카메라를 설치하면 첫 번째, 세 번째 차량이 카메라를 만납니다.

 

풀이 코드

def solution(routes):
    answer = 0
    routes.sort(key=lambda x: x[0])
    camera = -30001

    for s, e in routes:
        print(s, e, camera, answer)
        if s > camera:
            camera = e
            answer += 1
        camera = min(camera, e)

    return answer

 

 

프로그래머스

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

programmers.co.kr

 

 

728x90

구명보트

문제 설명

무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다.

예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.

구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.

사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
  • 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.

 

입출력 예

 

코드

from collections import deque

def solution(people, limit):
    answer = 0
    
    # 보트에 한번에 2명만 가능
    # limit 보트 무게 제한
    
    people.sort(key=lambda x: -x)
    people = deque(people)
    
    while len(people) > 0:
        if len(people) > 1 and people[-1] + people[0] <= limit:
            people.popleft()
            people.pop()
            answer += 1
        else:
            people.popleft()
            answer += 1
        
    return answer
728x90

조이스틱

문제 설명

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다.
ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다.

▲ - 다음 알파벳
▼ - 이전 알파벳 (A에서 아래쪽으로 이동하면 Z로)
◀ - 커서를 왼쪽으로 이동 (첫 번째 위치에서 왼쪽으로 이동하면 마지막 문자에 커서)
▶ - 커서를 오른쪽으로 이동 (마지막 위치에서 오른쪽으로 이동하면 첫 번째 문자에 커서)

 

예를 들어 아래의 방법으로 "JAZ"를 만들 수 있습니다.

- 첫 번째 위치에서 조이스틱을 위로 9번 조작하여 J를 완성합니다.
- 조이스틱을 왼쪽으로 1번 조작하여 커서를 마지막 문자 위치로 이동시킵니다.
- 마지막 위치에서 조이스틱을 아래로 1번 조작하여 Z를 완성합니다.
따라서 11번 이동시켜 "JAZ"를 만들 수 있고, 이때가 최소 이동입니다.

 

만들고자 하는 이름 name이 매개변수로 주어질 때, 이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.

 

제한 사항

  • name은 알파벳 대문자로만 이루어져 있습니다.
  • name의 길이는 1 이상 20 이하입니다.

입출력 예시

 

코드

# 조이스틱
def solution(name):
    A = 65
    Z = 90
    answer = 0
    n = len(name)
    
    # 각 문자에 대해 위아래 조작 횟수 계산
    for char in name:
        answer += min(ord(char) - A, Z - ord(char) + 1)
    
    # 좌우 이동 최소값 계산
    move = n - 1
    for i in range(n):
        next = i + 1
        while next < n and name[next] == 'A':
            next += 1
        move = min([move, 2 * i + n - next, i + 2 * (n - next)])
    
    return answer + move

 

 

 

 

https://school.programmers.co.kr/learn/courses/30/lessons/42860?language=python3

 

프로그래머스

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

programmers.co.kr

 

728x90

+ Recent posts