[알고리즘] 증가수열 만들기(그리디)

(문제) 증가수열 만들기(그리디)


1부터 N까지의 모든 자연수로 구성된 길이 N의 수열이 주어집니다.

이 수열의 왼쪽 맨 끝 숫자 또는 오른쪽 맨 끝 숫자 중 하나를 가져와 나열하여 가장 긴 증가수열을 만듭니다.

이때 수열에서 가져온 숫자(왼쪽 맨 끝 또는 오른쪽 맨 끝)는 그 수열에서 제거됩니다.

예를 들어 2 4 5 1 3 이 주어지면 만들 수 있는 가장 긴 증가수열의 길이는 4입니다.

맨 처음 왼쪽 끝에서 2를 가져오고, 그 다음 오른쪽 끝에서 3을 가져오고, 왼쪽 끝에서 4, 왼쪽 끝에서 5를 가져와 2 3 4 5 증가수열을 만들 수 있습니다.

입력설명

첫째 줄에 자연수 N(3<=N<=100)이 주어집니다.

두 번째 줄에 N개로 구성된 수열이 주어집니다

출력설명

첫째 줄에 최대 증가수열의 길이를 출력합니다.

두 번째 줄에 가져간 순서대로 왼쪽 끝에서 가져갔으면 ‘L’, 오른쪽 끝에서 가져갔으면 ’R’를 써간 문자열을 출력합니다.
(단 마지막에 남은 값은 왼쪽 끝으로 생각합니다.)

테스트케이스

입력예제 출력예제
5
2 4 5 1 3
4
LRLL
5
1 3 5 2 4
4
LLRL
10
3 2 10 1 5 4 7 8 9 6
3
LRR

해결방법

문제는 증가 수열을 구하는 것이며 N개로 구성된 수열이라고 함으로 1~N 까지 만들기 때문에, 첫 비교를 0으로 시작하기 위해 last 라는 변수를 생성하여 0으로 초기화 한다.

“L” 혹은 “R”을 저장할 수 있는 word 변수를 추가 한다.

lt : 시작위치 와, rt : 끝 위치를 인덱스로 잡아 놓는다.

만약 이 lt 가 rt 보다 작을 때 무한 반복을 한다.

이 아래 있는 과정은 일정 조건이 충족하지 않는 이상 무한 반복을 할 것이다.

그 후, temp라는 리스트를 생성하여 값이 들어있는 리스트의 맨 왼쪽 값과 맨 오른쪽 값 중, last 보다 큰 값을 temp라는 리스트에 대입한다.

대입할 때, 왼쪽것을 대입할 때는 튜플로 (값, “L”) 로 대입하고, 오른쪽 것을 대입할 때는 튜플로 (값, “R”) 로 대입합니다.

그 후, temp를 정렬 시킨다.

정렬을 시켜야 그 다음 위치에 들어갈 수열이라는 것을 알 수 있기 때문이다.

만약에 temp 라는 리스트에 값이 있으면 가장 첫번째 인덱스에 있는 값과 위치를 값은 last에 대입하고 위치 즉, “L” 혹은 “R”은 word에 추가한다.

추가 할 때 만약에 “L”을 추가하면 lt에 + 1을 하고, “R”을 추가하면 rt - 1로 rt를 줄여 준다!

만약 temp 라는 리스트에 값이 없으면 이 반복문을 종료한다.


코드

n = int(input())

arr = list(map(int, input().split()))

last = 0

lt = 0
rt = n-1

temp = []

word = ""

while lt < rt:
    if last < arr[lt]:
        temp.append((arr[lt], "L"))
    if last < arr[rt]:
        temp.append((arr[rt], "R"))
    temp.sort()

    if temp:
        word = word + temp[0][1]
        last = temp[0][0]
        if temp[0][1] == 'L':
            lt = lt + 1
        else:
            rt = rt - 1
        temp.clear()
    else:
        break

print(len(word), word, sep='\n')

댓글남기기