見た数を集合に覚え、桁の 2 乗の和を繰り返して 1 に着くかを確かめる

正の整数を「各桁の 2 乗の和」に置き換える操作を繰り返し、いつか 1 に着くかを判定します。同じ数にもう一度来たら輪に入ったと分かるので、見た数を集合に覚えて止める練習です。

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

問題

数遊びのゲームで、正の整数 n を「各桁を 2 乗して足した数」に置き換える操作を繰り返します。たとえば 28 は 2² + 8² = 68 になります。この操作を繰り返して、いつか 1 に着くなら真、いつまでも 1 に着かないなら偽を返す関数を書いてください。

  • 1 に着いたら、そこで止めて真とします (1 を置き換えても 1 のままです)
  • n は 1 以上 2147483647 以下です

入力と出力の例

例 1

28 は 68、100、1 と進み、1 に着きます。

n = 28
true

例 2

11 は 2、4、16、37、58、89、145、42、20 と進み、また 4 に戻ります。4 から先は同じ並びを回り続け、1 には着きません。

n = 11
false

例 3

7 は 49、97、130、10、1 と進みます。1 桁の数でも、1 に着くものがあります。

n = 7
true

面接での聞かれ方

面接では、最初の 1 問として短く出されることが多い問題です。

  • 「この操作を繰り返して 1 になるかを返してください」
  • 書き始めると「1 にならないとき、いつ止めますか?」と聞かれます
  • 書き終えたあとに「集合を使わずに、記憶 O(1) で書けますか?」と続くことがあります

芯は、1 に着かない数は同じ数の輪を回り続けると気づくことです。「同じ数にもう一度来たら止める」と言えれば、あとは素直に書けます。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3答えに近い

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

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

main.py
def is_happy(n: int) -> bool:
    """
    Goal: 何を返すか

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

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

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


# 「実行」を押すと、この行の結果が出ます
print(is_happy(28))

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