https://www.acmicpc.net/problem/2295
2295번: 세 수의 합
우리가 x번째 수, y번째 수, z번째 수를 더해서 k번째 수를 만들었다라고 하자. 위의 예제에서 2+3+5=10의 경우는 x, y, z, k가 차례로 1, 2, 3, 4가 되며, 최적해의 경우는 2, 3, 4, 5가 된다. k번째 수가 최
www.acmicpc.net

문제 분석
중복이 가능한 세 수를 골라 집합에 있는 수를 만들면 된다.
N이 1000까지 가능하기 때문에 삼중 for문을 사용하여 세 수를 각각 골라 계산한다면
시간복잡도가 O(N**3)이 될 것이다.
큰 시간복잡도를 가지므로 다른 방법을 생각해보자.
우선 탐색을 위한 하나의 수(k번째 수)를 정한다.
이 수는 세가지 수의 합을 의미하는 수이다.
그 후 조합이 되는 세가지 수를 정해야 하는데
이 때, 사용할 수 있는 방법은 하나의 수를 정한 뒤 미리 정한 수에 뺀 값을 확인하는 방법이다.
즉, (k번째 수) - (z번째 수) = (x번째 수) + (y번째 수)가 되는 것이다.
이 방법을 사용하면 두 번의 반복문만으로 문제를 해결할 수 있다.
x번째 수와 y번째 수를 더한 값을 미리 입력받은 리스트에서 구해놓은 뒤
반복할 때마다 리스트에서 있는지 체크하면 된다.
코드1
set의 in을 사용
import sys
input = sys.stdin.readline
def solution():
# 가장 큰 수부터 두 수의 차이를 계산해서 남은 두 수의 합을 만들 수 있으면
# 세 수의 합이 존재하는 것
# (x + y) = k - z
for i in range(N - 1, -1, -1):
for j in range(i, -1, -1):
num = arr[i] - arr[j]
if num in sumL:
return arr[i]
N = int(input())
arr = [int(input()) for _ in range(N)]
sumL = set()
arr.sort()
# 두 수의 합 리스트 생성
for i in range(N):
for j in range(i, N):
sumL.add(arr[i] + arr[j])
print(solution())
코드2
이분 탐색을 사용 (시간이 더 느리다..?)
import sys
input = sys.stdin.readline
def solution():
# 가장 큰 수부터 두 수의 차이를 계산해서 남은 두 수의 합을 만들 수 있으면
# 세 수의 합이 존재하는 것
# (x + y) = k - z
for i in range(N - 1, -1, -1):
for j in range(i, -1, -1):
num = arr[i] - arr[j]
if bs(num):
return arr[i]
# 이분 탐색
def bs(num):
l, r = 0, len(sumL)
while l <= r:
m = (l + r) // 2
if num == sumL[m]:
return True
elif num > sumL[m]:
l = m + 1
elif num < sumL[m]:
r = m - 1
return False
N = int(input())
arr = [int(input()) for _ in range(N)]
sumL = set()
arr.sort()
# 두 수의 합 리스트 생성
for i in range(N):
for j in range(i, N):
sumL.add(arr[i] + arr[j])
sumL = sorted(list(sumL))
print(solution())
코드3
itertools의 combinations_with_replacement를 이용
이 함수는 배열과 반복 횟수를 지정해서 중복이 가능한 조합을 구하는 함수이다.
가장 빠른 방법
import sys
from itertools import combinations_with_replacement
input = sys.stdin.readline
def solution():
# 가장 큰 수부터 두 수의 차이를 계산해서 남은 두 수의 합을 만들 수 있으면
# 세 수의 합이 존재하는 것
# (x + y) = k - z
for i in range(N - 1, -1, -1):
for j in range(i, -1, -1):
num = arr[i] - arr[j]
if num in sumL:
return arr[i]
N = int(input())
arr = [int(input()) for _ in range(N)]
arr.sort()
sumL = {x + y for x, y in combinations_with_replacement(arr, 2)}
print(solution())
'알고리즘 > 백준' 카테고리의 다른 글
[백준/Python] 1629번: 곱셈 (0) | 2023.04.09 |
---|---|
[백준/Python] 9996번: 한국이 그리울 땐 서버에 접속하지 (0) | 2023.03.22 |
[백준/Python] 1402번: 아무래도이문제는A번난이도인것같다 (0) | 2023.02.24 |
[백준/Python] 17404번: RGB거리 2 (0) | 2023.02.08 |
[백준/Python] 10942번: 팰린드롬? (0) | 2023.02.01 |