全部を XOR でまとめ、1 回だけ出てくる値を見つける

1 つを除いてどの値もちょうど 2 回ずつ出てくる並びから、1 回だけ出てくる値を返します。同じ値どうしの XOR は 0 になるので、全部を XOR でまとめれば対の値が消えて 1 つだけ残る練習です。

海外で定番の問題リスト 4 本には入っていません

問題

靴の倉庫で、左右の対になった靴に同じ番号を振っています。番号の並び nums を受け取ります。1 つの番号を除き、どの番号もちょうど 2 回ずつ出てきます。片方しか無い靴の番号、つまり 1 回だけ出てくる値を返す関数を書いてください。

  • 時間は O(n)、追加の記憶は O(1) を目指してください
  • nums の長さは 1 以上 30000 以下の奇数、値はどれも -30000 以上 30000 以下です

入力と出力の例

例 1

nums = [7, 3, 5, 3, 7]
5

例 2

並びが 1 つだけなら、その値が答えです。

nums = [12]
12

例 3

負の数と 0 も入ります。

nums = [-4, 0, 9, -4, 9]
0

面接での聞かれ方

面接では、ビット演算の入り口として短く出されることが多い問題です。

  • 「1 つだけ対になっていない数を返してください」
  • 辞書で数える書き方を見せると、「追加の記憶を使わずにできますか?」と続きます
  • 「3 回ずつ出てくる中から 1 つを探すなら?」と、続きを聞かれることもあります

XOR の性質を知っていて、それを理由とともに説明できるかが見られています。

ヒント

まだ開いていません

付箋は 3 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3答えに近い

アルゴリズムのチートシートの「配列と文字列」に、この型の要点を表とコードでまとめています。

配列と文字列の問題は、全部の組を調べると手間が大きくなる所を、窓や左右の添字で減らす形が多いです。

main.py
def single_number(nums: list[int]) -> int:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(single_number([7, 3, 5, 3, 7]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します