출처: Better Programming


 

1. 같은 숫자는 싫어 (Lv. 1)

https://school.programmers.co.kr/learn/courses/30/lessons/12906

# 이해
# 스택에 연속된 숫자가 저장되면 안 됨.

# 풀이
# arr을 탐색하며 stack에 추가
# 추가하기 전, stack의 top과 같은 경우 pass, 다른 경우 push

def solution(arr):
    stack = []
    
    for elem in arr:
        if stack:
            if elem != stack[-1]:
                stack.append(elem)
        else:
            stack.append(elem)
    
    return stack

 

 

 

기능개발 (Lv. 2)

https://school.programmers.co.kr/learn/courses/30/lessons/42586

# 이해
# progresses의 원소는 100%를 달성하면 배포된다.
# 매일 speeds의 원소만큼 progress가 진행된다.
# 가장 앞에 있는 원소가 100%를 달성한 순간에, 100%를 달성한 모든 원소를 배포한다.

# 풀이
# progresses의 각 원소를 100에서 빼고, 그 값을 speeds로 나누어 남은 일자를 계산한다. remain_days: [Int]
# remain_days를 탐색하며, 내림차순으로 정렬된 경우 tmp에 더하고, 
    # 내림차순이 깨진 순간 tmp를 answer에 append하고, tmp를 초기화 한다.
# answer를 return한다.

import math

def solution(progresses, speeds):
    answer = []
    remain_days = [math.ceil((100 - progress) / speed) for progress, speed in zip(progresses, speeds)]
    
    current_max_day = remain_days[0]
    count = 0
    
    for day in remain_days:
        if day <= current_max_day:
            count += 1
        else:
            answer.append(count)
            current_max_day = day
            count = 1
    
    answer.append(count)
    
    return answer

 

`zip()` 함수는 여러 개의 iterators를 인자로 받아, 인덱스를 기준으로 짝 지은 튜플을 반환하는 함수이다.

위 코드에서 math.ceil()는 필수적이지 않다. `-((progress - 100) // speed)`의 형태로 작성해도 같은 결과이다.

 

 

 

3. 올바른 괄호 (Lv. 2)

https://school.programmers.co.kr/learn/courses/30/lessons/12909

나의 풀이

# 이해
# 괄호가 올바르게 짝지어지면 True
# 하나라도 틀리면 False

# 풀이
# "("인 경우
    # stack이 비었으면 추가한다.
    # stack에 원소가 있다면, stack의 top이 "("이라면 추가. ")"이라면 return False
# ")"인 경우
    # stack이 비었으면 return False
    # stack에 원소가 있다면, stack의 top이 "("이라면 stack.pop(), ")"이라면 return False

def solution(brackets):
    stack = []
    
    for bracket in brackets:
        if bracket == "(":
            if not stack:
                stack.append(bracket)
            else:
                if stack[-1] == "(":
                    stack.append(bracket)
                else:
                    return False
        
        else: # bracket == ")"
            if not stack:
                return False
            else:
                if stack[-1] == "(":
                    stack.pop()
                else:
                    return False
                
    return True if not stack else False

 

더 쉬운 풀이

def is_pair(s):
    wt = 0
    
    for c in s :
        if c == '(' :
            wt += 1
        elif c == ')':
            wt -= 1
        
        if wt < 0: 
            return False
        
    return wt == 0

 

스택에 성질을 활용하면 `나의 풀이`처럼 모든 케이스를 대응할 필요가 없다.

 

 

 

4. 프로세스 (Lv. 2)

https://school.programmers.co.kr/learn/courses/30/lessons/42587

나의 풀이

# 이해
# priorities 배열을 우선순위에 따라 pop() 할 때, 
# location 위치에 있는 원소가 몇 번째로 pop() 되는지 return

# 풀이
# max_value = max(priorities)
# priorities_with_hash = [[i, hash(i)] for i in priorities]
# max_value_hash = priorities_with_hash[location][1]
# order = 0
# while len(priorities_with_hash) >= 0:
    # current = popleft()
    # current[0] >= max_value, 
        # if current[1] == max_value_hash:
            # return order
        # order += 1
    # current[0] < max_value:
        # priorities_with_hash.append(current)

from collections import deque
import random

def solution(priorities, location):
    order = 1
    priorities_with_hash = deque([[priorities[i], i] for i in range(len(priorities))])
    max_value = max(priorities)
    target_hash = priorities_with_hash[location][1]
    
    while len(priorities_with_hash) >= 0:
        current = priorities_with_hash.popleft()
        
        if current[0] >= max_value: 
            if current[1] == target_hash:
                return order
            max_value = max([elem[0] for elem in priorities_with_hash])
            order += 1
            
        else: # current[0] < max_value
            priorities_with_hash.append(current)
            
    return order

 

더 나은 풀이

def solution(priorities, location):
    queue =  [(i,p) for i,p in enumerate(priorities)]
    answer = 0
    while True:
        cur = queue.pop(0)
        if any(cur[1] < q[1] for q in queue):
            queue.append(cur)
        else:
            answer += 1
            if cur[0] == location:
                return answer

 

`any()`: 인자로 받은 iterators 중에 하나라도 True이면, 전체를 True로 반환한다.

 

 

 

5. 다리를 지나는 트럭 (Lv. 2)

https://school.programmers.co.kr/learn/courses/30/lessons/42583

# 이해
# bridge_length는 다리에 올라갈 수 있는 트럭 수. 동시에 트럭이 이동해야 하는 길이.
# weight는 다리가 버틸 수 있는 무게. 트럭의 개수가 bridge_length보다 적어도, 무게 기준을 만족해야 한다.
# 모든 트럭이 다리를 건너는 데까지 걸리는 시간을 return

# 풀이
# 정석적인 원형 큐로 풀이해보자
# bridge = deque([])
# bridge.append(truck_weights[0])
# bridge_sum += truck_weights[0]
# time = 0

# while True:
    # time += 1
    # out_truck = bridge.popleft()
    # bridge_sum -= out_truck
    # if out_truckt > 0 and len(truck_weights) == 0:
        # return time
    
    # if bridge_sum + truck_weights[0] < weight:
        # in_truck = truck_weights.popleft()
        # bridge.append(in_truck)
        # bridge_sum += in_truck
        
    # else:
        # bridge.append(out_truck)

from collections import deque
        
def solution(bridge_length, weight, truck_weights):
    
    bridge = deque([0] * bridge_length)
    truck_weights = deque(truck_weights)
    bridge_sum = 0
    time = 0

    while truck_weights or bridge_sum > 0:
        time += 1
        out_truck = bridge.popleft()
        bridge_sum -= out_truck

        if truck_weights and bridge_sum + truck_weights[0] <= weight:
            in_truck = truck_weights.popleft()
            bridge.append(in_truck)
            bridge_sum += in_truck
        else:
            bridge.append(0)
    
    return time

 

`if truck_weights and bridge_sum + truck_weights[0] <= weight:` 이러한 방식이 좋다.

반복할 때마다 판단해야 하는 조건이 있다면, if이든 while이든 조건문에 포함시키자.

 

 

 

6. 주식가격(Lv. 2)

https://school.programmers.co.kr/learn/courses/30/lessons/42584

나의 풀이 (큐)

from collections import deque

def solution(prices):
    queue = deque(prices)
    answer = []
    
    while queue:
        price = queue.popleft()
        sec = 0
        for q in queue:
            sec += 1
            if price > q:
                break 
        answer.append(sec)        
    return answer

 

복잡할 것이 없는 풀이이다.


그러나 30분 동안 고민했다.

주어진 배열의 길이가 10 ** 5이어서, O(N ** 2)은 시간 초과가 발생할 수 있다고 판단했기 때문이다.

실제로는 시간 초과가 발생하지 않았다.

계속해서 queue의 크기를 줄여나가기  때문인 듯하다.

 

실제로 코테에서도 웬만한 크기(10 ** 4 ~ 10 ** 5)라면 일단 완전탐색으로 풀이하자.

그렇게 부분 점수 먼저 확보해 놓고, 시간복잡도를 개선하는 것이 훨씬 현실적인 코테 접근법이다.

 

더 나은 풀이 (스택)

# 이해
# 배열의 각 원소가 오름차순이 지속되는 길이를 각각 return
# 다음 원소와 비교하여, 값이 작아지지 않을 때마다 += 1
# 일단 지속 시간을 1초 증가시키고, 그 뒤에 오름차순 여부를 판단한다.
# 마지막 원소는 0초이다.

# 풀이
# 일단 이중 반복문으로 풀자

from collections import deque

def solution(prices):
    length = len(prices)
    answer = [i for i in range(length - 1, -1, -1)]
    
    stack = [0]
    for i in range(1, length):
        while stack and prices[stack[-1]] > prices[i]:
            j = stack.pop()
            answer[j] = i - j
        stack.append(i)
    
    return answer

 

https://velog.io/@soo5717/프로그래머스-주식가격-Python

위 블로그 글을 참고한 풀이이다.

 

 

 

 

+ Recent posts