골드2 : 이분 탐색 문제이다.
생각
기존에 dp로 풀었던 문제가 데이터의 개수만 달라져 새로운 문제가 되었다. 이번 문제는 풀이를 좀 참고하였으며 새로운 공부를 할 수 있었다.
이 문제는 먼저, 일반적인 dp문제로 풀수가 없다. dp로 풀기 위해서는, 알고리즘인데, 그렇게 될 경우 n=1000000이라, 터진다. 따라서 시간 복잡도를 줄여야 한다. 그래서 방법을 달리한다.
현재 index까지 왔을 때, 가장 긴 증가하는 수열의 길이는 얼마인가?
이것이 기존 dp로 풀었을 때 정의였다. 그런데 조금 색다르게, 배열을 하나 두고 이걸 만들어보자.
a[] : 1 2 4 3
#1 1
#2 1 2
#3 1 2 4
$4 1 2 ?
이 다음에 우리는 4번째 index에 있는 3을 추가해야 한다. 3까지 포함해 보았을 때, 가장 증가하는 수열의 길이는 1 2 4
혹은 1 2 3
으로 3이다. 여전히 값은 3이지만 지금 하는 과정은 증가하는 수열을 나타내는 배열을 만들어보는 중이다. 어떤 것을 선택하는 것이 바람직 할까?
조금 생각해보면 1 2 3을 가지고 있는 것이 보다 현명하다. 결국 3을 1 2 4에서 추가하지 못하는 이유는 3이 4보다 작기 때문이다. 그리고 이 마지막 값은, 다음 요소에 대한 LIS를 구하는 데 있어 가장 핵심적인 숫자이다. 이 숫자가 가장 작은 숫자를 유지하면서 같은 LIS값을 갖는 것이 이후에 배열을 업데이트하는데 있어서 LIS를 구하는 것에 핵심적이다. 그래서 기본적으로는 내 요소를 포함하는 LIS를 만드는 것이 좋다. 따라서 이 상황에서 우리는 3보다 큰 요소 중 가장 첫번째에 나오는 요소와 3을 바꿔야 한다.
그렇다면 여기서 만약 이렇게 주어졌다고 생각해보자.
a[] : 1 2 3 2
#1 1
#2 1 2
#3 1 2 3
$4 1 2 ?
여전히 같은 상황이다. 4번째 index인 2는 3보다 작기 때문에 추가할 수 없다. 그렇다면, 위의 논리대로라면 2는 3과 바꿔야 한다. 하지만 그럴 경우 1 2 2
로 LIS에 합당하는 배열을 만들지 못한다. 실질적으로 4번째 index에서 LIS는 1 2 3
이다. 즉, 유지되어야 한다. 따라서, 우리는 2를 LIS에서 찾아 자기 자신과 바꾸는 작업을 해야 한다.(위의 작업과의 일관성을 위해 이렇게 설명. 사실은 바꾸지 않는다라는 표현이 맞을지 모름)
lowerBound
위의 두 문제를 다 만족하는 것이 있다. 바로 lowerBound이다. lowerBound는, 내가 원하는 값의 가장 하한선의 위치를 찾아주고(같은 것을 고를 수 있음), 내가 원하는 값이 없을 경우, 내 값보다 큰 원소 중 가장 첫번째로 나오는 요소의 위치를 반환한다. 이 두 기능은, 위에서 설명한 문제의 해결책과 동일하다. 따라서 우리는 이 함수를 사용할 수 있다.