프로그래머스_두수의합같게만들기

임정민·2024년 3월 5일
0

알고리즘 문제풀이

목록 보기
171/173
post-thumbnail

프로그래머스 Lv2 문제입니다. 실전에 대비하기 위해 60분 시간제한을 두고 풀었습니다.

문제

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

⌛ 56분

[나의 풀이]


from collections import deque

def solution(queue1, queue2):
    answer = -2
    
    queue1 = deque(queue1)
    queue2 = deque(queue2)
    hap1 = sum(queue1)
    hap2 = sum(queue2)
    chance = 0
    max_chance = len(queue1)*3
    isFind = False

    while chance<max_chance:
        
        if hap1>hap2:
            v1 = queue1.popleft()
            queue2.append(v1)
            hap1 -= v1
            hap2 += v1
        elif hap1<hap2:
            v2 = queue2.popleft()
            queue1.append(v2)
            hap2 -= v2
            hap1 += v2
        else:
            isFind = True
            break
        chance += 1
    if isFind:
        return chance
    else:
        return -1

크기가 동일한 두 큐(queue1, queue2)가 주어지고 (1)queue1의 요소를 pop하여 queue2에 insert하거나, (2)queue2의 요소를 pop하여 queue1에 insert하여 각 큐들의 합을 같게하는 insert(pop) 최소 횟수를 구하는 문제입니다.

먼저 리스트로 입력되는 두 큐(queue1,queue2)를 deque()를 활용하여 Queue자료구조로 바꾸어주었습니다.

이후 각 큐의 합(hap1, hap2)을 미리 정의해줍니다. 이는 문제에서 정의한 큐의 최대 크기(300000)일 때를 기준으로 queue에 새로운 요소가 추가된어 합을 구해야한다면, 반복문이 실행될 때마다 최악의 경우 300000개를 sum()하여 합을 확인해야하기 때문에 시간 초과가 발생할 수 있기 때문입니다.

다음으로 현재 상태의 queue1의 합(hap1)과 queue2의 합(hap2)를 비교하여 hap1이 hap2보다 크다면 queue1의 요소를 queue2에 insert하고 그 반대라면 queue2의 요소를 queue1에 insert하여 hap1이 hap2와 같을 때까지 반복하는 방식입니다.

단, 큐 구조이므로 insert-pop을 계속 반복한다면 처음 queue1, queue2의 형태로 돌아오게 되므로 max_chance(처음 상태까지 돌아가는 횟수)를 정의하여 제한을 두어 두 큐가 같아질 수 없다면 -1를 반환합니다.

[다른 사람의 풀이]

def solution(queue1, queue2):
    _sum = (sum(queue1) + sum(queue2)) // 2
    
    if (max(queue1 + queue2) > _sum) : return -1
    
    answer, start1, start2 = 0, 0, 0
    end1, end2 = len(queue1) - 1, len(queue1) - 1
    lst1 = queue1 + queue2 + queue1
    lst2 = queue2 + queue1 + queue2
    sum1, sum2 = sum(queue1), sum(queue2)
    
    while sum1 != _sum and sum2 != _sum :

        if sum1 < _sum :
            end1 += 1
            if end1 == len(lst1) : return -1
            sum1 += lst1[end1]
        else :
            sum1 -= lst1[start1]
            start1 += 1
        
        if sum2 < _sum :
            end2 += 1
            if end2 == len(lst2) : return -1
            sum2 += lst2[end2]
        else :
            sum2 -= lst2[start2]
            start2 += 1
        answer += 1
    return answer

투 포인터 알고리즘을 활용한 풀이입니다.

Queue구조로 변환하여 popleft(), append()하는 방식이 아니라, 각 큐별로 다른 큐를 앞/뒤로 확장하여 투 포인터의 인덱스를 통해 범위를 규정하는 방식입니다.

예를 들어 queue1을 기준으로 앞/뒤로 queue2의 요소를 더하는 구조에서, popleft()해야한다면 start 인덱스를 더하며 append()해야한다면 end 인덱스를 더하여 범위를 정하고 합을 확인할 수 있었습니다.

각 큐의 합들(sum1, sum2)을 미리 규정하고 새로 추가/삭제되는 요소만 연산(+/-)하여 반복문 실행 시마다 sum()하지 않도록 한 부분은 '나의 풀이'와 같았습니다.

감사합니다.

profile
https://github.com/min731

0개의 댓글