(Leetcode) [Dynamic programming] Longest increasing subsequence
Topic: Dynamic programming
Difficulty: Medium
Question
Given an integer array nums
, return the length of the longest strictly increasing subsequence.
My first solution
int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
int arr[len];
for (int i=0; i<len; i++) {
arr[i]=0;
}
for (int i=0; i<len; i++) {
if (arr[i] == 0) { arr[i]=1; }
else { continue; }
vector<int>::iterator p = nums.begin()+i+1;
int p_arr = i+1;
vector<int>::iterator mark=p-1;
int mark_arr = p_arr-1;
for (p; p!=nums.end(); p++) {
if (*p > *mark) {
if (arr[p_arr] < arr[mark_arr]+1) {
arr[p_arr] = arr[mark_arr]+1;
mark_arr = p_arr;
mark = p;
}
}
p_arr++;
}
}
return *max_element(arr, arr+len);
}
์๋ฒฝํ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๊ฒฌํ๋ค๊ณ ์๊ฐํ์ง๋ง, ์ด๊ฑด ํฐ ์ค์ฐ์ด์๋ค.
์ผ๋จ longest subsequence array์ ์์ ๊ฐฏ์๋ฅผ ์ ์ฅํ๊ธฐ ์ํ array๋ฅผ ํ๋ ๋ง๋ค์ด์ค๋ค (arr[]).
์ฒซ๋ฒ์งธ for loop์ sequential array์ ์์์ ์ ์ก๊ธฐ ์ํจ์ด๊ณ ,
๋๋ฒ์งธ loop์์ iterator๊ฐ ๋ ๊ฐ ์ฐ์ธ๋ค.
sequential array๋ฅผ ์ด์ด๋๊ฐ๊ธฐ ์ํด์ ๋ฐ๋ก ์ ์ element์ ํฌ๊ธฐ ๋น๊ต๋ฅผ ํด์ผํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋น๊ตํ๋ ๊ณผ์ ์์ ์ ์ฝ์ ์ด ํ๋ ๋ฐ์ํ๋ค.
nums = [0 1 0 3 2 3]
arr = [1 2 1 3 2 3] -> my algorithm (wrong)
arr = [1 2 1 1 3 4] -> correct algorithm
nums์์ ๋ง๋ค ์ ์๋ ๊ฐ์ฅ ๊ธด subarray๊ฐ [0 1 2 3]์ด๋ค.
ํ์ง๋ง ๋ด ์ฝ๋์์ p iterator๊ฐ ์์๋๋ก ์์ง์ด๊ธฐ ๋๋ฌธ์, ๋ค์ ๋ ์์ ์ซ์๊ฐ ์์์๋ ์๋๋ฐ ๋น๊ต๋ฅผ ํ์ง ์์์
1 ๋ค์์ 2๊ฐ ์์์๋ ๋ถ๊ตฌํ๊ณ 2๋ณด๋ค ์์ ์๋ 3์ ์ฑํํด๋ฒ๋ฆฐ๋ค.
๊ทธ๋ฌ๋ฏ๋ก 2๋ ๋ฌด์๊ฐ ๋์ด๋ฒ๋ฆฐ๋ค.
๊ทธ๋ ๋ค๋ฉด ํด๊ฒฐ๋ฐฉ๋ฒ์ด ๋ฌด์์ด ์์๊น??
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ชป ์ฐพ์์ ๊ฒฐ๊ตญ์ geeksforgeeks,,
My second solution: Dynamic programming
์ผ๋จ ์ฝ๋๋ ๋ณด์ง ์๊ณ ์ค๋ช (illustration)๋ง ์ฝ์ด๋ดค๋ค.
nums[] = {3, 10, 2, 11}
arr[] = {1, 1, 1, 1} (initialization)
1. arr[2] > arr[1] -> arr[2] = max(arr[2], arr[1]+1) = 2
2. arr[3] < arr[1] -> no change
3. arr[3] < arr[2] -> no change
4. arr[4] > arr[1] -> arr[4] = max(arr[4], arr[1]+1) = 2
5. arr[4] > arr[2] -> arr[4] = max(arr[4], arr[2]+1) = 3
6. arr[4] > arr[3] -> arr[4] = max(arr[4], arr[3]+1) = 3
p๋ผ๋ iterator๋ฅผ ๋๊ณ , ์ด์ค ๋ฃจํ๋ฅผ ์ด์ฉํด์ p ์ด์ ์ ์๋ ๋ชจ๋ element๋ค๊ณผ ๋น๊ต๋ฅผ ํ๊ฒ ํ๋ฉด ๋์ ์ฒซ๋ฒ์งธ solution์ ๋ฌธ์ ์ ์ด ํด๊ฒฐ์ด ๋๋ค.
int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
int arr[len];
for (int i=0; i<len; i++) {
arr[i]=1;
}
if (len==1) { return 1; }
vector<int>::iterator p;
int p_arr = 1;
for (p=nums.begin()+1; p != nums.end(); p++) {
vector<int>::iterator mark;
int mark_arr = 0;
for (mark=nums.begin(); mark != p; mark++) {
if (*p > *mark) {
if (arr[p_arr] < arr[mark_arr]+1) {
arr[p_arr] = arr[mark_arr]+1;
}
}
mark_arr++;
}
p_arr++;
}
return *max_element(arr, arr+len);
}
runtime: 163 ms (์์ 30%)
memory usage: 10.4 MB (์์ 30%)
time complexity: O(n^2)
๋ฌธ์ follow up์์ time complexity๊ฐ O(nlog n)์ธ ์๊ณ ๋ฆฌ์ฆ์ ์ฐพ์๋ณด๋ผ๊ณ ํ๋ค. ๋ ๋ชป ์ฐพ์.
Third solution: Lower bound based approach (time complexity of O(nlog n))
int lengthOfLIS(vector<int>& nums) {
vector<int> arr;
int len = nums.size();
for (int i=0; i<len; i++) {
// lower_bound searches for nums[i] by binary search.
// if nums[i] doesn't exist in arr, p์ ์์น๋ nums[i]๋ณด๋ค ํฐ ๊ฐ ์ค์ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ๋ฅดํด.
vector<int>::iterator p = lower_bound(arr.begin(), arr.end(), nums[i]);
// p==nums.end() if all values of arr < nums[i]
if (p==nums.end()) { arr.push_back(nums[i]); }
// replace *p with ์์ ๋ณด๋ค ํฐ ๊ฐ ์ค ๊ฐ์ฅ ์์ ๊ฐ.
// ๋ฐ๋ผ์ arr์ ๊ธธ์ด์๋ ๋ณํ๊ฐ ์์ง๋ง, ์์๊ฐ ๋ ์์ ๊ฐ์ผ๋ก ๋์ฒด๋์์ผ๋ฏ๋ก ๋ ํฐ ๊ฐ์ ์์๋ก ๊ฐ์ฆ๋ ๋ถ๋ถ ๋ฐฐ์ด๋ณด๋ค๋ ํญ์ ์ด๋์ด๋ค.
else { *p = nums[i]; }
return arr.size();
}
}
Reference
https://www.geeksforgeeks.org/longest-increasing-subsequence-dp-3/ https://www.geeksforgeeks.org/c-program-for-longest-increasing-subsequence/
Leave a comment