문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

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

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

둘째 줄에는 가장 긴 증가하는 부분 수열을 출력한다. 그러한 수열이 여러가지인 경우 아무거나 출력한다.

예제

예제 입력 1

1
2
3
6
10 20 10 30 20 50

예제 출력 1

1
2
4
10 20 30 50

내 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 나의 오답
const [N, input] = require("fs")
.readFileSync("/dev/stdin")
.toString()
.trim()
.split("\n");
const A = input.split(" ").map(Number);

const DP = Array.from({ length: N }, () => 1);

for (let i = 1; i < N; i++) {
for (let j = 0; j < i; j++) {
if (A[j] < A[i]) {
DP[i] = Math.max(DP[i], DP[j] + 1);
}
}
}

const LIS = Math.max(...DP);

let LIS_Array = [];
for (let i = 0; i < N; i++) {
const index = DP.findIndex((elem) => elem === i + 1);
LIS_Array.push(A[index]);
}

console.log(LIS);
console.log(LIS_Array.join(" "));
  • 기존 LIS를 구하는 로직에서 DP에 해당하는 LIS뿐만 아니라 그 때의 배열까지 생성해주도록 하였다.
  • 처음 배열 길이만큼 반복문을 순회하면서 DP값에서 Index를 찾는다. 해당 index의 A 수열의 값을 넣어준다.
  • 왜 틀렸는지 이유를 모르겠어서 해설을 보게되었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const [N, input] = require("fs")
.readFileSync("/dev/stdin")
.toString()
.trim()
.split("\n");
const A = input.split(" ").map(Number);

const DP = Array.from({ length: N }, () => 1);

for (let i = 1; i < N; i++) {
for (let j = 0; j < i; j++) {
if (A[j] < A[i]) {
DP[i] = Math.max(DP[i], DP[j] + 1);
}
}
}

let LIS = Math.max(...DP);
let LIS_Array = [];

for (let i = N - 1; i >= 0; i--) {
if (DP[i] === LIS) {
LIS_Array = [A[i], ...LIS_Array];
LIS--;
}
}

console.log(LIS_Array.length);
console.log(LIS_Array.join(" "));
  • 이전 내 코드는 findIndex 메서드로 제일 앞에서 부터 해당 인덱스를 찾아주도록 하였다. 하지만 이런 경우 반례가 생긴다. 왜냐하면 내가 처음에 DP의 초기값을 모두 1로 설정해두었기 때문에 LIS_Array의 배열의 데이터가 이상하게 들어올 수 있다

반례

N = 14, A = [10, 12, 1, 3, 5, 6, 7, 10, 12, 2, 4, 7, 10, 12]

  • findIndex로 앞에서부터 찾았을 경우: LIS_Array = [10, 12, 5, 6, 7, 10, 12]
  • 반복문 역순으로 찾았을 경우: LIS_Array = [1, 3, 5, 6, 7, 10, 12]