Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions 0424.Longest-Repeating-Character-Replacement/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 424. Longest Repeating Character Replacement

## step1
sliding windowを使う。
23mほどかかった。

時間計算量はO(N)。ただし文字列に含まれるユニークな文字を定数とみなした場合。

他の解法は思いつかない。Hashmapがヒントにあるがこれをどう使うのかわからない。

## 他の人のコード

https://github.com/olsen-blue/Arai60/pull/49#issuecomment-3649179920

https://github.com/Exzrgs/LeetCode/pull/48

hashmapの使い方はこうするのか

https://github.com/potrue/leetcode/pull/65/changes

maxを取り出す部分でheapを使った解法。

heapの遅延評価: heapからの削除が難しいからとりあえずcounterだけ更新しておいて、heapから取り出したときの値は一致していなかったら捨てる

実際にはheapの定数倍の計算量で遅くなるようだ。

https://leetcode.com/problems/longest-repeating-character-replacement/solutions/8301734/optimal-solution-by-nthapa000-lejz/

max_frequencyは更新されるときだけ計算しても良く、時間計算量が小さくなる。が、毎回計算した方がわかりやすいようにも思う。

## step2
21 changes: 21 additions & 0 deletions 0424.Longest-Repeating-Character-Replacement/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
length_of_longest = 0

def update_longest(target_alphabet):
nonlocal length_of_longest
left = 0
num_other_than_target = 0
for right in range(len(s)):
if s[right] != target_alphabet:
num_other_than_target += 1
while num_other_than_target > k:
if s[left] != target_alphabet:
num_other_than_target -= 1
left += 1
length_of_longest = max(length_of_longest, right - left + 1)

for target_alphabet in set(s):
update_longest(target_alphabet)

return length_of_longest
19 changes: 19 additions & 0 deletions 0424.Longest-Repeating-Character-Replacement/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import collections


class Solution:
def characterReplacement(self, s: str, k: int) -> int:
count = collections.defaultdict(int)
left = 0
length_of_longest = 0

for right in range(len(s)):
count[s[right]] += 1

while (right - left + 1) - max(count.values()) > k:
count[s[left]] -= 1
left += 1

length_of_longest = max(length_of_longest, right - left + 1)

return length_of_longest
28 changes: 28 additions & 0 deletions 0424.Longest-Repeating-Character-Replacement/step2_heap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import collections
import heapq


class Solution:
def characterReplacement(self, s: str, k: int) -> int:
count = collections.defaultdict(int)
left = 0
length_of_longest = 0
heap = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heap に何が入っているのか、処理が追いづらく感じました。変数名に、要素がどのようなものかを表す英単語・英語句を付けるとよいと思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントを加えました。heap だけではなく stack などにも適用できる点だと思うので頭にいれておきます。
ついでに heapq モジュールの機能を使って max heap を実現しました。


def get_max_count():
while -heap[0][0] != count[heap[0][1]]:
heapq.heappop(heap)
return -heap[0][0]

for right in range(len(s)):
count[s[right]] += 1
heapq.heappush(heap, (-count[s[right]], s[right]))

while (right - left + 1) - get_max_count() > k:
count[s[left]] -= 1
heapq.heappush(heap, (-count[s[left]], s[left]))
left += 1

length_of_longest = max(length_of_longest, right - left + 1)

return length_of_longest
28 changes: 28 additions & 0 deletions 0424.Longest-Repeating-Character-Replacement/step2_heap_revised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import collections
import heapq


class Solution:
def characterReplacement(self, s: str, k: int) -> int:
count = collections.defaultdict(int)
left = 0
length_of_longest = 0
heap = [] # contains (count, alphabet) in max heap

def get_max_count():
while heap[0][0] != count[heap[0][1]]:
heapq.heappop_max(heap)
return heap[0][0]

for right in range(len(s)):
count[s[right]] += 1
heapq.heappush_max(heap, (count[s[right]], s[right]))

while (right - left + 1) - get_max_count() > k:
count[s[left]] -= 1
heapq.heappush_max(heap, (count[s[left]], s[left]))
left += 1

length_of_longest = max(length_of_longest, right - left + 1)

return length_of_longest
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import collections


class Solution:
def characterReplacement(self, s: str, k: int) -> int:
count = collections.defaultdict(int)
max_frequency = 0
left = 0
length_of_longest = 0

for right in range(len(s)):
count[s[right]] += 1
max_frequency = max(max_frequency, count[s[right]])

while (right - left + 1) - max_frequency > k:
count[s[left]] -= 1
left += 1

length_of_longest = max(length_of_longest, right - left + 1)

return length_of_longest