220209 - 풍선 터트리기

이상해씨·2022년 2월 9일
0

알고리즘 풀이

목록 보기
44/94

◾ 풍선 터트리기 : 프로그래머스 LEVEL 3

문제

일렬로 나열된 n개의 풍선이 있습니다. 모든 풍선에는 서로 다른 숫자가 써져 있습니다. 당신은 다음 과정을 반복하면서 풍선들을 단 1개만 남을 때까지 계속 터트리려고 합니다.

  1. 임의의 인접한 두 풍선을 고른 뒤, 두 풍선 중 하나를 터트립니다.
  2. 터진 풍선으로 인해 풍선들 사이에 빈 공간이 생겼다면, 빈 공간이 없도록 풍선들을 중앙으로 밀착시킵니다.

여기서 조건이 있습니다. 인접한 두 풍선 중에서 번호가 더 작은 풍선을 터트리는 행위는 최대 1번만 할 수 있습니다. 즉, 어떤 시점에서 인접한 두 풍선 중 번호가 더 작은 풍선을 터트렸다면, 그 이후에는 인접한 두 풍선을 고른 뒤 번호가 더 큰 풍선만을 터트릴 수 있습니다.

당신은 어떤 풍선이 최후까지 남을 수 있는지 알아보고 싶습니다. 위에 서술된 조건대로 풍선을 터트리다 보면, 어떤 풍선은 최후까지 남을 수도 있지만, 어떤 풍선은 무슨 수를 쓰더라도 마지막까지 남기는 것이 불가능할 수도 있습니다.

일렬로 나열된 풍선들의 번호가 담긴 배열 a가 주어집니다. 위에 서술된 규칙대로 풍선들을 1개만 남을 때까지 터트렸을 때 최후까지 남기는 것이 가능한 풍선들의 개수를 return 하도록 solution 함수를 완성해주세요.


입력

  • a의 길이는 1 이상 1,000,000 이하입니다.
    • a[i]는 i+1 번째 풍선에 써진 숫자를 의미합니다.
    • a의 모든 수는 -1,000,000,000 이상 1,000,000,000 이하인 정수입니다.
    • a의 모든 수는 서로 다릅니다.

출력

  • 최후까지 남기는 것이 가능한 풍선들의 개수

입출력 예

aresult
[9,-1,-5]3
[-16,27,65,-2,58,-92,-71,-68,-61,-33]6

◾ 풀이

1. 해설

직접 푼 방식

  • 각 값에 대해 왼쪽, 오른쪽 범위에 대해 검사하며 탐색
    • 왼쪽, 오른쪽 범위의 최소값이 해당 값보다 작으면 해당 값은 최후에 남을 수 없다.
    • 가장 왼쪽값, 가장 오른쪽 값은 무조건 최후에 남을 수 있다.
    • 왼쪽 범위 최소값 : for을 통해 진행할 때마다 현재의 최소값과 현재 검사 중인 값을 확인하고 최소값 선택
    • 오른쪽 범위 최소값 : heap을 통해 최소값 결정
      • (값, 인덱스) 형태로 추가하여 인덱스가 현재 단계의 인덱스 이하인 경우 삭제
  • 구성 및 삭제 등에 많은 연산이 이루어져 상대적으로 오래 걸린다.

다른 사람이 푼 방식

  • 최소값을 찾고 왼쪽, 오른쪽 범위에 대해 검사하며 탐색
    • 직접 푼 방식과 비슷하지만 최소값을 기준으로 진행하기 때문에 왼쪽 또는 오른쪽 한 쪽 범위의 최소값은 변하지 않고 고정된다.
  • 구성 및 삭제 과정이 따로 없으므로 빠른 시간안에 해결할 수 있다.

2. 프로그램

  1. answer 초기화
    • a의 길이가 2개 이하인 경우 : a의 길이
    • a의 길이가 2개 초과인 경우 : 2(가장 왼쪽 값, 가장 오른쪽 값)
  2. a의 각 요소에 대해 차례로 검사하며 진행
    • 왼쪽 범위 최소값 : 현재 최소값과 현재 값을 비교하여 선택
    • 오른쪽 범위 최소값 : heap
  3. 왼쪽 범위 최소값 또는 오른쪽 범위 최소값 중 현재값보다 클 경우 answer + 1
# 코드
import heapq
def solution(a):
    answer = 0
    a_size = len(a)
    if a_size <= 2 :
        answer = a_size
    else:
        answer = 2
        left_min = a[0]
        right_min = []
        for i in range(2, a_size):
            heapq.heappush(right_min, (a[i], i))
        for i in range(1, a_size - 1):
            while i >= right_min[0][1]:
                heapq.heappop(right_min)
            if left_min >= a[i] or right_min[0][0] >= a[i]:
                answer += 1
                if left_min > a[i]:
                    left_min = a[i]
    return answer
  1. answer, M(a의 최소값) 초기화
  2. M 기준 왼쪽 오른쪽 범위에 대해 각각 탐색
  3. 왼쪽의 경우 왼쪽 범위의 최소값이 현재보다 큰 경우 answer + 1
  4. 오른쪽의 경우 오른쪽 범위의 최소값이 현재보다 큰 경우 answer + 1
def solution(a):
    answer = 1
    M = min(a)
    for _ in range(2):
        m = a[0]
        i = 1
        while m != M:
            if m >= a[i]:
                m = a[i]
                answer += 1
            i += 1
        a.reverse()
    return answer

profile
후라이드 치킨

0개의 댓글

관련 채용 정보