Skip to content

703_Kth_Largest_Element_in_a_stream追加#1

Open
haniwachann wants to merge 4 commits intomasterfrom
03_heap_priorityque
Open

703_Kth_Largest_Element_in_a_stream追加#1
haniwachann wants to merge 4 commits intomasterfrom
03_heap_priorityque

Conversation

@haniwachann
Copy link
Copy Markdown
Owner

@haniwachann
Copy link
Copy Markdown
Owner Author

初めての投稿です。
Cs初心者なので、コーディング、調べ方、勉強の仕方など誤りがあったら教えていただけると嬉しいです。
よろしくお願いします。

Comment on lines +16 to +17
vector<int> scores;
int kth;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

外からアクセスが想定されていないものは private に。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

以前野田さんにおすすめされたのですが、「effective c++」にこの辺りのことが記載されておりますので読んでみるといいと思いました。

Comment on lines +20 to +22
scores=nums;
sort(scores.rbegin(),scores.rend());
kth=k;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

スペースの空け方のルールはなにか統一的なものがあればなんでもいいと思います。
Google Style Guide は一つです。
https://google.github.io/styleguide/cppguide.html

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.

ありがとうございます。
リンク参考にさせていただきます。
違和感を持たれないようにコードを書くことを心がけます。

Comment on lines +28 to +32
if((int)size(scores)>kth){
return scores[kth-1];
}else{
return scores[kth-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.

これ、条件分岐して同じ式ですね。それだったらまとめていいですが、なんか意図があったんじゃないでしょうか。全体の大きさを小さくするとか。kth より多いときには減らせますね。

(int) もこの場合は不要ですかね。

Copy link
Copy Markdown
Owner Author

@haniwachann haniwachann Nov 9, 2024

Choose a reason for hiding this comment

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

すみません。
vectorの要素数がkthよりも大きいことが前提ならば必要ないですが、vectorの要素数がkthより小さいときはエラーを知らせるように書こうとしてました。

教えていただいた通り、vectorの長さを減らすようにします!

if(canditates.count(nums[i])!=0){
canditates[nums[i]]++;
}else{
canditates[nums[i]]=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.

ない場合でも、アクセスするだけで作られて0になります。

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.

https://cpprefjp.github.io/reference/map/map/op_at.html
「対応する要素が存在しない場合は、要素を値初期化して参照を返す。」
そうですね。とりあえず、読みましょう。
だから canditates[nums[i]]++; だけでいいですね。

Comment on lines +81 to +85
if(canditates.begin()->second==1){
canditates.erase(canditates.begin());
}else{
canditates.begin()->second--;
}
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を引いて、0以下になっていたら消すという方法もあります。

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.

ありがとうございます。
条件分岐のelseが1つ減ってわかりやすくなりそうです。

Comment on lines +104 to +106
auto iter=canditates.begin();
int ans= iter->first;
return ans;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

これくらいならば一行でもいいでしょう。

}
}

for(int i=k;i<(int) size(nums);i++){
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

なんだかfor, if, else文のスペースの開け方に違和感を感じてしまいます.
https://ttsuki.github.io/styleguide/cppguide.ja.html#Formatting_Looping_Branching
こちらにGoogle Coding Style Guideのifのスペースの開け方があります

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.

違和感を教えていただきありがとうございます。
いただいたリンクに目を通して、少しずつ修正していきます!


今度は、時間を測りながら、もう一回、書きましょう。書いてアクセプトされたら文字消してもう一回書く。これを10分以内に一回もエラーを出さずに書ける状態になるまで続ける。3回続けてそれができたらその問題はOK。

実施しました。 No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

他の人はstep3も載せているので載せちゃうといいと思います


実施しました。 No newline at end of file
実施しました。

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.

step4として、レビューを受けてコードを修正いたしました。

class KthLargest {
public:

map<int,int> canditates;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

multimap を使っても同様の処理が書けると思います。余裕があれば挑戦してみてください。

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.

ありがとうございます。
multimapを使用する場合は、keyを問題で与えられた値として、keyの値がmultimap全体の中で何個目であるかを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.

いえ、 multipmap の要素数が k を超えるたびに、一番小さい値を削除していくことになると思います。

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.

multimapではkey,valueともに同じものが複数存在できるという理解でいいでしょうか。
https://cpprefjp.github.io/reference/map/multimap.html

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

しまった…。書き間違えました…。 multiset のほうでした…。

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.

multiset教えていただきありがとうございます!
実装のイメージつきました!

class KthLargest {
public:

map<int,int> canditates;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらはcandidateの誤りでしょうか?

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.

スペルミスです🙏

}

auto iter=canditates.begin();
int ans= iter->first;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ansだと何が格納されているのか分からないので、変数名から何が入っているのか分かるような変数名がいいと思いました。

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.

ありがとうございます。
kth_numとかがいいかと思いました。

Comment on lines +177 to +181
canditates[nums[i]]++;
canditates.begin()->second--;
if (canditates.begin()->second<=0) {
canditates.erase(canditates.begin());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

L185-189とほとんど同じです。関数に切り出せますか?

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.

ありがとうございます。
privateに関数を追加して処理をまとめました。

class KthLargest {
private:
    map<int,int> candidates;
    int kth;
    void add_num_to_candidates(int nums_add){
        candidates[nums_add]++;
        candidates.begin()->second--;
        if (candidates.begin()->second<=0) {
            candidates.erase(candidates.begin());
        }
    }
public:
    KthLargest(int k, vector<int>& nums) {
        kth=k;

        for (int i=0; i<k; i++) candidates[nums[i]]++;
        for (int i=k; i<size(nums); i++) add_num_to_candidates(nums[i]);
    }
    int add(int val) {
        add_num_to_candidates(val);
        return candidates.begin()->first;
    }
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

下のテストケースがパスしないようです。

["KthLargest","add","add","add","add","add"]
[[1,[]],[-3],[-2],[-4],[0],[4]]

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.

初期配列が空だと
for (int i=0; i<k; i++) candidates[nums[i]]++;
のnums[i]で存在しない要素を呼び出していて、エラーが出るようでした。
for文の実行条件をi<k && i<size(nums)に修正しました。

また、add_num_to_candidatesの中で、配列の数がkthに満たない場合も
加えた値を削除してしまっていたので、candidates_counterの変数を用意して、
要素数がkthより大きい時のみ、削除する処理をするように条件分けしました。

class KthLargest {
private:
    map<int,int> candidates;
    int candidates_counter=0;
    int kth;
    void add_num_to_candidates(int nums_add){
        candidates[nums_add]++;
        candidates_counter++;
        if (candidates_counter>kth) {
            candidates.begin()->second--;
            if (candidates.begin()->second<=0) {
                candidates.erase(candidates.begin());
            }
        }
    }
public:
    KthLargest(int k, vector<int>& nums) {
        kth=k;

        for (int i=0; i<k && i<size(nums); i++){
            candidates[nums[i]]++;
            candidates_counter++;
        }
        for (int i=k; i<size(nums); i++) add_num_to_candidates(nums[i]);
    }
    int add(int val) {
        add_num_to_candidates(val);
        return candidates.begin()->first;
    }
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

一回、自然言語にしてみるんですが、重複している感じがしませんか。
kth は、「この KthLargest のインスタンスがいくつまで管理するか」
candidates は、「大きいものから k 個(追加された数が k に満たない場合はすべて)の分布」
candidates_counter は、「消去したものも含めて追加された数」ですね。

add_num_to_candidates は、意味は「数字を追加して candidates の分布を更新」、操作としては「数字を追加し、k を超えていたら一番小さいのを消す」
KthLargest は、意味は「k と nums で初期化」、操作としては「入力の配列に対して、k 番目までは candidates を更新し、それ以降 add_num_to_candidates を呼ぶ」
add は、意味は「数字を追加して、k 番目に大きいものを返す」、操作としては「add_num_to_candidates を呼んで、k 番目を返す」

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

個人的には
KthLargest は add_num_to_candidates を nums に対して呼ぶのでよいでしょう。
add_num_to_candidates と add は一緒にしてしまうかもしれません。
candidates_counter は、意味を「中に入っている個数」にして消したら減らしたいです。

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.

変数、関数ともに自然言語にしてみると、
・addがadd_num_to_candidatesを呼んでるだけになっている。
・KthLargestのk番目とそれ以降で分けていることを、すでにadd_num_to_candidatesで処置している。
ことがよくわかります...

candidates_counterの変数の意味は中に入っている個数という意味で使いたかったのですが、
実装上は違う意味になっていました...
コードを頭の中でミスなく動かす練習をしていきたいです。

以下の通り直してみました。

class KthLargest {
private:
    map<int,int> candidates;
    int candidates_counter=0;
    int kth;

public:
    KthLargest(int k, vector<int>& nums) {
        kth=k;
        for (int i=0; i<size(nums); i++) add(nums[i]);
    }
    int add(int val) {
        candidates[val]++;
        candidates_counter++;
        if (candidates_counter>kth) {
            candidates.begin()->second--;
            if (candidates.begin()->second<=0) {
                candidates.erase(candidates.begin());
            }
            candidates_counter--;
        }
        return candidates.begin()->first;
    }
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

いいかと思います。
削除の際のcandidates.begin()は三回繰り返しているので変数においてもいいかもしれませんね。
他に気になるのは、スタイル(演算子の前後にスペースをいれるか、ぶら下がり for を使うか、インクリメント・デクリメントは前置が好きか、など)ですが、趣味の範囲です。

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.

6 participants