[프로그래머스 77486] 다단계 칫솔 판매 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Union-Find 알고리즘의 Find() 함수를 사용하여 부모 노드에 대해 재귀적으로 접근
  • 최악의 경우 O(NM)=10^10으로 시간 초과가 발생하지만, 매 탐색마다 최대 10,000원을 10씩 나눠 0이 되는 순간에 재귀가 종료되기 때문에 최대 깊이가 5로 좁혀짐

Time Complexity #

  • O(N) = 100,000

Data Size #

  • enroll, referral: str(10) * 10,000
  • seller: str(10) * 100,000
  • amount: int(100) * 100,000

해설 코드 #

python
def find(parents, cur, income, answer):
    alloc = income//10
    if parents[cur] == cur or alloc == 0:
        answer[cur] += income-alloc
        return
    answer[cur] += income-alloc
    find(parents, parents[cur], alloc, answer)
    return

def solution(enroll, referral, seller, amount):
    N = len(enroll)
    answer = [0] * N
    name2id = {name:i for i,name in enumerate(enroll)}
    parents = [i if referral[i]=='-' else name2id[referral[i]] for i in range(N)]
    for i in range(len(seller)):
        find(parents, name2id[seller[i]], amount[i]*100, answer)
    return answer

[프로그래머스 68936] 쿼드압축 후 개수 세기 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Divide and Conquer
  • 2차원 배열을 4등분씩 나눠 재귀함수를 호출하고 동일한 값으로 채워져 있는지 판단하여 값의 개수 증가
  • 2^n 형태의 정수에 대해 NumPy를 활용해 행렬 인덱싱을 간단히 구현

Time Complexity #

  • O(N^2 Log N^2) = 20,000,000

Data Size #

  • arr: [[int(1)]], shape(2^n, 2^n)
  • 1 <= 2^n <= 1024

해설 코드 #

python
import numpy as np

def quad_comp(n, arr, answer):
    values = np.unique(arr)
    if len(values) == 1:
        answer[values[0]] += 1
        return
    div = n//2
    quad_comp(div, arr[:div, :div], answer)
    quad_comp(div, arr[:div, div:], answer)
    quad_comp(div, arr[div:, :div], answer)
    quad_comp(div, arr[div:, div:], answer)

def solution(arr):
    arr = np.array(arr)
    answer = [0,0]
    quad_comp(len(arr), arr, answer)
    return answer

[프로그래머스 87390] n^2 배열 자르기 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Greedy
  • n의 크기가 굉장히 크기 때문에 2차원 배열을 만드는 것만으로 시간 초과가 발생할 것을 예상
  • r행 c열의 값은 max(r,c)+1과 같고 1차원 배열의 인덱스 i에 대해 r은 i//n, c는 i%n와 동일
  • left부터 right까지의 인덱스를 규칙에 맞는 값으로 변환하여 반환

Time Complexity #

  • O(N) = 10^5

Data Size #

  • n: 1 <= int <= 10^7
  • left, right: 0 <= long <= n^2
  • right - left < 10^5

해설 코드 #

python
def solution(n, left, right):
    return [max(divmod(i,n))+1 for i in range(left,right+1)]

[프로그래머스/카카오 17687] n진수 게임 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Math
  • 0부터 시작해 t*m의 길이를 만족하는 N진법 배열을 생성
  • 매 순서마다 p 위치에 해당하는 값을 추출해 문자열로 반환

Data Size #

  • n: 2 <= int <= 16
  • t: 0 < int <= 1,000
  • m: 2 <= int <= 100
  • p: 1 <= int <= m

해설 코드 #

python
alpha = {10:'A',11:'B',12:'C',13:'D',14:'E',15:'F'}

def n_base(num, base):
    result = str()
    while num > 0:
        num, mod = divmod(num, base)
        result += str(mod) if mod < 10 else alpha[mod]
    return result[::-1]

def solution(n, t, m, p):
    arr = '01'
    total = t*m
    p = p%m

    i = 2
    while len(arr) < total:
        arr += n_base(i, n)
        i += 1

    answer = [t for i,t in enumerate(arr[:total]) if (i+1)%m==p]
    return ''.join(answer)

[프로그래머스 43238] 입국심사 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Binary Search
  • answer에 대한 이진탐색 수행 (1 <= answer <= max(times)*n)
  • 매 탐색마다 answer 시간 동안 심사관들이 심사할 수 있는 사람의 수를 계산
  • 심사한 사람의 수가 n명 이상일 경우 최대 범위를 조정하고 재탐색
  • 심사한 사람의 수가 n명 미만일 경우 최소 범위를 조정하고 재탐색
  • n명 이상의 사람을 심사할 수 있는 가장 작은 answer를 반환

Time Complexity #

  • Binary Search: O(M Log N^N) = 6,000,000

Data Size #

  • n: 1 <= int <= 1,000,000,000
  • times: int(1,000,000,000) * 100,000

해설 코드 #

python
def solution(n, times):
    answer = 0
    start, end = 1, max(times)*n

    while start <= end:
        mid = (start+end)//2
        passed = 0
        for time in times:
            passed += mid // time
            if passed >= n:
                break
        if passed >= n:
            answer = mid
            end = mid-1
        elif passed < n:
            start = mid+1

    return answer

[프로그래머스 42895] N으로 표현 (Python)

문제 링크 #

문제 해설 #

Idea #

  • Dynamic Programming
  • S[1] = {N}
  • S[2] = {NN, N+N, N-N, N*N, N/N}
  • S[3] = {NNN, S[2][x] (+,-,*,/) S[1][y], …}
  • 2부터 8까지의 범위를 가진 i와 1부터 i-1까지의 범위를 가진 j에 대해,
    S[j]와 S[i-j]의 사칙연산 결과를 S[i]에 추가하고 해당 집합이 number를 포함하는지 검증

Time Complexity #

  • DP: O(1)

Data Size #

  • N: 1 <= int <= 9
  • number: 1 <= int <= 32,000
  • answer: int <= 8

해설 코드 #

python
from itertools import product

def solution(N, number):
    S = [set() for _ in range(9)]

    if N == number:
        return 1
    else:
        S[1].add(N)

    for i in range(2,9):
        S[i].add(int(str(N)*i))
        for j in range(1,i):
            for x,y in product(S[j],S[i-j]):
                S[i].update({x+y,x-y,x*y})
                if y != 0:
                    S[i].add(x//y)
        if number in S[i]:
            return i
    return -1

[프로그래머스/카카오 17686] 파일명 정렬 (Python)

문제 링크 #

문제 해설 #

Idea #

  • 정규표현식을 활용해 HEAD, NUMBER, TAIL을 분리
  • 전체 파일명을 완전탐색하면서 리스트에 분리된 파일명을 저장
  • HEAD와 NUMBER를 기준으로 파일명을 정렬하고 정렬된 원본 파일명을 반환

Time Complexity #

  • Brute-Force + Sort: O(NM+NlogN)) = 110000

Data Size #

  • files: str(100) * 1000

해설 코드 #

python
import re

def solution(files):
    answer = []

    for file in files:
        head, number, tail = re.findall('([^0-9]+)([0-9]+)(.*)', file)[0]
        answer.append((head.lower(), int(number), tail, file))
    answer.sort(key=lambda x: [x[0],x[1]])

    return [file for _,_,_,file in answer]

[프로그래머스/카카오 17684] 압축 (Python)

문제 링크 #

문제 해설 #

Idea #

  • LZW 알고리즘 (List로 구현)
  • 단어를 문자 단위로 탐색하면서 캐시에 추가
  • 캐시가 문자 사전에 없을 경우 이전 문자까지의 인덱스를 반환하고 캐시를 문자 사전에 추가

Time Complexity #

  • Brute-Force: O(N^2) = 1000000

Data Size #

  • msg: str(1000)

해설 코드 #

python
def solution(msg):
    answer = []
    chars = [chr(x) for x in range(64,91)]

    cache = str()
    for c in msg:
        cache += c
        if cache not in chars:
            answer.append(chars.index(cache[:-1]))
            chars.append(cache)
            cache = c
    answer.append(chars.index(cache))

    return answer

[프로그래머스/카카오 17683] 방금그곡 (Python)

문제 링크 #

문제 해설 #

Idea #

  • 악보 정보에서 #이 포함된 음을 소문자로 대체하고 완전탐색
  • 시간 계산은 timedelta 활용
  • (재생시간,제목)으로 구성된 리스트를 정렬

Time Complexity #

  • Brute-Force: O(NM) = 143,900

Data Size #

  • m: 1 <= int <= 1439
  • musicinfos: list <= 100
  • musicinfos[0,1]: HH:MM (00:00 - 23:59)
  • musicinfos[2]: str(64)
  • musicinfos[4]: 1 <= int <= 1439

해설 코드 #

python
import datetime as dt
import re
import math

def solution(m, musicinfos):
    answer = list()

    lower_repl = lambda match: match.group(1)[0].lower()
    sharp_repl = lambda s: re.sub('([A-G]#)', lower_repl, s)
    m = sharp_repl(m)
    strptime = lambda x: dt.timedelta(hours=int(x[0]),minutes=int(x[1]))

    for info in musicinfos:
        start, end, title, chord = info.split(',')
        plays = (strptime(end.split(':'))-strptime(start.split(':'))).seconds//60
        chord = sharp_repl(chord)
        chord = (chord * math.ceil(plays/len(chord)))[:plays]
        if m in chord:
            answer.append((plays,title))

    return sorted(answer, key=lambda x: x[0], reverse=True)[0][1] if len(answer) else '(None)'

[프로그래머스/카카오 17680] 캐시 (Python)

문제 링크 #

문제 풀이 #

Idea #

  • LRU 알고리즘 (Deque로 구현)
  • 도시이름이 캐시에 존재할 경우 시간에서 1 추가, 아닐 경우 5 추가
  • 캐시에서 참고한 도시는 deque 최상단으로 재배치
  • 캐시 사이즈를 초과할 경우 가장 오래된 도시를 제거

Time Complexity #

  • Deque: O(N) = 100,000

Data Size #

  • cacheSize: 0 <= int <= 30
  • cities: str(20) * 100,000

해설 코드 #

python
from collections import deque

def solution(cacheSize, cities):
    answer = 0
    cache = deque(maxlen=cacheSize)

    for city in cities:
        city = city.lower()
        if city in cache:
            answer += 1
            cache.remove(city)
            cache.append(city)
        else:
            answer += 5
            cache.append(city)
    return answer