From 5ccd49a533cea1c129eab652bfee6c286010e6ba Mon Sep 17 00:00:00 2001 From: Sumin Date: Wed, 27 Sep 2023 00:29:40 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Create=20=EA=B0=80=EC=9E=A5=20=EA=B8=B4=20?= =?UTF-8?q?=EC=A7=9D=EC=88=98=20=EC=97=B0=EC=86=8D=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=97=B4=20(large)=20sumin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sumin.py" | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 "BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" diff --git "a/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" "b/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" new file mode 100644 index 00000000..0d4aa33e --- /dev/null +++ "b/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" @@ -0,0 +1,46 @@ +""" +풀이시간: 50분 + + +n: 수열 s의 길이 (1 <= n <= 1,000,000) +k: 삭제할 수 있는 최대 횟수 (1 <= k <= 100,000) +s: 수열 (1 <= 원소의 값 <= 1,000,000) + + +최대 K개의 수를 삭제할 수 있다면, 연속한 짝수 부분수열의 길이를 길게 하기 위해 홀수만 K번 삭제를 해야 한다. +-> 홀수를 K개 포함하는 부분수열 중에서 가장 긴 것을 찾는 문제 +1. left와 right를 0부터 시작해 연속된 부분 수열을 탐색한다. +2. right를 이동하면서, 홀수가 나오면 해당 수를 제거한다(실제로 remove가 아니라 remove_cnt를 통해 개념적으로 제거) +3. 만약 remove_cnt가 제거할 수 있는 최대 개수인 K를 넘어선다면 left를 옮겨준다. +4. right를 끝까지 이동할 때까지, 가장 긴 연속된 짝수 부분 수열의 길이를 확인한다. + +<시간복잡도> +O(n) +- 두 포인터는 한 번에 하나의 요소만 확인하므로 모든 요소를 확인하는데 O(N) +- while문에서 홀수를 삭제하려면 left 포인터를 최악의 경우 (remove_cnt - K)번 이동 +""" +import sys +input = sys.stdin.readline + + +n, k = map(int, input().split()) # n: 수열의 길이, k: 최대 삭제 횟수 +s = list(map(int, input().split())) # 수열 s + +max_len = 0 # 가장 긴 연속된 짝수 부분 수열의 길이 + +left = 0 # 연속된 부분 수열의 왼쪽 포인터 +remove_cnt = 0 # 현재 연속된 부분 수열에서 삭제한 홀수의 개수 + +for right in range(n): # 연속된 부분 수열의 오른쪽 포인터를 이동하며 검사 + # 현재 오른쪽 포인터가 가르키고 있는 수가 홀수라면, 해당 수를 제거 + if s[right] % 2 != 0: + remove_cnt += 1 + # 제거한 홀수의 개수가 k를 넘으면, (홀수의 개수가 K개 이하가 될 때까지) left를 옮긴다. + while remove_cnt > k: + if s[left] % 2 != 0: + remove_cnt -= 1 + left += 1 + + max_len = max(max_len, right-left+1-remove_cnt) # 현재 연속된 부분 수열의 길이를 갱신 + +print(max_len) \ No newline at end of file From 7db58485654f372ed47c628f6b02c2dc23eb7c2d Mon Sep 17 00:00:00 2001 From: Sumin Date: Wed, 27 Sep 2023 12:23:36 +0900 Subject: [PATCH 2/2] refactor : remove while condition --- .../sumin.py" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" "b/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" index 0d4aa33e..42a12d2a 100644 --- "a/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" +++ "b/BOJ/\352\260\200\354\236\245 \352\270\264 \354\247\235\354\210\230 \354\227\260\354\206\215\355\225\234 \353\266\200\353\266\204 \354\210\230\354\227\264 (large)/sumin.py" @@ -18,6 +18,7 @@ O(n) - 두 포인터는 한 번에 하나의 요소만 확인하므로 모든 요소를 확인하는데 O(N) - while문에서 홀수를 삭제하려면 left 포인터를 최악의 경우 (remove_cnt - K)번 이동 + """ import sys input = sys.stdin.readline @@ -35,12 +36,11 @@ # 현재 오른쪽 포인터가 가르키고 있는 수가 홀수라면, 해당 수를 제거 if s[right] % 2 != 0: remove_cnt += 1 - # 제거한 홀수의 개수가 k를 넘으면, (홀수의 개수가 K개 이하가 될 때까지) left를 옮긴다. - while remove_cnt > k: - if s[left] % 2 != 0: - remove_cnt -= 1 - left += 1 - + # 제거한 홀수의 개수가 k를 넘으면, 왼쪽 포인터를 옮겨 연속 부분 수열의 길이를 줄여준다. + if remove_cnt > k: + if s[left] % 2 != 0: + remove_cnt -= 1 + left += 1 max_len = max(max_len, right-left+1-remove_cnt) # 현재 연속된 부분 수열의 길이를 갱신 print(max_len) \ No newline at end of file