Skip to content

347. Top K Frequent Elements#16

Merged
ryoooooory merged 15 commits intomainfrom
task/347
Jul 21, 2024
Merged

347. Top K Frequent Elements#16
ryoooooory merged 15 commits intomainfrom
task/347

Conversation

@ryoooooory
Copy link
Copy Markdown
Owner

Copy link
Copy Markdown

@hayashi-ay hayashi-ay left a comment

Choose a reason for hiding this comment

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

良いと思います。quickselectのpivotの選択は、真ん中の値を取る以外にも乱択や3 median(先頭、真ん中、末尾のメジアン)などもあります。

https://en.wikipedia.org/wiki/Quicksort#Choice_of_pivot

@hayashi-ay
Copy link
Copy Markdown

Issueのタイトルでどの問題かが分かるかがタイトルも含めてあると良いかなと思いました。

他の人のレビューをみてみると関連知識としてQuickSelectの解法もあったので、勉強のためにそちらでも解いてみた。
https://github.com/Ryotaro25/leetcode_first60/pull/10#discussion_r1627890286
以前他の問題でもQuickSelectをやっていたがまだ身に付いてはいなかったので実装に15分ほど時間がかかってしまった。
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.

Java を使う場合は、TreeMap も見ておいてください。私は、PriorityQueue よりもこちらのほうが大事な感覚があります。Key が順番に並んでいます。
https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html

Comment on lines +22 to +28
if (pivotIndex == target) {
return;
} else if (pivotIndex < target) {
left = pivotIndex + 1;
} else {
right = pivotIndex - 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.

好みの問題ですが、pivotIndex == target のケースだけ終了条件になっているので、そこだけ別の if 文にしてもいいかなとおもいました。


private void quickSelect(int left, int right, List<Map.Entry<Integer, Integer>> frequency, int target) {
while(left < right) {
int pivotIndex = left + (right - left) / 2;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

pivotIndex を算出する方法はこれ以外にもいくつかあるので、もしご存知なければ他の方の解答等を見て把握しておくと良いと思いました。それらを踏まえた上で、なぜこの方法を選ぶのかというのが意識できていると素晴らしいと思います!

storeIndex++;
}
}
Collections.swap(frequency, storeIndex, right);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Collections.swap() 知りませんでした。勉強になります!✍️

Comment on lines +11 to +14
minCountAndNums.add(entry);
if (k < minCountAndNums.size()) {
minCountAndNums.poll();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

k 個既に要素がある場合、一番頻度が低い要素よりも entry の頻度がさらに低い場合スキップすれば、ケースによっては処理時間を結構減らせそうです

@seal-azarashi
Copy link
Copy Markdown

バケットソートを用いて計算量 O(n) で実装する方法もあります。他の方のプルリクにあったと思うので、目を通しておいても損はないと思います。

@hayashi-ay
Copy link
Copy Markdown

↑ Pythonですが自分Bucket Sortでも解いてます。https://github.com/hayashi-ay/leetcode/pull/60/files

numToCount.put(num, numToCount.getOrDefault(num, 0) + 1);
}

List<Map.Entry<Integer, Integer>> frequency = new ArrayList<>(numToCount.entrySet());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Map.Entry を pair や tuple の代わりに使っている点に違和感を感じました。クラスを定義し、クラスのインスタンスのリストとしたほうが良いと思います。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Java 16 で正式リリースされた Record の使用もおすすめします。
https://docs.oracle.com/en/java/javase/17/language/records.html

@ryoooooory ryoooooory changed the title Task/347 347. Top K Frequent Elements Jul 9, 2024
Copy link
Copy Markdown

@Yoshiki-Iwasa Yoshiki-Iwasa left a comment

Choose a reason for hiding this comment

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

みました!

Comment on lines +11 to +15
Collections.sort(elements);
int[] topKFrequentElements = new int[k];
for(int i = 0; i < k; i++) {
topKFrequentElements[i] = (int)elements.get(elements.size() - i - 1).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.

降順ソートしてelements[i].valueで抜き出した方が自然だと思います

Comment on lines +54 to +56
for (int i = 0; i < k; i++) {
topKFrequentElements[i] = (int) numToCountQueue.poll().getKey();
}
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でも問題ありませんが、iterator を使っても良さそうです

  • for文より条件と処理を簡潔に書ける
  • 仮にnumsがk以下でも安全に動作する

などのメリットがあると思いました

@ryoooooory ryoooooory merged commit 0f3e08a into main Jul 21, 2024
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