Algorithm Test

[Python] 프로그래머스 고득점 Kit 전체 문제 풀이

TNLEE 2020. 10. 22. 13:16

문제 풀러 가기 : programmers.co.kr/learn/challenges?tab=algorithm_practice_kit

 

코딩테스트 연습

기초부터 차근차근, 직접 코드를 작성해 보세요.

programmers.co.kr

각각의 풀이에 대한 설명은 이후에 정리 할 예정.

문제가 갱신된 것들이 있어서 10/21 부터 22일까지 전체 문제를 다시 풀어보았습니다.

(필요하신 분들은 ctrl+f로 검색해서 보시면 됩니다.)

 

해시

 

1. 완주하지 못한 선수
from collections import defaultdict
def solution(participant, completion):
    d = defaultdict(int)
    for p in participant:
        d[p] += 1
    for c in completion:
        d[c] -= 1
        if d[c] == 0:
            d.pop(c)
    return "".join(d.keys())

 

2. 전화번호 목록
def solution(phone_book):
    len_number = [[] for _ in range(21)]
    answer = True
    for number in phone_book:
        len_number[len(number)].append(number) 
    for i in range(1,21):
        for str1 in len_number[i]:
            for j in range(i+1,21):
                for str2 in len_number[j]:
                    if str1 == str2[:i]:
                        return False
    return True

 

3. 위장
def solution(clothes):
    d = dict()
    for name,item in clothes:
        d[item] = d.get(item,0) + 1
    
    answer = 1
    for item,n in d.items():
        answer *= (n+1)
    return answer-1

 

4. 베스트 앨범
from collections import defaultdict
def solution(genres, plays):
    genre_play = defaultdict(int)
    song_play = defaultdict(list)
    
    for i in range(len(genres)):
        genre_play[genres[i]] += plays[i]
        song_play[genres[i]].append((i,plays[i]))
    
    genre_lst = sorted(genre_play.items(),key=lambda x:x[1],reverse=True)
    answer = []
    for genre,_ in genre_lst:
        musics = sorted(song_play[genre],key=lambda x:x[1],reverse=True)[:2]
        for idx,nplay in musics:
            answer.append(idx)
    return answer

 

스택/큐

 

1. 주식가격
def solution(prices):
    answer = [len(prices)-i-1 for i in range(len(prices))]
    for i in range(len(prices)):
        for j in range(i+1,len(prices)):
            if prices[i] > prices[j]:
                answer[i] = j-i
                break
    return answer

 

2. 기능개발
def solution(progresses, speeds):
    stack = []
    d = dict()
    for i in range(len(progresses)):
        cost = (100 - progresses[i])//speeds[i]
        if (100-progresses[i]) % speeds[i] > 0:
            cost += 1
        if len(stack) == 0 or cost > stack[-1]:
            stack.append(cost)
            d[cost] = 1
        else:
            d[stack[-1]] += 1
 
    return [v for k,v in sorted(d.items())]

 

3. 다리를 지나는 트럭
from collections import deque
def solution(bridge_length, weight, truck_weights):
    trucks = deque(truck_weights)
    wait = deque()
    sum_weight = 0
    time = 0
    while trucks:
        time += 1
        while wait and wait[0][0] <= time:
            t,w = wait.popleft()
            sum_weight -= w
        if sum_weight+trucks[0] <= weight:
            truck = trucks.popleft()
            wait.append((bridge_length+time,truck))
            sum_weight += truck
    return wait[-1][0]

 

4. 프린터
from collections import deque
def solution(priorities, location):
    d = [0]*11
    queue = deque()
    for i,p in enumerate(priorities):
        d[p] += 1
        queue.append((i,p))
    
    idx = 0
    while True:
        i,j = queue.popleft()
        if sum(d[j+1:])>0:
            queue.append((i,j))
        elif i == location:
            return idx+1
        else:
            idx += 1
            d[j] -= 1

 

힙(HEAP)

 

1. 더 맵게
import heapq
def solution(scoville, K):
    answer = 0
    scoville.sort()
    while scoville[0] < K:
        food1 = heapq.heappop(scoville)
        if scoville:
            food2 = heapq.heappop(scoville)
        else:
            return -1
        heapq.heappush(scoville,food1+food2*2)
        answer += 1
    return answer

 

2. 디스크컨트롤러
def solution(jobs):
    wait = 0
    curr = 0
    jobs.sort(key=lambda x:x[1])
    visited = set()
    while len(visited) < len(jobs):
        chk = True
        for i in range(len(jobs)):
            if i in visited:
                continue
            if jobs[i][0] <= curr:
                curr += jobs[i][1]
                wait += curr - jobs[i][0]
                visited.add(i)
                chk = False
                break
        if chk:
            curr += 1
    return wait // len(jobs)

 

3. 이중우선순위큐
import heapq
def solution(operations):
    minq = []
    maxq = []
    removed = set()
    for oper in operations:
        op,digit = oper.split(" ")
        digit = int(digit)
        if op == "I":
            heapq.heappush(minq,digit)
            heapq.heappush(maxq,-digit)
        elif digit == -1 and minq:
            temp = heapq.heappop(minq)
            while temp in removed and minq:
                temp = heapq.heappop(minq)
            removed.add(temp)
        elif digit == 1 and maxq:
            temp = -heapq.heappop(maxq)
            while temp in removed and maxq:
                temp = -heapq.heappop(maxq)
            removed.add(temp)
    
    maxval = 0
    minval = 0
    while maxq:
        temp = -heapq.heappop(maxq)
        if temp not in removed:
            maxval = temp
            break
    
    while minq:
        temp = heapq.heappop(minq)
        if temp not in removed:
            minval = temp
            break
            
    return [maxval,minval]

 

정렬

 

1. K번째 수
def solution(array, commands):
    answer = []
    for i,j,k in commands:
        answer.append(sorted(array[i-1:j])[k-1])
    return answer

 

2. 가장 큰 수
def solution(numbers):
    numbers.sort(key=lambda x: str(x)*3, reverse=True)
    if numbers[0] == 0:
        return "0"
    else:
        return "".join(map(str,numbers))

 

3. H-Index
def solution(citations):
    citations.sort()
    n = len(citations)
    for h in range(n):
        if citations[h] >= n-h: ## n-h보다 크거나 같은 n-h개, h보다 작거나 같은 h개의 논문들
            return n-h
    return 0

 

완전탐색

 

1. 모의고사
def solution(answers):
    first = [1,2,3,4,5]
    second = [2,1,2,3,2,4,2,5]
    third = [3,3,1,1,2,2,4,4,5,5]
    ret = [0,0,0]
    for i in range(len(answers)):
        if answers[i] == first[i%5]:
            ret[0] += 1
        if answers[i] == second[i%8]:
            ret[1] += 1
        if answers[i] == third[i%10]:
            ret[2] += 1
    maxval = max(ret)
    answer = []
    for i in range(len(ret)):
        if ret[i] == maxval:
            answer.append(i+1)
    return answer

 

2. 소수 찾기
from itertools import permutations
def prime_check(x):
    if x<2:
        return 0
    for i in range(2,int(x**0.5)+1):
        if x % i == 0:
            return 0
    return 1
    
def solution(numbers):
    numbers = list(numbers)
    cand = set()
    for i in range(1,len(numbers)+1):
        for string in permutations(numbers,i):
            cand.add(int(''.join(string)))
            
    answer = 0
    for x in list(cand):
        answer += prime_check(x)
    return answer

 

3. 카펫
def solution(brown, yellow):
    n = brown + yellow
    for i in range(1,(n+1)//2):
        if n % i ==0:
            j = n // i
            if i*2+j*2-4 == brown: ##가로둘레*2 + 세로둘레*2 - 4(외곽 네모칸 4개 중복 되므로 4로 빼줌)
                return [j,i]
    return False

 

탐욕법(GREEDY)

 

1. 체육복
def solution(n, lost, reserve):
    reallost = set(lost) - set(reserve)
    realres = set(reserve) - set(lost)
    for r in sorted(list(realres)):
        if r-1 in reallost:
            reallost.remove(r-1)
        elif r+1 in reallost:
            reallost.remove(r+1)
    return n - len(reallost)

 

2. 큰 수 만들기
def solution(number, k):
    answer = []
    for i in range(len(number)):
        while answer and k>0 and number[i] > answer[-1]:
            answer.pop()
            k -= 1
        answer.append(number[i])
    return ''.join(answer[:len(answer)-k])

 

3. 조이스틱
def dfs(goal,idx,ans,finish):
    global minval
    if finish == 0:
        minval = min(ans,minval)
    else:
        for i in range(len(goal)):
            if goal[i]:
                temp = goal[i]
                goal[i] = 0
                ## 좌우이동 cost + 위아래이동 cost
                dfs(goal,i,ans+min(abs(idx-i),abs(len(goal)+idx-i))+temp,finish-temp)
                goal[i] = temp
 
def solution(name):
    global minval
    goal = []
    for x in list(map(ord, name)):
        goal.append(min(abs(65 - x), abs(91 - x)))
    minval = 1e9
    dfs(goal,0,0,sum(goal))
    return minval

 

4. 구명보트
def solution(people, limit):
    people.sort()
    p1 = 0
    p2 = len(people)-1
    couple = 0
    while p1<p2:
        if people[p1] + people[p2] <= limit:
            p1 += 1
            couple += 1
        p2 -= 1
    return len(people) - couple

 

5. 섬 연결하기
def find_parent(parent,x):
    if parent[x] == x:
        return x
    else:
        return find_parent(parent,parent[x])
 
def solution(n, costs):
    edges = sorted([(c,a,b) for a,b,c in costs])
    parent = [x for x in range(n)]
    answer = 0
    bridge = 0
    for c,a,b in edges:
        a = find_parent(parent,a)
        b = find_parent(parent,b)
        if a != b:
            if a<b:
                parent[b] = a
            else:
                parent[a] = b
            answer += c
    return answer if sum(parent) == 0 else -1

 

6. 단속카메라
def solution(routes):
    routes.sort(key=lambda x:x[1])
    last_camera = -30000
    answer = 0
    for s,e in routes:
        if last_camera < s:
            last_camera = e
            answer += 1
    return answer

 

동적 프로그래밍(Dynamic Programming)

 

1. N으로 표현
def solution(N, number):
    if N == number:
        return 1
 
    memo = [set() for _ in range(9)]
    for i in range(1,len(memo)):
        memo[i].add(N*int(str(1)*i))
 
    for i in range(2, 9):
        for j in range(1, i):
            temp = list(memo[j])
            for k in range(1,i):
                if j+k != i:
                    continue
                temp2= list(memo[k])
                for x in temp:
                    for y in temp2:
                        memo[i].add(x + y)
                        memo[i].add(x * y)
                        memo[i].add(x - y)
                        if y != 0:
                            memo[i].add(x // y)
        if number in memo[i]:
            return i
    return -1

 

2. 정수삼각형
def solution(triangle):
    for i in range(1,len(triangle)):
        for j in range(i+1):
            left = triangle[i-1][j-1] if j!=0 else 0
            right = triangle[i-1][j] if j!=i else 0
            triangle[i][j] = triangle[i][j] + max(left,right)
    return max(triangle[-1])

 

3. 등굣길
def solution(m, n, puddles):
    board = [[0]*(m+1) for _ in range(n+1)]
    for x,y in puddles:
        board[y][x] = -1
    
    board[1][1] = 1
    for x in range(1,n+1):
        for y in range(1,m+1):
            if x==1 and y==1:
                continue
            if board[x][y] != -1:
                board[x][y] = max(0,board[x-1][y]) + max(0,board[x][y-1])
                
    return board[n][m]%1000000007

 

4. 도둑질
def solution(money):
    a = [money[0],money[0]]
    b = [0,money[1]]
    for i in range(2,len(money)-1):
        a.append(max(a[i-2]+money[i],a[i-1]))
        b.append(max(b[i-2]+money[i],b[i-1]))
    answer = max(a[-1],b[-2]+money[-1])
    return answer

 

깊이/너비 우선탐색(DFS/BFS)

 

1. 타겟넘버
def dfs(idx,ans):
    global answer,nb,tg
    if idx == len(nb):
        if ans==tg:
            answer += 1
        return
    else:
        dfs(idx+1,ans+nb[idx])
        dfs(idx+1,ans-nb[idx])
        return
    
def solution(numbers, target):
    global answer,nb,tg
    nb = numbers
    tg = target
    answer = 0
    dfs(0,0)
    return answer

 

2. 네트워크
def solution(n, computers):
    parent = [x for x in range(n)]
    for i in range(n): ## start
        for j in range(n): ## end
            if i == j:
                continue
            if computers[i][j]: ##edge
                for k in range(n):
                    if parent[k] == parent[i]: ##start -> end update
                        parent[k] = parent[j]
    return len(set(parent))

 

3. 단어 변환
def WordDist(w1,w2):
    dist = 0
    for i in range(len(w1)):
        if w1[i] != w2[i]:
            dist += 1
            if dist>1:
                return False
    return True if dist == 1 else False
 
def dfs(begin,target,words,count,visited):
    global minval
    if begin == target:
        minval = min(minval,count)
    else:
        for i in range(len(words)):
            if i in visited:
                continue
            if WordDist(begin,words[i]):
                visited.add(i)
                dfs(words[i],target,words,count+1,visited)
                visited.remove(i)
 
def solution(begin, target, words):
    global minval
    minval = 51
    dfs(begin,target,words,0,set())
    return minval if minval<51 else 0

 

4. 여행경로
from collections import defaultdict
def solution(tickets):
    route = defaultdict(list)
    for s,a in tickets:
        route[s].append(a)
    for k in route.keys():
        route[k].sort(reverse=True)
    
    ## dfs using stack
    stack = ["ICN"]
    visit = []
    while stack:
        top = stack[-1]
        if route[top]: ##갈 수 있는 곳이 있다면(빈 리스트가 아니라면)
            stack.append(route[top].pop())
        else: ##없다면 가장 마지막 노드
            visit.append(stack.pop())
    return visit[::-1]

 

이분탐색

 

1. 입국심사
def check(t,times):
    ret = 0
    for time in times:
        ret += t//time
    return ret
    
def solution(n, times):
    answer = 0
    left = 0
    right = max(times)*n ##가장 오래걸리는 사람이 모두 처리하는 상황
    while left <= right:
        mid = (left+right)//2
        chk = check(mid,times)
        if chk < n:
            left = mid+1
        else: ##n명보다 많이 처리할 수 있다면(answer는 될 수 있지만, 더작은 것 찾기)
            answer = mid
            right = mid-1
    return answer

 

2. 징검다리
def check(term, rocks):
    count = 0
    start = 0
    minval = 1e9
    for i in range(len(rocks)):
        if rocks[i] - start<term: #start위치부터 못건널때까지 체크(지나가는 돌들 체크)
            count += 1
        else:
            minval = min(minval,rocks[i]-start)
            start = rocks[i]
    return count,minval
 
 
def solution(distance, rocks, n):
    answer = 0
    rocks.append(distance)
    rocks.sort()
 
    left = 0
    right = distance
    while left <= right:
        mid = (left + right) // 2
        count,minval = check(mid, rocks)
        if count > n:
            right = mid - 1
        else:
            answer = minval
            left = mid + 1
    return answer

 

그래프

 

1. 가장 먼 노드
def solution(n, edge):
    graph = [set() for _ in range(n + 1)]
    for s, e in edge:
        graph[s].add(e)
        graph[e].add(s)
 
    queue = set([1])
    visited = set([1])
 
    while len(visited) < n:
        next_queue = set()
 
        while queue:
            node = queue.pop()
            next_queue |= graph[node]
 
        queue = next_queue - visited
        visited |= queue
 
    return len(queue)

 

2. 순위
import copy
def solution(n, results):
    linked = [[set(),set()] for _ in range(n+1)]
    for w,l in results:
        linked[w][1].add(l)
        linked[l][0].add(w)
    
    answer = 0
    for i in range(1,n+1):
        front,back = copy.deepcopy(linked[i])
        visited = set()
        
        while front:
            linked[i][0] |= front
            visited |= front
            next_front = set()
            for _ in range(len(front)):
                next_front |= linked[front.pop()][0]
            front |= (next_front - visited)
        
        while back:
            linked[i][1] |= back
            visited |= back
            next_back = set()
            for _ in range(len(back)):
                next_back |= linked[back.pop()][1]
            back |= (next_back - visited)
        
        if len(linked[i][0]) + len(linked[i][1]) == n-1:
            answer += 1
    return answer

 

3. 방의 개수
from collections import defaultdict
def solution(arrows):
    dx = [-1,-1,0,1,1,1,0,-1]
    dy = [0,1,1,1,0,-1,-1,-1]
    x,y = 0,0
    answer = 0
    visited = set([(0,0)])
    edges = defaultdict(int)
    for d in arrows:
        for _ in range(2):
            nx,ny = x+dx[d], y+dy[d]
            if (nx,ny) in visited and edges[(x,y,nx,ny)] == 0:
                answer += 1
            edges[(x,y,nx,ny)] += 1
            edges[(nx,ny,x,y)] += 1
            visited.add((nx,ny))
            x,y = nx,ny
    return answer