새소식

알고리즘 테스트 ⏲/백준

[백준] 11054. 가장 긴 바이토닉 부분 수열 풀이 / Python, JavaScript

  • -

 

 

11054번: 가장 긴 바이토닉 부분 수열

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

www.acmicpc.net

접근한 방법

가장 쉽게 푸는 방법은 가장 긴 증가하는 부분 수열을 구하는 알고리즘을 주어진 수열의 정방향과 역방향으로 적용해주면 해결 가능합니다.

주어진 예제를 봅시다.

1 5 2 1 4 3 4 5 2 1

위 수열에서 정방향으로 가장 긴 증가하는 부분 수열을 DP 테이블에 담았을 때 결과는 아래와 같습니다.

가장 긴 수열이 어떤 부분 수열인지는 상관없습니다.

[1, 2, 2, 1, 3, 3, 4, 5, 2, 1]

다음으로 역방향으로 가장 긴 증가하는 부분 수열을 DP 테이블에 담았을 때 결과는 아래와 같습니다.

가장 긴 수열이 어떤 부분 수열인지는 상관없습니다.

[1, 5, 2, 1, 4, 3, 3, 3, 2, 1]

이제 이 두 테이블을 비교하면서 각 인덱스에 위치한 값의 합이 가장 큰 경우를 찾으면 됩니다.

두 테이블의 원소를 서로 합하면 아래와 같습니다.

[2, 7, 4, 2, 7, 6, 7, 8, 4, 2]

여기서 가장 합이 큰 경우는 8입니다. 단 두 테이블이 원본 배열에서 원소 5를 중복 체크하고 있기에 8에서 1을 뺀 결괏값 7을 정답으로 도출할 수 있습니다.

 

 

작성 코드 (Python)

import sys
input = sys.stdin.readline

n = int(input())
arr = list(map(int, input().split()))
table_a, table_b = [1] * n, [1] * n
for i in range(n):
    for j in range(i):
        if arr[i] > arr[j]:
            table_a[i] = max(table_a[i], table_a[j] + 1)
for i in range(n - 1, -1, -1):
    for j in range(n - 1, i, -1):
        if arr[i] > arr[j]:
            table_b[i] = max(table_b[i], table_b[j] + 1)
result = 0
for i in range(n):
    result = max(result, table_a[i] + table_b[i] - 1)
print(result)

작성 코드 (JavaScript)

function solution(n, array) {
  const [tableA, tableB] = [Array(n).fill(1), Array(n).fill(1)];
  for (let i = 0; i < n; i += 1) {
    for (let j = 0; j < i; j += 1) {
      if (array[i] > array[j]) tableA[i] = Math.max(tableA[i], tableA[j] + 1);
    }
  }
  for (let i = n - 1; i >= 0; i -= 1) {
    for (let j = n - 1; j > i; j -= 1) {
      if (array[i] > array[j]) tableB[i] = Math.max(tableB[i], tableB[j] + 1);
    }
  }
  let result = 0;
  for (let i = 0; i < n; i += 1) {
    result = Math.max(result, tableA[i] + tableB[i] - 1);
  }
  return result;
}
solution(10, [1, 5, 2, 1, 4, 3, 4, 5, 2, 1]);
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.