본문 바로가기

알고리즘/백준

[백준] 1806번 : 부분합

728x90

https://www.acmicpc.net/problem/1806

 

1806번: 부분합

첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.

www.acmicpc.net

해당 문제는 이중 for문으로 문제를 해결 할 수 있다.N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000) 조건이 이므로, 시간복잡도는 O(N^2) 이고, 시간복잡도 문제가 발생한다. 투포인터를 이용하여 O(2N) -> O(N) 의 시간복잡도로 문제를 해결 할 수 있다.

p1과 p2로 포인터를 2개를 두고, p1=0 인상태 p2=1인 상태 그리고 초기 value=arr[0], 초기 length = 1로 두고 출발을 한다.

 

1) 종료시점

종료시점은 p2가 N-1상태이고 value가 S보다 작다면 p1을 움직여봐야 이미 최소 값이기 때문에 종료한다. p2가 N-1 상태에서 value가 S보다 크다면 p1을 N-1 상태까지 움직여서 최소 길이를 구해야하는데 value가 S보다 크다면 p1 커서만 움직여서 최소값을 구하기때문에 종료 조건은 if (N == p2 and value < S or N == p1) 로 잡았다.

 

2) 커서 움직임 조건

Value가 S보다 작은경우

- Value에 arr[p2] 값을 더하고 길이를 1증가 시키고, p2 커서를 하나 증가한다.

Vluae가 S보다 큰경우

- 최적의 길이의 값의 조건이기때문에 최소길이를 갱신한다, 그후 Value에 arr[p1] 값을 빼고, 길이를 1감소시키고, p2 커서를 증가시킨다.

 

INF = int(1e9)
N, S = map(int, input().split()) # N은 수열의개수, S는 부분집합의 합
arr = list(map(int, input().split()))


p1 = 0
p2 = 1
value = arr[0]
currentlen = 1
minlength = INF
while True:
    if (N == p2 and value < S) or (N == p1): # end가 도달했을경우
        if value >= S:
            minlength = min(minlength, currentlen)
        break
    
    if value < S: # 현재 value 값이 부분의 합보다 작다면
        value += arr[p2] # p2 를 더한다
        p2 += 1 # p2를 1증가한다
        currentlen += 1

    else:
        minlength = min(minlength, currentlen)
        value -= arr[p1] # p1 값을 뺀다
        p1 += 1 # p1 값을 더한다
        currentlen -= 1
        

        
if minlength == INF:
    print(0)
else:
    print(minlength)

 

 

728x90

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 4991번 : 로봇 청소기  (0) 2023.07.30
[백준] 1194번 : 달이 차오른다, 가자.  (0) 2023.07.29
[백준] 2098번 : 외판원 순회  (0) 2023.07.26
[백준] 2294번 : 동전 2  (0) 2023.07.24
[백준] 1987번 :알파벳  (0) 2023.07.23