Skip to content

Create TopKFrequentElements.md#15

Open
kt-from-j wants to merge 1 commit intomainfrom
TopKFrequentElements
Open

Create TopKFrequentElements.md#15
kt-from-j wants to merge 1 commit intomainfrom
TopKFrequentElements

Conversation

@kt-from-j
Copy link
Copy Markdown
Owner

今回解いた問題:
347. Top K Frequent Elements
次に解く問題:
373. Find K Pairs with Smallest Sums

Comment on lines +65 to +67
if (nums.length <= k) {
return nums;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nums.length <= kの場合でも、ユニーク化した配列を返してあげる方が仕様として親切だと思いました。

条件分岐をもう少し後にし、たとえば:

if (numToCount.size() <= k) {
    int[] all = new int[numToCount.size()];
    int i = 0;
    for (int key : numToCount.keySet()) all[i++] = key;
    return all;
}

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 +203 to +204
PriorityQueue<NumAndFrequency> topKNumToCountEntry
= new PriorityQueue<>(Map.Entry.comparingByValue());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PriorityQueue<NumAndFrequency>は誤植でしょうか。

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.

おっしゃる通りです。
PriorityQueue<Map.Entry<Integer, Integer>>が正しいです。。。
お恥ずかしい限りです。


## 解答
- Step1のPriorityQueueを使った実装とほぼ一緒
- `numToCountEntry`としているが、命名がいまいちな感じ
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

topKFrequencyHeapなどはどうでしょうか?

}

int[] result = frequentNums.stream()
.mapToInt(Map.Entry::getKey).toArray();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

メソッドチェーンを書く場合は、呼び出しごとに改行を入れたほうが、読み手にとって読みやすくなるかもしれません。

// 要素が一つしかない場合
if (left == right) return;

// (n - k)番目に頻度が高い値(kSmallestと一致する値)を選べればベストだが
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ピボットの選び方は色々とあるようです。調べてみることをおすすめします。

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.

ありがとうございます。少し調べてみました。

  • 先頭、末尾、中央などいずれかの位置にある要素の値を採用する
  • 乱数で適当に選択した要素の値を採用する
  • いくつか取り出した要素の中央値を採用する(median of threeなど)
  • 要素をいくつかのグループに分割し、それらの中央値の中央値を採用する(median of medians)

多くの場合は、ランダム/median of threeを使用し、超大規模データの場合はmedian of mediansを使用することもあると理解しました。

// (n - k)番目に頻度が高い値(kSmallestと一致する値)を選べればベストだが
// 分からないので、ピボットをランダムに選ぶ
Random random = new Random();
int pivotIndex = left + random.nextInt(right - left + 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.

細かいですがleft/rightにindexを付けてないのでこっちもpivotで良いかも知れません

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.

たしかに。統一されていないと実はindexではないのかと勘繰ってしまいますね。
統一するように心がけます。

.toArray(NumAndFrequency[]::new);

// 頻度の高い要素を配列の(n - k)番目からn番目に集める
quickselect(numAndFrequencies, 0, n - 1, n - 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.

欲しいのはtopKなので、個人的には引数としては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.

再帰で書くには今の引数の方が都合がよく、n-kを渡してしまいました。
でも、呼び出す人の気持ちを考えたらkを渡す方が直感的で親切ですね。
オーバロード的な感じで(array、left、right、k)を渡す関数を用意しておけばよかったです。


private void quickselect(NumAndFrequency[] numAndFrequencies, int left, int right, int kSmallest) {
// 要素が一つしかない場合
if (left == right) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

n - kが0以下の場合も早期returnしても良いかも知れません。

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.

4 participants