LIS - changicho/algorithm-training GitHub Wiki
์ต์ฅ ์ฆ๊ฐ ์์ด
๋ณดํต LIS๋ฅผ ๊ตฌํ๋ ๋ฌธ์ ์ ๋ต์ ํ ์์ด์์ ์ฃผ์ด์ง๋ LIS์ ๊ธธ์ด๊ฐ ๋ต์ด ๋๋ค.
index๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฆ๊ฐ์์ผ๊ฐ๋ฉฐ, ์ด์ ์ ๋ฐฉ๋ฌธํ๋ 0 ~ (index-1)๊น์ง์ ๊ฐ์ ๋ค์ ์ํํ๋ฉฐ ๊ณ์ฐํ๋ ๊ฐ์ ์ด์ฉํด ํ์ฌ index์ ๊ฐ์ ๊ฐฑ์ ํ๋ค.
int lis(vector<int> array) {
int size = array.size();
// initialize
vector<int> dp(size, 1);
for (int target = 0; target < size; target++) {
for (int before = 0; before < target; before++) {
if (array[before] < array[target]) {
dp[target] = max(dp[target], dp[before] + 1);
}
}
}
return dp.back();
}์๊ฐ ๋ณต์ก๋ : O(N * log_2(N))
- N : O(N)์ผ๋ก ๋ฐฐ์ด์ ํ์ํจ
- log_2(N) : lower_bound๋ก ์ต์ ์ ์๋ฆฌ๋ฅผ ์ฐพ์
๋ฐฐ์ด์ ์ํํ๋ฉด์ ๋ฒกํฐ์ ๋งจ ๋ค ์์์ ํ์ฌ ๋ณด๊ณ ์๋ ์์ด์ ์์๋ฅผ ๋น๊ตํ๋ค.
์์ด์ ์์๊ฐ ๋ ํด ์ ๋ฒกํฐ์ push_backํด์ค ๋ค LIS์ ํฌ๊ธฐ(๋ต)์ 1์ฆ๊ฐ ์ํจ๋ค. ์์ด์ ์์๊ฐ ๋ฒกํฐ์ ๋งจ ๋ค ์์๋ณด๋ค ์์ ๊ฒฝ์ฐ lower_bound๋ฅผ ์ด์ฉํ์ฌ ์ต์ ์ ์๋ฆฌ๋ฅผ ์ฐพ์ ๋ค ๊ทธ ์๋ฆฌ์ ๊ฐ์ ํด๋น ์์ด์ ์์๋ก ๊ต์ฒดํ๋ค.
LIS ๋ฐฐ์ด์ ๊ตฌํ๊ธฐ ์ํด์ ๊ฐ index๋ณ๋ก ์ด๋ค ๊ฐ์ด ์๋์ง ๊ฐ์ด ์ ์ฅํด์ผํ๋ค.
int lisLength(vector<int>& nums) {
int size = nums.size();
vector<int> lis;
for (int i = 0; i < size; i++) {
int target = lower_bound(lis.begin(), lis.end(), nums[i]) - lis.begin();
if (target == lis.size()) {
lis.push_back(nums[i]);
} else {
lis[target] = nums[i];
}
}
// lis ๋ฐฐ์ด์ LIS๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์์๋ก ์ฌ์ฉ๋ ์ซ์๋ค์ด ๋ค์ด์์
return lis.size();
}LIS ์๊ณ ๋ฆฌ์ฆ์์ lower_bound๋ฅผ ์ด์ฉํด ์ด์ ์ ๋์จ ๊ฐ์ค์์ ํ์ฌ๊ฐ ์ด์์ธ ๋ถ๋ถ์ ๊ต์ฑํ๋ค.
์ด๋ฅผ upper_bound๋ฅผ ์ด์ฉํ ๊ฒฝ์ฐ ์ด์ ์ ๋์จ ๊ฐ์ค ํ์ฌ๊ฐ์ ์ด๊ณผํ๋ ๋ถ๋ถ์ ๊ต์ฑํ๋ฉฐ, ์ด ๊ณผ์ ์์ ์ค๋ณตํด์ ์์๊ฐ ๋ค์ด๊ฐ ์ ์๋ค.
int longestNonDecreasingSubsequence(vector<int> &nums){
int size = nums.size();
vector<int> lis;
for (int i = 0; i < size; i++) {
int target = upper_bound(lis.begin(), lis.end(), nums[i]) - lis.begin();
if (target == lis.size()) {
lis.push_back(nums[i]);
} else {
lis[target] = nums[i];
}
}
// lis ๋ฐฐ์ด์ LIS๋ฅผ ๊ตฌ์ฑํ๋ ์์๊ฐ ๋ค์ด์์
return lis.size();
}struct LIS {
int index, from;
};
vector<int> longestIncreasingSubsequence(int N, vector<int> array) {
vector<LIS> lis;
int lis_cache[MAX] = {
0,
};
int index = 0;
lis_cache[index] = array[0];
lis.push_back({0, array[0]});
for (int i = 1; i < N; i++) {
if (lis_cache[index] < array[i]) {
index++;
lis_cache[index] = array[i];
lis.push_back({index, array[i]});
} else {
int new_index = lower_bound(lis_cache, lis_cache + index, array[i]) - lis_cache;
lis_cache[new_index] = array[i];
lis.push_back({new_index, array[i]});
}
}
// index + 1์ LIS ๋ฐฐ์ด์ ํฌ๊ธฐ๋ฅผ ์๋ฏธํ๋ค.
// ์ญ์์ผ๋ก LIS ๋ฐฐ์ด์ ๊ตฌํ๋ค. (index๋ฅผ ์ด์ฉํด ์ญ์์ผ๋ก ๊ตฌํจ)
stack<int> s;
for (int i = N - 1; i >= 0; i--) {
if (lis[i].index == index) {
s.push(lis[i].from);
index--;
}
}
// stack์ ์ญ์์ผ๋ก ์ ์ฅ๋์ด์์ผ๋ฏ๋ก ๋ค์ง์ด LIS ๋ฐฐ์ด์ ๊ตฌํจ
vector<int> ret;
while (!s.empty()) {
ret.push_back(s.top());
s.pop();
}
return ret;
}