백준 2470번: 두 용액 [Python]

tomkitcount·2026년 1월 7일

매일 알고리즘

목록 보기
287/303

문제 출처 : https://www.acmicpc.net/problem/2470
난이도 : 골드 5


문제 파악

이 문제의 본질은 배열에서 서로 다른 두 숫자를 골라 합이 0에 가장 가까워지도록 만드는 것이다.
그리고 그 합이 가장 0에 가까워졌을 때의 두 숫자 자체를 출력해야 한다.

이를 효율적으로 해결하기 위해 배열을 먼저 정렬한 뒤,
양 끝에서 시작하는 투 포인터 방식을 사용한다.

우리는 “0에 가장 가까운 값”을 찾아야 하므로
각 시점의 합에 대해 절댓값 abs()를 기준으로 비교해야 한다.

또한 언제든 더 좋은 조합이 나올 수 있기 때문에,
현재까지의 최소 절댓값을 저장할 best를 충분히 큰 값(float('inf'))으로 초기화하고
매번 더 작은 절댓값이 나오면 이를 갱신하는 방식으로 접근한다.

이때마다 해당 조합의 두 값을 answer에 함께 저장해 두고,
모든 탐색이 끝난 뒤 abs(mix)가 가장 작았던 순간의 answer를 출력하면 된다.

해답 및 풀이

import sys
input = sys.stdin.readline

# 산성(양수), 알칼리(음수)라는 설정이 있지만
# 결국은 "두 수의 합이 0에 가장 가까운 쌍"을 찾는 문제

N = int(input())  # 최대 100,000
nums = list(map(int, input().split()))

# 투 포인터를 쓰려면 정렬이 필수
nums.sort()

# 정렬된 배열에서 양 끝에서 시작
left = 0
right = N - 1

# abs(mix)의 최소값을 저장 (초기값은 아주 크게)
best = float('inf')

# 정답으로 뽑힌 두 용액 값 저장
answer = (0, 0)

while left < right:
    mix = nums[left] + nums[right]

    # 현재 조합이 더 0에 가까우면 갱신
    if abs(mix) < best:
        best = abs(mix)
        answer = (nums[left], nums[right])

    # 합이 양수면 너무 큰 상태 -> right를 줄여서 합을 낮춘다
    if mix > 0:
        right -= 1

    # 합이 음수면 너무 작은 상태 -> left를 늘려서 합을 키운다
    elif mix < 0:
        left += 1

    # mix == 0이면 이론상 최적이라 바로 종료
    else:
        break

print(answer[0], answer[1])

나는 계속 best를 갱신하는 방법이 아닌,
혼합물을 0과 비교하려고 했기에 해멨다.

다시 풀어본 코드

import sys
input = sys.stdin.readline

INF = float('inf')

N = int(input())
nums = list(map(int,input().split()))

nums.sort()

left = 0 
right = N-1
best_value = INF
best_pair = [None,None]

while left < right:
    total = nums[left] + nums[right]

    if abs(total) < best_value:
        best_value = abs(total)
        best_pair[0] = nums[left]
        best_pair[1] = nums[right]

    if total > 0:
        right -= 1
    
    elif total < 0:
        left += 1
    
    else:
        print(nums[left], nums[right])
        sys.exit(0)

print(best_pair[0],best_pair[1])
profile
To make it count

0개의 댓글