-
Notifications
You must be signed in to change notification settings - Fork 0
300. Longest Increasing Subsequence #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| // least increasing order | ||
| vector<int> 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(); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| vector<int> 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(); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| vector<int> 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<int>& 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; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| ## ステップ1 | ||
| 思いついたのは愚直にループを回しながら頭からみていく方法と | ||
| 頭から1歩ずつ進んでいき、地点ごとの最大距離をメモ化する | ||
|
|
||
| メモ化のロジックを、形で覚えてしまっている感がある | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この解法はDPのテーブルを埋めているだけでメモ化ではないような気がします。 https://en.wikipedia.org/wiki/Memoization
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. longest_lengths[j] + 1の部分が、過去に入力されたデータを使っているイメージだったのですが再帰呼び出しの関数の結果を保存していることなのですね。誤って認識しておりました🙇 |
||
| 15分ほどでaccept | ||
|
|
||
| 時間計算量 | ||
| O(n^2) | ||
|
|
||
| 空間計算量 | ||
| O(n) | ||
|
|
||
| ## ステップ2 | ||
| ・メモ化のvectorの名前をmemoizationから変更 | ||
|
|
||
| ## 他の解法 | ||
| binary_searchでも解くことができる | ||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/46/commits/56e8cf4d4efc42c5784108191d1e5fc615de9206 | ||
|
|
||
| こちらも二分探索 | ||
| 他にもBitとセグメント木というものがある(名前を聞いたことがあるようなないような。。。) | ||
| ぱっと見「アルゴリズムイントロダクション」に載っていない? | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ソフトウェアエンジニアの常識から微妙に外れていると思います。知っている人は多いけれども、知らなくても別に動揺されないものです。 |
||
| 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} | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| vector<int> 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]) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. iとjの位置関係が分かりにくく感じました。 |
||
| memoization[i] = max(memoization[i], memoization[j] + 1); | ||
| } | ||
| } | ||
| max_length = max(max_length, memoization[i]); | ||
| } | ||
|
|
||
| return max_length; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| vector<int> 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; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| vector<int> 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; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| vector<int> 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; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| class Solution { | ||
| public: | ||
| int lengthOfLIS(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| vector<int> 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(); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/Yoshiki-Iwasa/Arai60/pull/46/files/56e8cf4d4efc42c5784108191d1e5fc615de9206#r1716128766
他のPRでたしかに、と思う議論があったので貼っておきます。厳密にはこれはLISではないという話です
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fhiyo
レビューありがとうございます。
この辺りですね。確かに中身を追っていくと一致しないので命名難しいです。