Same code works for 3+ unique chars too.
// example
xx xxxxx
abbcbcbdddde
|-|3 .. ..
|----|6 ..
|--|4 ..
|-|3 ..
||2 ..
|---|5
|---|5
(s, k = 2):
if s == null:
throw
maxstart = maxend = 0
set unique = new
resetindex = 0
start = i = 0
while i < s.length():
c = s[i]
if unique.has(c):
i++
else if unique.count() == k:
if i-start > maxend-maxstart:
maxstart = start, maxend = i
unique.clear()
start = i = resetindex
else:
unique.add(c)
// reset from 2nd char's index (first occurrence)
if unique.count() == 2:
resetindex = i
i++
if i-start > maxend-maxstart:
maxstart = start, maxend = i
return s.substring(maxstart, maxend-maxstart)
It's better to use a circular queue and map. The circular queue is useful to drop the oldest char. The map is mainly to hold the index of chars to adjust start.(s, k = 2):
unique, cq = new
len = maxlen = start = 0
for i = 0, i < s.length(), i++:
ch = s[i]
if unique.has(ch):
if cq.peektail() != ch:
cq.enqueue(i)
len += 1
else if unique.count() == k:
unique.remove(s[cq.dequeue()])
unique.add(ch)
cq.enqueue(i)
len = i+1 -cq.peek()
else: // unique.count() < k
unique.add(ch)
cq.enqueue(i)
len += 1
if len > maxlen:
maxlen = len
start = i+1 -len
return s.substring(start, maxlen)
circularQueue:
enqueue(x):
x dequeue():
x peek(): // return head
x peekTail(): // return tail
[Hat tip to SM]
No comments:
Post a Comment