문제
풀이
처음 접근한 방식은 고른 물건의 수가 1개, 2개, 3개일 때를 구분해서 구현했었다.
1. 먼저 오름차순으로 정렬한다.
2. 각 case에 따라 나누어 binary search를 통해 확인한다.
diff = C - weight[i]
가 있는지 binarySearch로 확인한다.diff = C - (weight[i] + weight[j])
가 있는지 binarySearch로 확인한다.이를 구현한 코드는 아래와 같다.
#18114번 블랙프라이데이
import sys
def binarySearch(start, end, c, weights):
while start <= end:
mid = (start + end) // 2
if weights[mid] == c:
return mid
if weights[mid] < c:
start = mid + 1
else:
end = mid - 1
return -1
def event(n, c, weights):
if binarySearch(0, n - 1, c, weights) >= 0:# 고른 물건 1개
return True
for i in range(n): # 고른 물건 2개
diff = c - weights[i]
if diff > 0 :
if binarySearch(i + 1, n - 1, diff, weights) >= 0:
return True
for i in range(n): # 고른 물건 3개
for j in range(i + 1, n):
diff = c - (weights[i] + weights[j])
if diff > 0:
if binarySearch(j + 1, n - 1, diff, weights) >= 0:
return True
return False
# N : 물건 개수, C : 무게
N, C = map(int, sys.stdin.readline().split())
# N개의 물건의 무게들
weights = list(map(int, sys.stdin.readline().split()))
weights.sort()
if event(N, C, weights):
print(1)
else:
print(0)
다른 문제에서 썼었던 two pointer
를 조금 응용해보았다. 이 역시 개수에 따라 case를 나누었지만, 위와는 다르게 1개인 경우와 2개 or 3개인 경우로 나누었다. 이를 살펴보면,
C
가 weights
리스트에 있는지 binarySearch
를 통해 확인 한다.i
: 제일 작은 값(0
), j
: 제일 큰 값(N - 1
),weightSum = weights[i] + weights[j]
일 때,weightSum
이 C
인 경우 True
를 반환하면 된다.weightSum
이 C보다 크다면 i를 1씩 증가시킨다.weightSum
이 커지게 된다weightSum
이 C보다 작으면 j를 1씩 감소시킨다.weightSum
이 작아지게 된다i
번째와 j
번째 weight
는 제외하고,diff = c - weightSum
가 weights
리스트에 있는지만 확인하면 된다.말로 설명하면 꽤 복잡하지만, 아래 코드를 보면서 따라가보면 충분히 이해가 될 것이다.
#18114번 블랙프라이데이
import sys
def binarySearch(start, end, c, weights):
while start <= end:
mid = (start + end) // 2
if weights[mid] == c:
return mid
if weights[mid] < c:
start = mid + 1
else:
end = mid - 1
return -1
def event(n, c, weights):
if binarySearch(0, n - 1, c, weights) >= 0:# 고른 물건 1개
return True
i = 0
j = n - 1
while(i < j): # 고른 물건 2개 or 3개
weightSum = weights[i] + weights[j]
if weightSum > c:
j -= 1
elif weightSum == c: # 고른 물건 2개
return True
else:
diff = c- weightSum
if diff != weights[i] and diff != weights[j] and binarySearch(0, n - 1, diff, weights) >= 0:
return True # 고른 물건 3개
i += 1
return False
# N : 물건 개수, C : 무게
N, C = map(int, sys.stdin.readline().split())
# N개의 물건의 무게들
weights = list(map(int, sys.stdin.readline().split()))
weights.sort()
if event(N, C, weights):
print(1)
else:
print(0)
결론
문제의 답은 어떻게든 구할 수 있지만, 코딩테스트나 일반적인 개발에서도 중요한 것이 바로 시간복잡도이다. N이 조금씩만 커져도 전체 프로그램의 시간복잡도가 걷잡을 수 없이 커지기 때문에, 이를 주의해서 생각해야 함을 깨달았다. 예전부터 풀어왔던 문제인데, 시간 복잡도 때문에 막혀서 방치해두었다가, 최근에 two poiner문제를 풀게 되면서, 이를 응용하면 되겠다고 생각했다. 배운 것을 응용해서 문제를 해결하는 것도 매우 중요하다고 생각이 들었다!
앞으로도 화이팅 하자!!!