見た 数を 集合に 覚え、 桁の 2 乗の 和を 繰り返して 1 に 着くかを確かめる
正の
海外で定番の問題リスト 4 本には入っていません
問題
数遊びのn を
- 1 に
着いたら、 そこで 止めて 真とします (1 を 置き換えても 1 のままです) nは 1 以上 2147483647 以下です
入力と出力の例
例 1
28 は 68、
例 2
11 は 2、
例 3
7 は 49、
面接での聞かれ方
面接では、
- 「この
操作を 繰り返して 1 に なるかを 返してください」 - 書き始めると
「1 に ならない とき、 いつ 止めますか?」と 聞かれます - 書き終えた
あとに 「集合を 使わずに、 記憶 O(1) で 書けますか?」と 続く ことがあります
芯は、
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
まずは 1 回分のn % 10 でn を 10 でn が 0 に
段 2
次の
段 3
見た
解答
Python
Python
def next_num(n):
total = 0
while n > 0:
d = n % 10
total += d * d
n //= 10
return total
def is_happy(n):
seen = set()
while n != 1:
if n in seen:
return False
seen.add(n)
n = next_num(n)
return TrueJavaScript
JavaScript
function nextNum(n) {
let total = 0;
while (n > 0) {
const d = n % 10;
total += d * d;
n = Math.floor(n / 10);
}
return total;
}
function isHappy(n) {
const seen = new Set();
while (n !== 1) {
if (seen.has(n)) {
return false;
}
seen.add(n);
n = nextNum(n);
}
return true;
}Go
Go
func nextNum(n int) int {
total := 0
for n > 0 {
d := n % 10
total += d * d
n /= 10
}
return total
}
func isHappy(n int) bool {
seen := map[int]bool{}
for n != 1 {
if seen[n] {
return false
}
seen[n] = true
n = nextNum(n)
}
return true
}JavaScript の / はMath.floor で
計算量
- 1 回の
置き換えは、 桁の 数だけの 手間で O(log n) です - 2 回目からの
数は どれも 810 以下なので、 繰り返しの 回数は 810 回ほどで 頭打ちに なります。 全体の 時間は O(log n) と 見てかまいません - 使う
記憶は、 集合に 入る 数の 分です。 これも 810 個ほどで 頭打ちです - 集合の
代わりに、 1 歩ずつ 進む数と 2 歩ずつ 進む数を 追い かける 書き方 (遅いのと 速いのが 輪の 中で 出会う ) に すると、 記憶は O(1) になります
よく ある間違い
- 止める
条件を 書かない。 1 に 着くまで 回すだけだと、 例 2 のような 数で いつまでも 終わりません - 回数で
打ち切る。 「100 回で 着かなければ 偽」のように 決め打ちすると、 なぜ その 回数で 足りるのかを 説明できません。 同じ数に 戻ったかで止めます - 桁の 2 乗を
n % 10 ** 2と書く。 Python では**が先に 計算されるので、 n % 100になってしまいます。 桁を dに取り出してから d * dを足します - JavaScript で
n / 10をそのまま使う。 商が 小数に なり、 桁を 取り出す繰り返しが 正しく 終わりません
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「次の
数は 今の 数だけで 決まるので、 同じ数に もう 一度来たら、 その先は 輪を 回り続けます。 見た 数を 集合に 覚えて、 1 に 着いたら真、 見た ことの ある 数に 来たら 偽を 返します。 2 回目からの 数は 810 以下に 収まるので、 繰り返しは 頭打ちに なります。」
書き終えたら、
「例 1 の 28 を
たどります。 4 と 64 で 68、 36 と 64 で 100、 1 と 0 と 0 で 1 です。 1 に 着いたので 真を 返します。」