diff --git a/300.LongestIncreasingSubsequence/binary_search.cpp b/300.LongestIncreasingSubsequence/binary_search.cpp new file mode 100644 index 0000000..4f15f35 --- /dev/null +++ b/300.LongestIncreasingSubsequence/binary_search.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + // least increasing order + vector lis; + + for (auto num : nums) { + auto it = lower_bound(lis.begin(), lis.end(), num); + if (it == lis.end()) { + lis.push_back(num); + } else { + *it = num; + } + } + + return lis.size(); + } +}; diff --git a/300.LongestIncreasingSubsequence/iteration_step1.cpp b/300.LongestIncreasingSubsequence/iteration_step1.cpp new file mode 100644 index 0000000..1a2d55c --- /dev/null +++ b/300.LongestIncreasingSubsequence/iteration_step1.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + if (nums.empty()) { + return 0; + } + vector increasing_nums; + increasing_nums.push_back(nums[0]); + for (int i = 1; i < nums.size(); i++) { + if (nums[i] > increasing_nums.back()) { + increasing_nums.push_back(nums[i]); + continue; + } + // find first larger or equal num + int greater_or_equal_index = 0; + while (nums[i] > increasing_nums[greater_or_equal_index]) { + greater_or_equal_index++; + } + increasing_nums[greater_or_equal_index] = nums[i]; + } + + return increasing_nums.size(); + } +}; diff --git a/300.LongestIncreasingSubsequence/iteration_step2.cpp b/300.LongestIncreasingSubsequence/iteration_step2.cpp new file mode 100644 index 0000000..53a4a2b --- /dev/null +++ b/300.LongestIncreasingSubsequence/iteration_step2.cpp @@ -0,0 +1,43 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + if (nums.empty()) { + return 0; + } + vector increasing_nums; + increasing_nums.push_back(nums[0]); + for (int i = 1; i < nums.size(); i++) { + if (nums[i] > increasing_nums.back()) { + increasing_nums.push_back(nums[i]); + continue; + } + // find first larger or equal num + int index = FindFirstLargerOrEqualIndex(increasing_nums, nums[i]); + increasing_nums[index] = nums[i]; + } + + return increasing_nums.size(); + } + +private: + int FindFirstLargerOrEqualIndex(vector& nums, int target) { + int left = 0; + int right = nums.size(); + + while (left < right) { + int middle = left + (right - left) / 2; + if (nums[middle] < target) { + // middle の値がターゲットより小さい場合、 + // ターゲットは middle の右側にある可能性がある。 + // したがって、探索範囲を [middle + 1, right) に絞る + left = middle + 1; + } else { + // middle の値がターゲット以上の場合、 + // middle は答えの候補であるか、ターゲットは middle の左側にある可能性がある。 + // したがって、探索範囲を [left, middle) に絞る。 + right = middle; + } + } + return left; + } +}; diff --git a/300.LongestIncreasingSubsequence/memo.md b/300.LongestIncreasingSubsequence/memo.md new file mode 100644 index 0000000..55f1de0 --- /dev/null +++ b/300.LongestIncreasingSubsequence/memo.md @@ -0,0 +1,52 @@ +## ステップ1 +思いついたのは愚直にループを回しながら頭からみていく方法と +頭から1歩ずつ進んでいき、地点ごとの最大距離をメモ化する + +メモ化のロジックを、形で覚えてしまっている感がある +15分ほどでaccept + +時間計算量 +O(n^2) + +空間計算量 +O(n) + +## ステップ2 +・メモ化のvectorの名前をmemoizationから変更 + +## 他の解法 +binary_searchでも解くことができる +https://github.com/Yoshiki-Iwasa/Arai60/pull/46/commits/56e8cf4d4efc42c5784108191d1e5fc615de9206 + +こちらも二分探索 +他にもBitとセグメント木というものがある(名前を聞いたことがあるようなないような。。。) +ぱっと見「アルゴリズムイントロダクション」に載っていない? +https://github.com/fhiyo/leetcode/pull/32/commits/4ddb934198ff85e6349b064edea5fe312bd27b9c + +基本方針はみなさんメモ化かな、二分探索もできた方がいいか +https://github.com/SuperHotDogCat/coding-interview/pull/28/commits/b81e3d1929c84abea2f00ef3b20b5a34b79eec38 +https://github.com/sakupan102/arai60-practice/pull/32 + +マジックナンバーについて +> 入力の制約を守らない入力を入れると、理解できない振る舞いをするんですよね。 +> 数年間使うコードならば、そういうことは間違いなく起きますよね。 +制約値よりは、std::numeric_limits::min()とstd::numeric_limits::max()を使うか +https://github.com/Exzrgs/LeetCode/pull/18 + +## 二分探索 +binary_search.cppに実装 +numsの中の最小値に出会うたびに先頭から入れ替えが走る +入れ替え後から大きな数が現れると要素が後ろに追加される + +https://en.cppreference.com/w/cpp/algorithm/lower_bound +時間計算量 +O(n log n) +要素数がnでそのループ内のlower_boundがlog n + +空間計算量 +O(n) + +メモ:下記のケースを使うと理解しやすい +{10, 9, 2, 5, 3, 7, 101, 18, 1, 2, 3, 4, 5, 6, 7, 8} + + diff --git a/300.LongestIncreasingSubsequence/step1.cpp b/300.LongestIncreasingSubsequence/step1.cpp new file mode 100644 index 0000000..ae41198 --- /dev/null +++ b/300.LongestIncreasingSubsequence/step1.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + vector memoization(nums.size(), 1); + + int max_length = 0; + for (int i = 0; i < nums.size(); i++) { + for (int j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + memoization[i] = max(memoization[i], memoization[j] + 1); + } + } + max_length = max(max_length, memoization[i]); + } + + return max_length; + } +}; diff --git a/300.LongestIncreasingSubsequence/step2.cpp b/300.LongestIncreasingSubsequence/step2.cpp new file mode 100644 index 0000000..ace8598 --- /dev/null +++ b/300.LongestIncreasingSubsequence/step2.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + vector longest_lengths(nums.size(), 1); + + int max_length = 0; + for (int i = 0; i < nums.size(); i++) { + for (int j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + longest_lengths[i] = max(longest_lengths[i], longest_lengths[j] + 1); + } + } + max_length = max(max_length, longest_lengths[i]); + } + + return max_length; + } +}; diff --git a/300.LongestIncreasingSubsequence/step3.cpp b/300.LongestIncreasingSubsequence/step3.cpp new file mode 100644 index 0000000..2fe6d03 --- /dev/null +++ b/300.LongestIncreasingSubsequence/step3.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + vector longest_lengths(nums.size(), 1); + + int max_length = 0; + for (int i = 0; i < nums.size(); i++) { + for (int j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + longest_lengths[i] = max(longest_lengths[i], longest_lengths[j] + 1); + } + } + + max_length = max(max_length, longest_lengths[i]); + } + + return max_length; + } +}; diff --git a/300.LongestIncreasingSubsequence/step4.cpp b/300.LongestIncreasingSubsequence/step4.cpp new file mode 100644 index 0000000..d1494b1 --- /dev/null +++ b/300.LongestIncreasingSubsequence/step4.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + vector longest_lengths(nums.size(), 1); + + int max_length = 0; + for (int i = 0; i < nums.size(); i++) { + for (int j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + longest_lengths[i] = max(longest_lengths[i], longest_lengths[j] + 1); + } + } + + max_length = max(max_length, longest_lengths[i]); + } + + return max_length; + } +}; diff --git a/problem_name/step1.cpp b/problem_name/step1.cpp index e69de29..1a2d55c 100644 --- a/problem_name/step1.cpp +++ b/problem_name/step1.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + if (nums.empty()) { + return 0; + } + vector increasing_nums; + increasing_nums.push_back(nums[0]); + for (int i = 1; i < nums.size(); i++) { + if (nums[i] > increasing_nums.back()) { + increasing_nums.push_back(nums[i]); + continue; + } + // find first larger or equal num + int greater_or_equal_index = 0; + while (nums[i] > increasing_nums[greater_or_equal_index]) { + greater_or_equal_index++; + } + increasing_nums[greater_or_equal_index] = nums[i]; + } + + return increasing_nums.size(); + } +};