상세 컨텐츠

본문 제목

풍선 터뜨리기

코딩테스트/정렬

by 수타. 2023. 7. 14. 14:54

본문

 

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

 

프로그래머스

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

programmers.co.kr

문제요약:

풍선들의 리스트가 있고 각 풍선들은 숫자가 할당되어있다, 인접한 풍선에서 큰것을 터뜨리고 작은것을 터뜨릴수 있는건 한번일때, 마지막에 남을수 있는 풍선의 숫자를 구하시오

 

소요시간:

20분

난이도3

 

1차 코딩:

def solution(a):
	ans = 2
	for i in range(1,len(a)-1):
		min1= min(a[:i])
		min2= min(a[i+1:])
		if max(min1,min2,a[i]) !=a[i]:
			ans +=1
	return ans

논리를 간단하게 구현한 1차 코딩 입니다. 

인접한 풍선에서 큰것만 터뜨리게 되면 결국 마지막엔 제일 작은 숫자를 가진 풍선이 남게 될것입니다.

이때 만약 어떠한 특정한 풍선이 살아 남을 수 있는지 없는지 알고 싶다면 그 특정 풍선을 제외하고 앞뒤로 리스트를 만들고 각 리스트의 최소값을 구한다음 만약 앞리스트의 최솟값, 특정한 풍선, 뒷자리의 최솟값 이 세 숫자 중 만약 본인이 제일 큰것이 아니라면(제일작은값이라면 큰것만터뜨리면 되고 두번째라면 작은것을 터뜨릴수 있는 한번의 기회를쓰면됨) 마지막에 남을 수 있기 때문에 다음과 같이 코딩 했습니다.

 

하지만이는 i 가 증가할때 마다 min함수가 두번씩 돌아야 함으로,    

 

import heapq as hp
def solution(a):
	ans = 2
	min1 = []
	min2 = a[1:]
	hp.heapify(min2)
	min2_left = []
	for i in range(1,len(a)-1):
		hp.heappush(min1,a[i-1])
		hp.heappush(min2_left,a[i])
		while min2_left and min2_left[0]==min2[0]:
			hp.heappop(min2)
			hp.heappop(min2_left)
		if max(min1[0],min2[0],a[i]) != a[i]:
			ans +=1
	return ans

다음과 같이 heap함수를 이용해 그때그때 min1의 최소값을 구해주었으며 , heap구조에서 최소값이 아닌 특정 수를 빼는 방법은 다음과 같이 빠지는 후보 list를 만든다음 이 리스트의 최솟값과 min2의 최솟값이 같을 때 빼주면 우선순위큐에서 최솟값이 아닌 특정수를 뺄수 있습니다.

 

다른사람 코드1 :

def solution(a):
    answer = 0
    left, right = float('inf'), float('inf')
    min_map = [[0, 0] for _ in range(len(a))]

    # 왼쪽 범위에서 최솟값 찾기
    for i in range(len(a)):
        if left > a[i]:
            left = a[i]
        min_map[i][0] = left

    # 오른쪽 범위에서 최솟값 찾기
    for i in range(len(a) - 1, -1, -1):
        if right > a[i]:
            right = a[i]
        min_map[i][1] = right

    # 찾은 최솟값 데이터를 가지고 기준 숫자의 양쪽이 모두 기준 숫자보다 작으면 answer += 1
    for i in range(len(a)):
        if a[i] <= min_map[i][0] or a[i] <= min_map[i][1]:
            answer += 1

    return answer

작성자는 알고리즘은 저와 똑같이 짜셨지만, 그때 그때 최솟값을 구할 필요없이 미리 두바퀴를 돌며 특정 부분까지의 최소값을 미리 구한 후, 비교만 해주었습니다. 

 

다른사람 코드2 :

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

비슷한 매커니즘에 더 간단한 코드입니다.

앞에서 부터 ,또 뒤에서부터 총 두바퀴를 돌았으며 각 첫번째항을 기본으로 놓고 최솟값이 갱신되는 횟수를 세 주었습니다.

아까 자신의 앞, 자신, 자신의 뒤 이 셋중 최대값만 아니면 된다고 했는데, 사실 전체에서 최솟값은 정해져 있고, 이 최솟값이 포함된 리스트의 최솟값은 항상 이 최솟값이기 때문에, 전체에서 최솟값을 기준으로 좌우만 살피면 되며, 이 최솟값을 포함하기 때문에 1에서 부터 시작하였습니다.  

 

'코딩테스트 > 정렬' 카테고리의 다른 글

가운데를 말해요  (1) 2023.09.10
상어 초등학교  (0) 2023.08.11
보석 쇼핑  (0) 2023.07.07
숫자게임  (0) 2023.07.03
야근지수  (0) 2023.07.03

관련글 더보기