スライディングウィンドウで k 枚まで 塗り 替えて 同じ色の 最長の 並びを作る
色を
海外で定番の問題リスト 4 本には入っていません
問題
壁に 1 列にs でs[i] がk 枚まで、
塗り
- 塗り
替える 色は、 英大文字の どれでもかまいません。 塗り 替えは k枚より少なくてもかまいません sの長さは 1 以上 100000 以下で、 AからZの英大文字だけで できています kは 0 以上、sの長さ以下です
入力と出力の例
例 1
左から 3 枚目から"GRGGGR" は、
例 2
塗り"XX" の 2 枚が
例 3
4 枚とも
面接での聞かれ方
面接では、
- 「k 文字まで
置き換えて、 同じ 文字が 続く 最長の 部分文字列の 長さを 求めてください」 - 「置き換える
先の 文字は、 何でも いいですか?」と、 範囲を 自分から 確かめるかを 見られます - 書き終えた
あとに 「最も 多い 文字の 数を、 窓が 縮むときに 減らさなくていいのは なぜですか?」と 聞かれる こともあります
窓の
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
1 つのk 以下なら
段 2
素直に
段 3
左右のtop をtop をk を
段 4
ここで 2 つのk をtop をtop がtop が
解答
Python
Python
from collections import Counter
def longest_repaint(s, k):
count = Counter()
lo = 0
top = 0
best = 0
for r, c in enumerate(s):
count[c] += 1
top = max(top, count[c])
size = r - lo + 1
if size - top > k:
count[s[lo]] -= 1
lo += 1
size -= 1
best = max(best, size)
return bestJavaScript
JavaScript
function longestRepaint(
s,
k
) {
const count = {};
const n = s.length;
let lo = 0;
let top = 0;
let best = 0;
for (let r = 0; r < n; r++) {
const c = s[r];
count[c] ??= 0;
const got = ++count[c];
top = Math.max(top, got);
let size = r - lo + 1;
if (size - top > k) {
count[s[lo]]--;
lo++;
size--;
}
best = Math.max(best, size);
}
return best;
}Go
Go
func longestRepaint(
s string,
k int,
) int {
var count [26]int
lo, top, best := 0, 0, 0
for r := 0; r < len(s); r++ {
c := s[r] - 'A'
count[c]++
top = max(top, count[c])
size := r - lo + 1
if size-top > k {
count[s[lo]-'A']--
lo++
size--
}
best = max(best, size)
}
return best
}lo がr がsize が
計算量
- 時間は O(n) です。
右の 端も 左の 端も、 それぞれ前へ 1 回ずつしか 進みません - 使う
記憶は O(1) です。 色の 数を 数えるのは 英大文字の 26 種類ぶんだけです - 段 2 の
全部の 区間を 確かめる 書き方は、 時間が O(n²) です
よく ある間違い
- 窓の
中の 最初の 色や、 右の 端の 色に そろえると決める。 いちばん 多い 色に そろえるのが 最も 少ない 塗り 替えです。 例 1 で R に そろえると 考えると、 6 枚の 並びを 見落とします - 窓の
長さを r - loで数える。 両端を含むので + 1が要ります。 1 文字の "A"で 1 になるかを 確かめると 気づけます topを減らそうとして、 毎回 26 色を 数え直す。 答えは 合いますが 手間が 増えます。 減らさなくて よい 理由を 説明できるように しておきます - 塗り
替えの 数を 「窓の中の違う色の数」で数える。 "GRGGGR"の違う色は 2 種類ですが、 塗り 替えるのは R の 2 枚です。 種類ではなく 枚数で数えます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「1 つの
区間を そろえるのに 要る 塗り 替えは、 区間の 長さから いちばん 多い 色の 枚数を 引いた数です。 右の 端を 伸ばしながら色を 数え、 この 数が k を 越えたら 左の 端を 1 つ 進めます。 窓は 縮まずに 横へずれるだけで、 いちばん 多い 色の 枚数も 減らさずに 持ちます。 答えが 伸びるのは その 枚数が 増えた ときだけだからです。 時間は O(n)、 記憶は 26 色ぶんです。」
書き終えたら、
「例 2 で
たどります。 k は 0 です。 X で 長さ 1。 Y を 足すと 長さ 2 で 多い色は 1 枚、 塗り 替えが 1 枚要るので 左を 進め、 長さ 1 のまま。 Z も 同じです。 次の X で 窓は Z と X、 まだ 1 枚要るので 進めます。 最後の X で 窓は X と X、 多い 色が 2 枚で 塗り 替えは 0、 長さ 2 が 答えです。」