筆算の 位ごとの 置き場に 積を 足し、 数字の 文字列どうしを掛ける
10 進の
海外で定番の問題リスト 4 本には入っていません
問題
電卓のa と b を
- 数の
型や 大きい整数の 型 (Python の int()、JavaScript の BigInt、Go の math/bigなど) に 直さず、 桁ごとに 計算してください aとbは数字だけで できていて、 "0"のときを 除き先頭は "0"ではありません - 答えも、
"0"のときを 除き先頭に "0"を付けません aとbの長さは 1 以上 200 以下です
入力と出力の例
例 1
例 2
どちらかが 0 なら、"0" です。"000" に
例 3
途中に 0 の
面接での聞かれ方
面接では、
- 「文字列で
渡された 2 つの 数を 掛けてください。 整数に 変換してはいけません」 - 筆算のように、
段ごとの 足し算を 作ってから 全部を 足す 書き方を 見せると、 「途中の 文字列を 作らずに できますか?」と続きます - 「答えは
最大で 何桁に なりますか?」と 聞かれる こともあります
芯は、a の i 桁目と b の j 桁目の
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
小学校のb の 1 a に
段 2
m 桁と n 桁のpos をa の i 番目 (左から 0 でb の j 番目のpos の i + j + 1 番目に
段 3
i と j をpos[i + j + 1] をs をs のpos[i + j + 1] にpos[i + j] に"0" を
解答
Python
Python
def multiply_strings(a, b):
m, n = len(a), len(b)
pos = [0] * (m + n)
for i in range(m - 1, -1, -1):
x = ord(a[i]) - 48
for j in range(n - 1, -1, -1):
y = ord(b[j]) - 48
s = x * y + pos[i + j + 1]
pos[i + j + 1] = s % 10
pos[i + j] += s // 10
k = 0
while k < m + n - 1 and pos[k] == 0:
k += 1
return "".join(
str(d) for d in pos[k:]
)JavaScript
JavaScript
function multiplyStrings(a, b) {
const m = a.length;
const n = b.length;
const pos = new Array(m + n).fill(0);
for (let i = m - 1; i >= 0; i--) {
const x = a.charCodeAt(i) - 48;
for (let j = n - 1; j >= 0; j--) {
const y = b.charCodeAt(j) - 48;
const s = x * y + pos[i + j + 1];
pos[i + j + 1] = s % 10;
pos[i + j] += Math.floor(s / 10);
}
}
let k = 0;
while (
k < m + n - 1 &&
pos[k] === 0
) {
k++;
}
return pos.slice(k).join("");
}Go
Go
func multiplyStrings(
a, b string,
) string {
m, n := len(a), len(b)
pos := make([]int, m+n)
for i := m - 1; i >= 0; i-- {
x := int(a[i] - '0')
for j := n - 1; j >= 0; j-- {
y := int(b[j] - '0')
s := x*y + pos[i+j+1]
pos[i+j+1] = s % 10
pos[i+j] += s / 10
}
}
k := 0
for k < m+n-1 && pos[k] == 0 {
k++
}
out := make([]byte, 0, m+n-k)
for _, d := range pos[k:] {
out = append(out, byte('0'+d))
}
return string(out)
}48 は0 のpos[i + j] にはs にpos[0] は、
計算量
- 時間は O(m × n) です。
桁の 組ごとに 1 回ずつ掛けます - 使う
記憶は、 答えの 置き場の O(m + n) です - 段ごとの
文字列を 作って 足す 書き方も 時間は O(m × n) ですが、 途中の 文字列の 分だけ記憶と 手間が増えます
よく ある間違い
- 数に
直して掛ける。 200 桁は 64 ビットの 整数にも、 JavaScript の 数にも 入りません。 条件で 禁じられていなくても、 20 桁を 超えると 答えが狂います - 先頭の 0 を残す。
例 1 では posが[0, 5, 4, 0]になり、 そのまま 並べると "0540"です。先頭の 0 を 飛ばします - 0 を
全部飛ば して 空の 文字列を返す。 例 2 では posが全部 0 です。 最後の 1 桁は 残すよう、 kをm + n - 1で止めます - 積の
落ちる 位を 間違える。 i + j に 一の 位を 入れると、 答えが 1 桁ずれます。 一の 位は i + j + 1、 繰り 上がりは i + j です
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「m 桁と n 桁の
積は 多くても m + n 桁なので、 その 長さの 位の 置き場を 用意します。 i 桁目と j 桁目の 積は i + j + 1 の 位に 足し、 繰り 上がりを i + j の 位に 送ります。 右から 回せば 繰り 上がりが 自然に まとまります。 最後に 先頭の 0 を 飛ばし、 全部 0 なら "0"を返します。 時間は O(m × n)、 記憶は O(m + n) です。」
書き終えたら、
「例 1 の 45 × 12 を
たどります。 5 × 2 で 10、 pos[3]が 0 でpos[2]に 1 です。5 × 1 に pos[2]の 1 を足して 6、 pos[2]が 6 です。4 × 2 に 6 を 足して 14、 pos[2]が 4 でpos[1]に 1 です。4 × 1 に 1 を 足して 5、 pos[1]が 5 です。[0, 5, 4, 0]の先頭の 0 を 飛ばして "540"です。」