Skip to content

300. Longest Increasing Subsequence#31

Open
dxxsxsxkx wants to merge 1 commit into276_paint_fencefrom
300_longest_increasing_subsequence
Open

300. Longest Increasing Subsequence#31
dxxsxsxkx wants to merge 1 commit into276_paint_fencefrom
300_longest_increasing_subsequence

Conversation

@dxxsxsxkx
Copy link
Copy Markdown
Owner

longest_length = std::max(longest_length, memo_longest_lengths[i]);
}

return longest_length;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好みかもしれませんが、最後にmemo_longest_lengthsの最大値(一つの書き方としては*std::max_element(memo_longest_lengths.begin(), memo_longest_lengths.end())ですかね?AIに聞いてみたらC++20以降だとstd::ranges::maxというのもあるらしいです)を返すようにすれば、longest_lengthは消せると思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます!知らなかったので調べてきました。

  • std::max_element: first, last の範囲で最大値を返す。内部の動作はC++20以前は operator、以降は std::less() による。
  • std::ranges::max: より柔軟で、1. ab のより大きい方を返す、2. 初期化子リストの最大値を返す、3. 与えられた範囲の最大値を返す の使い方がある。

ここに使うかはちょっと様子見しようと思います。

- 最長の increasing subsequence の index を持つ increasing sequence を作る。
- 命名が悩ましいが、[ここ](https://github.com/mamo3gr/arai60/pull/29/changes#diff-99ef9dfc883fb81ff2f1ba8126bf45e8b41cf737c5540cd1ce53afd3e1e18049)で言及されている `min_tails` は良さそう。各長さの部分列の中で末尾が最小のものを保存しているので。
- `nums` の各要素につき、`std::lower_bound` でこのベクトルと比較する。大きな数が見つかったらベクトルの後ろに足す。
- [`std::lower_bound`](https://en.cppreference.com/w/cpp/algorithm/lower_bound.html)。`first`, `last` の区間の中で、`value` より前に並ばない最後の(?)要素を返す。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

「最初の」ではないでしょうか。value以上の(つまり、昇順にソートした時にvalueよりも前に来ないような)値が入っている最初のindexが返ると認識しています。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本当ですね。ありがとうございます。その通りです。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(自分が解いたときから)1ヶ月ぶりにこの解法を見てみたら、思い出すのに時間がかかりました。ぜひ時間を置いて見返してみてください。
初見の読み手では何をしているのか読み解くのに苦労しそうです。
min_tails の周辺にコメントで説明を付与する、it に情報を載せる、などの工夫があると親切だと思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。1ヶ月後に自分で見てわかるかどうかというのは良い基準だと思いました。

class Solution {
public:
int lengthOfLIS(std::vector<int>& nums) {
std::vector<int> memo_longest_lengths(nums.size(), 1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memo_longest_lengths が何を表しているのか、コメントで補足するとより丁寧だと思いました。「インデックス i 番目の要素(nums[i])を、増加部分列の末尾(最後)として使った場合の最大長」ですかね。

この変数が表すものと、メインループでの処理の意図の両方が分からないと読解の難易度がかなり上がるように感じました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants