KimMinJun
Coding Note
KimMinJun
전체 방문자
오늘
어제
  • 분류 전체보기 (486)
    • ALGORITHM (11)
      • 정렬 (6)
      • 최단경로 (1)
      • 자료구조 (1)
      • 슬라이딩 윈도우 (1)
      • etc (2)
    • Git (5)
    • Web (24)
      • Vanilla JS (13)
      • TS (2)
      • React (7)
      • ETC (1)
    • React 공식문서 (번역, 공부) (11)
      • Quick Start (2)
      • Installation (0)
      • Describing the UI (9)
      • Adding Interactivity (0)
      • Managing State (0)
      • Escape Hatches (0)
    • Next.js 공식문서 (번역, 공부) (3)
      • Getting Started (2)
      • Building Your Application (1)
    • PS (431)
      • 백준 (187)
      • Programmers (104)
      • CodeUp (21)
      • STL (3)
      • 제코베 JS 100제 (50)
      • SWEA (0)
      • LeetCode (65)
    • IT (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 관리

공지사항

인기 글

태그

  • recursion
  • codeup
  • 백준
  • C++
  • Level1
  • Level 2
  • 그래프
  • 다이나믹 프로그래밍
  • 수학
  • 문자열
  • 제코베 JS 100제
  • tree
  • programmers
  • Level 1
  • string
  • LeetCode
  • js
  • Level 0
  • C
  • 정렬

최근 댓글

최근 글

hELLO · Designed By 정상우.
KimMinJun
PS/백준

백준 / 투 포인터 / 22862번 / 가장 긴 짝수 연속한 부분 수열 (large) / JS

PS/백준

백준 / 투 포인터 / 22862번 / 가장 긴 짝수 연속한 부분 수열 (large) / JS

2025. 4. 7. 21:34

문제 간단설명

길이가 N인 수열 S가 있다.

 

수열 S는 1이상 정수로 이루어져 있는데,

최대 K개의 정수를 삭제할 수 있다.

 

최대 K개 삭제한 수열에서,

짝수로 이루어져 있는 연속한 부분 수열 중,

가장 긴 길이를 구하면 된다.

 

제한 사항

  • 1 <= N <= 1,000,000
  • 1 <= K <= 100,000
  • 1 <= 원소의 값 <= 1,000,000

 

성공 코드

const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : '../input.txt';
// const filePath = process.platform === 'linux' ? '/dev/stdin' : 'BOJ/input.txt';
const input = fs
  .readFileSync(filePath)
  .toString()
  .trim()
  .split('\n')
  .map((el) => el.trim());

const [N, K] = input.shift().split(' ').map(Number);
const sequence = input.shift().split(' ').map(Number);

function solution() {
  let left = 0;
  let right = 0;
  let removeCount = 0; // 제거한 홀수의 개수
  let result = 0;

  while (right < N) {
    // 짝수일 경우
    if (sequence[right] % 2 === 0) {
      result = Math.max(result, right - left - removeCount + 1);
      right++;
    } else {
      // 홀수일 경우
      // 제거한 홀수의 개수가 K보다 작으면 제거한 홀수의 개수를 증가시키고 포인터를 오른쪽으로 이동
      if (removeCount < K) {
        removeCount++;
        right++;
      } else {
        // 더 이상 제거할 수 없으면 왼쪽 포인터를 오른쪽으로 이동
        while (removeCount === K) {
          // 왼쪽 포인터가 가리키는 수가 홀수일 경우
          // 제거한 홀수의 개수를 줄이고 왼쪽 포인터 한 칸 오른쪽으로 이동
          if (sequence[left] % 2 === 1) {
            removeCount--;
          }
          left++;
        }
      }
    }
  }

  console.log(result);
}

solution();

 

투 포인터 알고리즘에서 조금 더 응용이 들어간 문제였다.

기본적인 문제에서 다음 두 가지만 신경쓰면 된다.

  1. 제거 횟수 관리
  2. 더 이상 제거할 수 없을 때 어떻게 할것인지

 

제거 횟수 관리

먼저, 제거 횟수를 관리하는 부분부터 알아보자.

처음에 최대 제거 횟수 K가 주어진다.

우리는 이 횟수를 홀수를 제거하는데 써야한다.

 

오른쪽 포인터가 수열의 끝에 다다를 때 까지 반복문으로 탐색한다.

 

오른쪽 포인터가 가리키는 값이 짝수라면,

현재 저장되어 있는 최댓값과

현재 수열의 길이에서 제거한 수를 뺀만큼의 길이를 비교하면 된다.

그리고 오른쪽 포인터를 한 칸 옮겨준다.

 

만약 오른쪽 포인터가 가리키는 값이 홀수라면,

다음 두 가지 상황이 있다.

  1. 제거할 수 있는 횟수가 남았을 때
  2. 제거할 수 있는 횟수가 남지 않았을 때

제거할 수 있는 횟수가 남았을 때는 간단하다.

현재 가리키는 홀수를 제거하고,

포인터를 한 칸 옮겨주면 된다.

 

더 이상 제거할 수 없을 때 어떻게 할 것인지

그런데,

제거할 수 있는 횟수가 남지 않았을 때는 어떻게 할까?

 

일단 왼쪽 포인터를 짝수를 만날때까지 옮겨준다.

그러면 우리가 홀수를 제거할 때 썼던 횟수를 충전할 수 있다.

예시로 알아보자.

 

1, 2, 4, 4, 5, 6, 7, 8 이라는 수열이 있을 때,

현재 left가 1을 가리키고 있고,

right가 5를 가리키고 있다고 해보자.

 

'가장 긴 짝수 연속한 부분 수열'을 구해야 하므로,

1을 제거하는데 제거 횟수를 한 번 썼을 것이다.

그러니까 이 때 사용한 제거 횟수를 충전하기 위해서

left를 2로 옮겨준다.

 

그러면 1, 2, 4, 4, 5 에서 가장 긴 짝수 연속한 부분 수열이나,

2, 4, 4, 5에서 가장 긴 짝수 연속한 부분 수열은 같다.

다만, 전자는 제거 횟수를 1을 제거하는데에 썼고,

후자는 제거 횟수를 사용하지 않았다.

 

이런 식으로 계속해서 반복하다면,

단 한번의 순회로 문제를 해결할 수 있다.

 

시간 복잡도는 O(n)이 되는 것이다.

저작자표시

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

백준 / 수학 / 11444번 / 피보나치 수 6 / JS  (0) 2025.01.13
백준 / 그래프 / 2206번 / 벽 부수고 이동하기 / JS  (0) 2025.01.11
백준 / 그래프 / 9019번 / DSLR / JS  (0) 2025.01.02
백준 / 그래프 / 16928번 / 뱀과 사다리 게임 / JS  (0) 2024.12.25
  • 문제 간단설명
  • 성공 코드
'PS/백준' 카테고리의 다른 글
  • 백준 / 수학 / 11444번 / 피보나치 수 6 / JS
  • 백준 / 그래프 / 2206번 / 벽 부수고 이동하기 / JS
  • 백준 / 그래프 / 9019번 / DSLR / JS
  • 백준 / 그래프 / 16928번 / 뱀과 사다리 게임 / JS
KimMinJun
KimMinJun

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.