План курса / Все задачи / Алгоритмы и структуры данных
Цепочка из k-генов
средне
# решено
Дана строка gene, представляющая последовательность генов, где каждый ген — это один символ.
Требуется найти самую длинную непрерывную подстроку, содержащую не более k уникальных генов, где k ≤ числа различных символов.
Пример 1:
Ввод: gene = "YYxxXXXyyy", k = 3
Вывод: 8
Объяснение: самая длинная непрерывная последовательность генов с максимум 3-мя разными генами это "xxXXXyyy" (регистр буквы имеет значение).
Пример 2:
Ввод: gene = "yyy", k = 0
Вывод: 0
Пример 3:
Ввод: gene = "aXYYYXYXYbccc", k = 1
Вывод: 3
Ограничения:
0 <= len(gene)
0 <= k <= len(gene)
gene содержит ASCII символы
Видео не скачано: Iframe provider detected. HLS/MP4 URL is required.. Оригинальная ссылка
Видео не скачано: [tcp @ 000002cfa4a58540] Failed to resolve hostname edge-ams-1.kinescopecdn.net: The name does not resolve for the supplied parameters
[in#0 @ 000002cfa4a4f840] Error when loading first segment 'https://edge-ams-1.kinescopecdn.net/f6cd6a5f-6ee4-4c22-9d30-396f5a6f501b/videos/18f1f52d-0a47-4215-bf38-2d5cc7e4d4a4/assets/01962117-6591-7e66-8e22-ebc5ffd4519f/audio_0.mp4'
[in#0 @ 000002cfa4a4f2c0] Error opening input: I/O error
Error opening input file https://kinescope.io/c9dd9bf3-c750-4667-b5f1-25342edf925a/master.m3u8?expires=1778403823&sign=96a0e25191bd061a.
Error opening input files: I/O error. Оригинальная ссылка
public class Solution
{
public static int LongestGeneSequence(string gene, int k)
{
int l = 0;
int r = -1;
int result = 0;
Dictionary<char, int> geneCount = new Dictionary<char, int>();
while (l < gene.Length)
{
while (r + 1 < gene.Length && (geneCount.Count < k || (geneCount.Count == k && geneCount.ContainsKey(gene[r + 1]))))
{
if (!geneCount.ContainsKey(gene[r + 1]))
{
geneCount[gene[r + 1]] = 0;
}
geneCount[gene[r + 1]] += 1;
r += 1;
}
if (k == 0)
{
result = 0;
}
else
{
int windowSize = r - l + 1;
result = Math.Max(result, windowSize);
}
if (geneCount.ContainsKey(gene[l]))
{
geneCount[gene[l]] -= 1;
if (geneCount[gene[l]] <= 0)
{
geneCount.Remove(gene[l]);
}
}
l += 1;
}
return result;
}
}
#include <algorithm>
#include <string>
#include <unordered_map>
using namespace std;
int longestGeneSequence(string gene, int k) {
int l = 0;
// r = -1, чтобы добавление первого элемента не было исключением
int r = -1;
int result = 0;
// ключ: название гена, значение: сколько раз встретился ген в плавающем окне
unordered_map<char, int> geneCount;
while (l < gene.size()) {
while (r + 1 < gene.size() && (geneCount.size() < k || geneCount.count(gene[r + 1]) > 0)) {
geneCount[gene[r + 1]] += 1;
r += 1;
}
// обновляем ответ
int windowSize = r - l + 1;
result = max(result, windowSize);
// двигаем l (левую границу окна) на 1 и обновляем число уникальных символов
geneCount[gene[l]] -= 1;
if (geneCount[gene[l]] <= 0) {
geneCount.erase(gene[l]);
}
l += 1;
}
return result;
}
package main
func max(a, b int) int {
if a > b {
return a
}
return b
}
func isMapContains(mp map[byte]int, key byte) bool {
_, ok := mp[key]
return ok
}
func longestGeneSequence(gene string, k int) int {
l := 0
// r = -1, чтобы добавление первого элемента не было исключением
r := -1
result := 0
// ключ: название гена, значение: сколько раз встретился ген в плавающем окне
geneCount := make(map[byte]int)
for l < len(gene) {
for r + 1 < len(gene) && (len(geneCount) < k || isMapContains(geneCount, gene[r + 1])) {
geneCount[gene[r + 1]] += 1
r += 1
}
// обновляем ответ
windowSize := r - l + 1
result = max(result, windowSize)
// двигаем l (левую границу окна) на 1 и обновляем число уникальных символов
geneCount[gene[l]] -= 1
if geneCount[gene[l]] <= 0 {
delete(geneCount, gene[l])
}
l += 1
}
return result
}
import java.util.*;
public class Solution {
public int longestGeneSequence(String gene, int k) {
int l = 0;
// r = -1, чтобы добавление первого элемента не было исключением
int r = -1;
int result = 0;
// ключ: название гена, значение: сколько раз встретился ген в плавающем окне
HashMap<Character, Integer> geneCount = new HashMap<Character, Integer>();
while (l < gene.length()) {
while (r + 1 < gene.length() && (geneCount.size() < k || geneCount.containsKey(gene.charAt(r + 1)))) {
geneCount.merge(gene.charAt(r + 1), 1, Integer::sum);
r += 1;
}
// обновляем ответ
int windowSize = r - l + 1;
result = Math.max(result, windowSize);
// двигаем l (левую границу окна) на 1 и обновляем число уникальных символов
geneCount.merge(gene.charAt(l), -1, Integer::sum);
if (geneCount.get(gene.charAt(l)) <= 0) {
geneCount.remove(gene.charAt(l));
}
l += 1;
}
return result;
}
}
from typing import *
def longest_gene_sequence(gene: str, k: int) -> int:
l = 0
# r = -1, чтобы добавление первого элемента не было исключением
r = -1
result = 0
# ключ: название гена, значение: сколько раз встретился ген в плавающем окне
gene_count: dict[str, int] = {}
while l < len(gene):
while r + 1 < len(gene) and (len(gene_count) < k or gene[r + 1] in gene_count):
gene_count[gene[r + 1]] = gene_count.get(gene[r + 1], 0) + 1
r += 1
# обновляем ответ
window_size = r - l + 1
result = max(result, window_size)
# двигаем l (левую границу окна) на 1 и обновляем число уникальных символов
gene_count[gene[l]] = gene_count.get(gene[l], 0) - 1
if gene_count[gene[l]] <= 0:
# <=, а не == т.к. при k = 0 gene_count[gene[l]] -= 1 добавит ключ gene[l]
# а так происходить не должно, поэтому условие <= 0
del gene_count[gene[l]]
l += 1
return result
/**
* @param {string} gene
* @param {number} k
* @returns {number}
*/
export function longestGeneSequence(gene, k) {
let l = 0;
// r = -1, чтобы добавление первого элемента не было исключением
let r = -1;
let result = 0;
// ключ: название гена, значение: сколько раз встретился ген в плавающем окне
const geneCount = new Map();
while (l < gene.length) {
while (r + 1 < gene.length && (geneCount.size < k || (geneCount.size === k && geneCount.has(gene[r + 1])))) {
geneCount.set(gene[r + 1], (geneCount.get(gene[r + 1]) || 0) + 1);
r += 1;
}
// если k == 0, допустимый размер окна должен быть 0
if (k === 0) {
result = 0;
} else {
let windowSize = r - l + 1;
result = Math.max(result, windowSize);
}
// двигаем l (левую границу окна) на 1 и обновляем число уникальных символов
geneCount.set(gene[l], geneCount.get(gene[l]) - 1);
if (geneCount.get(gene[l]) <= 0) {
geneCount.delete(gene[l]);
}
l += 1;
}
return result;
}
Оценка сложности
Время: O(n), где n - длина строки gene
Память: O(min(n, k)), где k - макс. размер словаря, а n - длина строки gene