最後の 位置を 使って 文字列を できるだけ多く切る
文字列を、どの
海外で定番の問題リスト 4 本には入っていません
問題
英小文字だけでs をs を
- 切れは、
sを左から 順に 区切った 物で、 並べ替えや 飛ばしはしません - 切れの
数が 最も 多い 分け方は 1 つに 決まります sの長さは 1 以上 500 以下です
入力と出力の例
例 1
a は 0 番と 3 番にabca は 1 つのd、e、ff、g は
例 2
t は 0 番と 4 番、o は 1 番と 5 番に
例 3
k は 1 回しかiwi は i が
面接での聞かれ方
面接では、
- 「文字列を、
同じ 文字が 別の 切れに 出ないように、 できるだけ 多く 分けてください。 切れの 長さを 返してください」 - 「切れの
中身ではなく 長さを 返すのですか」と 確かめると、 「長さで」と 返ってくるのが ふつうです - 書き終えた
あとに 「なぜ この 切り方で 切れの 数が 最も 多くなるのですか」と、 理由を 聞かれる こともあります
返すのが
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直に
段 2
あるc がc が
段 3
前からstart と、end をend をend とend - start + 1 の
解答
Python
Python
def partition_labels(s):
last = {}
for i, ch in enumerate(s):
last[ch] = i
out = []
start = 0
end = 0
for i, ch in enumerate(s):
end = max(end, last[ch])
if i == end:
out.append(end - start + 1)
start = i + 1
return outJavaScript
JavaScript
function partitionLabels(s) {
const last = new Map();
for (let i = 0; i < s.length; i++) {
last.set(s[i], i);
}
const out = [];
let start = 0;
let end = 0;
for (let i = 0; i < s.length; i++) {
end = Math.max(
end, last.get(s[i]),
);
if (i === end) {
out.push(end - start + 1);
start = i + 1;
}
}
return out;
}Go
Go
func partitionLabels(
s string,
) []int {
last := [26]int{}
for i := 0; i < len(s); i++ {
last[s[i]-'a'] = i
}
out := []int{}
start, end := 0, 0
for i := 0; i < len(s); i++ {
end = max(end, last[s[i]-'a'])
if i == end {
out = append(out,
end-start+1)
start = i + 1
}
}
return out
}Go は
計算量
- 時間は O(n) です。
最後の 位置を 調べるのに 1 回、 切れ目を 決めるのに 1 回、 文字列をなめます - 使う
記憶は、 答えを 除けば O(1) です。 最後の 位置の 表は 文字の 種類の 26 個までです - 答えの
並びは 最悪 n 個の 長さを 持ちます (どの 文字も 1 回ずつしか 出ないとき)
よく ある間違い
- 最初の
文字の 最後の 位置だけで切る。 例 1 で aの最後の 位置 3 で 切るのは 合っていますが、 tomatoでtの最後の 位置 4 で 切ると、 oが 1 番と 5 番で 2 つの切れに 分かれます。 切れの 中の 全部の 文字の 最後の 位置の 最大を取ります - 切れの
長さを end - startで数える。 両端を含むので 1 を 足します。 足し忘れると、 例 3 の kの切れの 長さが 0 になります - 同じ
文字が 並んだ所で切る。 例 1 の ffを見て 「同じ文字の続きで切る」と 考えると、 離れて 出る aのような文字を 扱えません。 見るのは 最後に 出る位置です - 次の
切れの 始まりを 更新し忘れる。 startをi + 1に直さないと、 2 つ目からの 切れの 長さが、 先頭からの 長さになります
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「ある
文字が 切れに 入ったら、 その 文字が 最後に 出る 位置までは 切れを 伸ばすしか ありません。 なので、 先に 文字ごとの 最後の 位置を 調べ、 前から 見て 切れの 中の 文字の 最後の 位置の 最大を 広げていきます。 いまの 位置が その 最大と 同じに なったら、 そこで 切ります。 できるだけ早く 切るので、 切れの 数が 最も 多くなります。 時間は O(n)、 記憶は 文字の 種類の 分だけです。」
書き終えたら、
「例 1 の
最後の 位置は、 aが 3、bが 1、cが 2、dが 4、eが 5、fが 7、gが 8 です。0 番の aで最大は 3 に なり、 1 番と 2 番では 3 のまま、 3 番で 位置と 最大が そろうので 長さ 4 で 切ります。 4 番の dは最大 4 で 長さ 1、 5 番の eも長さ 1 です。 6 番の fで最大が 7 に なり、 7 番で そろって 長さ 2、 8 番の gで長さ 1 です。 答えは [4, 1, 1, 2, 1]です。」