Skip to content

Conversation

@t-ooka
Copy link
Owner

@t-ooka t-ooka commented Jul 2, 2024

@t-ooka t-ooka changed the title Question/longest consecutive sequence 128. Longest Consecutive Sequence Jul 2, 2024
num_to_index = {}

for i in range(0, len(nums)):
num_to_index[nums[i]] = i
Copy link

Choose a reason for hiding this comment

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

num_to_index のバリューは最後まで使われていないですね。
set が思いつかなかったとしたら、num_to_index[nums[i]] = None などとすると、インデックスを使わないことのシグナルになると思います。

以下は set の内部実装に関して見つけたものです。
https://stackoverflow.com/questions/3949310/how-is-set-implemented

Copy link
Owner Author

Choose a reason for hiding this comment

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

レビュー頂き誠にありがとうございます。
step1で解法思いつかず試行錯誤してたところで使われていない値があることに気づけていませんでした。こういった点意識して再度コーディングをしてみます!


for key in num_to_index.keys():
count = 1
while key+1 in num_to_index:
Copy link

Choose a reason for hiding this comment

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

算術演算子の周りにスペースを入れるかどうかは、PEP8のサンプルを見る限りどちらでもいいみたいです。ひとつのPRで混ざっていると、なにか使い分けがあるのかな?と少し注意が向くのでどちらかに統一してあるといいかもです。
https://peps.python.org/pep-0008/#other-recommendations
discord のログには次のような議論が見つかりました。他の方がどのような判断をしているかの参考までに。
見た目が窮屈になるときに開けるかどうか:https://discord.com/channels/1084280443945353267/1225849404037009609/1254109293091881052

Copy link
Owner Author

Choose a reason for hiding this comment

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

算術演算子周りのスペースについて別のところでもご指摘を頂いておりました。ご指摘を頂く前にやったコーディングでごちゃごちゃになってしまってたと思います。今後はスペースを空ける方向で統一しようと思います。

class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int>num_set(nums.begin(), nums.end());
Copy link

@sakzk sakzk Jul 3, 2024

Choose a reason for hiding this comment

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

自分はC++で書いていないので詳しくは知らないのですが、set関連のデータ構造はいろいろあるようです。
Ryotaro25/leetcode_first60#14 (comment)

内部実装、各種操作の計算量がPythonと異なる点も意識が必要と思われます。
Ryotaro25/leetcode_first60#14 (comment)

上記読む限り、vector を unorderd_set に変換する操作は O(n) で実行できなさそうです。

Choose a reason for hiding this comment

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

ハッシュセット・ハッシュテーブルへの挿入は、O(1)と考えて問題ないかと思います。

while num+length in num_set:
length+=1

longest = max(length, longest)
Copy link

Choose a reason for hiding this comment

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

これは好みの問題ですが、自分は上下のスペースは削ったほうが見やすく感じます。

Copy link
Owner Author

Choose a reason for hiding this comment

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

好みのところでご意見いただけること、とても参考になります。ありがとうございます!


for ( auto &n: nums) {
if (!num_set.contains(n-1)) {
int length = 1;
Copy link

@sakzk sakzk Jul 3, 2024

Choose a reason for hiding this comment

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

nums の要素の値の元の型は、関数の引数まで読み返さないとわからないので、&n の型を int に明示して、int length と揃えてもいいのかなと思いました。

一応、nums の要素数が大きい場合に、length がオーバーフローしないかは気になりました。だいたい 2* 10^9でオーバーフローしますが、扱うデータの大きさによってはあり得る状況かなと思います。(暗黙の型変換などされるのでしょうか?)

以下、int型の取りうる範囲についての参照リンクです。
https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170
https://en.cppreference.com/w/cpp/types/climits

@@ -0,0 +1,14 @@
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
num_set = set(nums)
Copy link

Choose a reason for hiding this comment

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

変数名 nums_set は、自分の場合は「集合だから重複は含まれていないんだな」と一段回思考を挟むことがあります。unique_nums とかもありだと思います。

def longestConsecutive(self, nums: List[int]) -> int:
num_set = set(nums)

longest_consecutive_sequence = 0
Copy link

Choose a reason for hiding this comment

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

変数名 longest_consecutive_sequence からは、何らかの連続そのものを想起します。
長さの最大値を保存する変数の名前としてはlongest_length, max_length あたりが良いのではないかと思います。
名前のスコープがもっと長いなら longest_consecutive_sequence_length も選択肢になるかもしれません。
(調べた限りでは、sequence に 「長さ」の意味は見つけられませんでした。
https://dictionary.cambridge.org/dictionary/english/sequence
命名に使う英単語を辞書を引いてみることは、自分もよくやっているのですがおすすめです。変数名に使う英語はそれほどパターンが多くないのでだんだん網羅されている感じがあります。)


longest_consecutive_sequence = 0

for num in nums:
Copy link

Choose a reason for hiding this comment

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

すでに検討されていたなら申し訳ないのですが、step1 とstep4の時間計算量、空間計算量は見積りましたか?

@@ -0,0 +1,13 @@
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
nums_set = set(nums)
Copy link

Choose a reason for hiding this comment

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

おまけ問題として、重複も連続として数えるとした場合にどのように変更するか考えてみるのも面白いかもです。

unordered_set nums_set(nums.begin(), nums.end());
int longest_consecutive_sequence = 0;

for ( auto num: nums_set) {
Copy link

Choose a reason for hiding this comment

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

すでにご存知でしたら申し訳ないのですが、参照渡しをするか、コピーをするか、コピーする場合はコストがかかることを意識しているかに関して discord 上で以下のような議論がありました。ご参考までに。
C++の例:https://discord.com/channels/1084280443945353267/1237649827240742942/1251719996242002043
pythonの例:
hrkh/leetcode#2 (comment)

Copy link

Choose a reason for hiding this comment

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

これ、int の場合は大きさが32ビットで、あんまりリファレンスにする必要は感じません。コピーコストが安いからですね。

unordered_set nums_set(nums.begin(), nums.end());
int longest_consecutive_sequence = 0;

for ( auto num: nums_set) {
Copy link

Choose a reason for hiding this comment

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

フォーマットに関して discord 内でよく引用されている印象がある google C++ style guide では、for ()() 前後にスペースを入れない書き方が推奨されていました。
https://google.github.io/styleguide/cppguide.html#Formatting_Looping_Branching

Choose a reason for hiding this comment

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

色々なところでスペースがあったりなかったり一貫性がないのが気になりますね。普通は開きカッコの後ろにスペースを入れるなら、閉じカッコの前にも入れるかと思います。sakzkさんのコメントのようにない方が一般的かと思います。

unordered_set nums_set(nums.begin(), nums.end());
int longest_consecutive_sequence = 0;

for ( auto num: nums_set) {

Choose a reason for hiding this comment

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

色々なところでスペースがあったりなかったり一貫性がないのが気になりますね。普通は開きカッコの後ろにスペースを入れるなら、閉じカッコの前にも入れるかと思います。sakzkさんのコメントのようにない方が一般的かと思います。

class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> num_set(nums.rbegin(), nums.rend());

Choose a reason for hiding this comment

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

どうしてreverse_iteratorですか?

if (!num_set.contains(n-1)) {
int length = 1;
while (num_set.contains(n + length)) {
length += 1;

Choose a reason for hiding this comment

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

++length;

class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int>num_set(nums.begin(), nums.end());

Choose a reason for hiding this comment

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

ハッシュセット・ハッシュテーブルへの挿入は、O(1)と考えて問題ないかと思います。

class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set nums_set(nums.begin(), nums.end());

Choose a reason for hiding this comment

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

ここだけtemplate argument deductionを使っていますが、意識してやっていますか?

nums_set = set(nums)
longest_consecutive_sequence = 0

for num in nums_set:
Copy link

Choose a reason for hiding this comment

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

なんとなく不自然さを感じます。つまり、手でやるとして、{0, 1, 2, 3, 4, 5} だったとして、0 から確認が終わった後に 1 を確認しないじゃないですか。

@t-ooka
Copy link
Owner Author

t-ooka commented Jul 5, 2024

@sakzk @liquo-rice @oda
レビューいただき本当にありがとうございます。一個一個確認していってますのでまばらな返信についてはお許しください 🙇

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.

5 participants