0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Set で一発解決!検索履歴の重複ワードを効率的に管理する方法

Posted at

PaizaのCランク問題「検索履歴」を解いていて、最初は Map でゴリ押ししようとしたけど、実は Set を使えばめちゃくちゃシンプルに書けると気づいた!

今回は、検索履歴の重複ワードを排除して、最適な履歴リストを作る方法を解説する。


📚 問題概要

与えられた検索ワードを以下のルールで管理しよう。

既に履歴にあるワードが再度入力された場合 → 履歴から削除し、先頭に追加。

履歴にないワードが入力された場合 → そのワードを履歴の先頭に追加。

すべての入力を処理した後の履歴を表示。


📚 入力例

5
book
candy
apple
book
candy

📃 出力例

candy
book
apple


❌ NG例: 配列だけでゴリ押ししたパターン

最初は Arrayincludes() を使って頑張ろうとした。

const rl = require('readline').createInterface({ input: process.stdin });
const lines = [];

rl.on('line', (input) => { lines.push(input); });

rl.on('close', () => {
    const N = Number(lines[0]);
    const words = [];
    
    for (let i = 1; i <= N; i++) {
        // 既にある場合は削除して追加
        if (words.includes(lines[i])) {
            words.splice(words.indexOf(lines[i]), 1);
        }
        words.unshift(lines[i]);
    }
    words.forEach(word => console.log(word));
});

❌ 問題点:

includes() の計算量が O(N) なので、大量データだと遅くなる。

splice() で要素削除すると、配列全体をシフトするためコストが高い。


✅ OK例: Set で最適化!

Set を使うことで、高速に重複チェックが可能!

const rl = require('readline').createInterface({ input: process.stdin });
const lines = [];

rl.on('line', (input) => { lines.push(input); });

rl.on('close', () => {
    const N = Number(lines[0]);
    const words = lines.slice(1).reverse(); // 逆順に取得
    const seen = new Set(); // 出力済みの単語を記録

    words.forEach(word => {
        if (!seen.has(word)) {
            console.log(word); //出力
            seen.add(word); //Setに追加
        }
    });
});

✅ 改善点:

Sethas() は O(1) で超高速チェック!

reverse() を使うことで、リストを逆順にし unshift() を使わずに済む。


📝 新しく学んだこと

Set で一瞬で重複チェック!

Set は 重複を許さない コレクション。だから has() で存在確認しつつ、重複なくデータを保存できる。
検索履歴の問題では、Set を使ってすでに出力した単語を記録し、二重出力を防いでいる!

reverse() で順番をひっくり返す!

配列の要素を 逆順に並び替える 便利メソッド。
検索履歴は「最後に入力した単語が先に出る」から、reverse() で逆順にして処理するのがポイント!

unshift() で配列の先頭に追加!

push() が末尾に追加するのに対して、unshift() は 先頭に追加する。
ただし unshift() は 配列全体をずらす から、大量データには向かない!


🔍 まとめ

Set を使えば、O(1) の高速な重複チェックができる!
reverse() で履歴を逆順にすれば unshift() を使わずスッキリ!

検索履歴を管理する問題を通して、 データ構造の選び方でパフォーマンスが大きく変わる ことを学んだ!


僕の失敗談と解決話!

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?