Count a Character
Тебе дана строка s и одна буква c. Верни количество вхождений c в s. Учитывается регистр: B и b — разные символы, поэтому считаются только точные совпадения с c.
Функция
- sstring
- строка английских букв для поиска
- cstring
- одна буква для подсчёта
- Возвращаетinteger
- сколько символов в s равны c
Ограничения
1 ≤ s.length ≤ 5 × 104sсодержит только английские буквы (a—z,A—Z).c— это ровно одна буква английского алфавита.
Примеры
- Ввод
- s = "Mississippi"c = "s"
- Вывод
- 4
- Пояснение
- В слове
Mississippiбукваsнаходится на позициях 2, 3, 5 и 6 при отсчёте с 0, поэтому ответ — 4.
- Ввод
- s = "Banana"c = "b"
- Вывод
- 0
- Пояснение
Bananaначинается с заглавной буквыB, а поиск выполняется по строчной буквеb. Они различаются, поэтому совпадений нет, и ответ — 0.
+18 скрытых тестов при отправке
Дополнительный вопрос
Что, если c может быть словом из нескольких букв, например ss? Считаются ли перекрывающиеся совпадения и как изменится ваш цикл?
Подсказки
Открывайте по одной. Каждая подсказывает чуть больше.
Чтобы узнать, сколько раз встречается
c, на какие символы вsнужно посмотреть?Сравнивайте каждый символ
sсcименно так, как они записаны. Здесь буквы в верхнем и нижнем регистре считаются разными символами.Ведите счётчик, который начинается с 0. Пройдите по строке один раз и добавляйте 1, когда текущий символ равен
c.
Решение
Каждый символ s нужно проверить один раз, потому что любой из них может быть c. Это делается за один проход с помощью счётчика. Трудности обычно связаны с регистром (заглавная буква — это другой символ) и, в некоторых языках, со сравнением символа со строкой из одной буквы.
Удалите каждую c и сравните длины
Идея
Создай копию s, удалив из неё все c. Каждый удалённый символ делает копию на один символ короче, поэтому разница между длинами двух строк в точности равна количеству вхождений c. В большинстве языков есть функция замены или удаления, которая выполняет это за тебя.
Для Mississippi и s копия будет такой: Miiippi. В ней 7 символов, а в исходной строке — 11, значит, c встречается 4 раза. Для Banana и b ничего не удаляется, потому что заглавная B не совпадает, и разница равна 0.
Нужно один раз пройти по s, поэтому время работы составляет O(n). Затраты связаны с памятью: копия может быть такой же длинной, как s, то есть требуется O(n) дополнительного пространства, которое счётчику не нужно.
Алгоритм
- Создай копию
s, пропустив каждый символ, равныйc. - Измерь длину
sи длину копии. - Верни длину
sминус длина копии.
def countChar(s, c):
# Every c that disappears makes the string one character shorter.
without = s.replace(c, "")
return len(s) - len(without)Один проход со счётчиком
Идея
Не создавай копию и считай по мере чтения. Пройдись по s слева направо, используя счётчик, который начинается с 0, и увеличивай его на 1, когда текущий символ равен c. Совпадение определяется обычным сравнением на равенство, поэтому заглавная буква никогда не совпадает со строчной.
В слове Mississippi счётчик увеличивается на индексах 2, 3, 5 и 6 и в итоге равен 4. Каждый символ сравнивается один раз, и больше ничего не сохраняется.
Это даёт временную сложность O(n) и дополнительную сложность по памяти O(1): один счётчик и целевая буква. Улучшить время выполнения нельзя, потому что пропущенный символ мог бы оказаться ещё одной буквой c.
Алгоритм
- Прочитай целевую букву из
cи установиcount = 0. - Просматривай
sпо одному символу за раз. - Если символ совпадает с целевым, прибавь 1 к
count. - Верни
count.
def countChar(s, c):
count = 0
for ch in s:
if ch == c:
count += 1
return count
Ловушки и крайние случаи
Цикл короткий, а ошибки кроются в способе сравнения двух значений.
- Игнорирование регистра. Перевод обеих сторон в нижний регистр приводит к тому, что для
Bananaиbвозвращается 1, но задача требует точного совпадения, поэтому ответ — 0. - Сравнение символа со строкой. В Java, C, C++, C# и Go значение
cпоступает как строка, аs.charAt(i)илиs[i]— это один символ. Возьмиc[0](илиc.charAt(0)) один раз до цикла. - Сравнение строк с помощью
==в Java. ВыражениеString.valueOf(s.charAt(i)) == cсравнивает идентичность объектов и почти всегда возвращает false. Сравнивай значения типаcharили используйequals. - Вызов
strlen(s)в условии цикла в C. Эта функция проходит по всей строке на каждом шаге, поэтому обработка5 × 10^4символов требует около2.5 × 10^9шагов. Вместо этого останавливайся на терминаторе'\0'.
Частые вопросы4
Как подсчитать количество вхождений символа в строку?
Начните счётчик с 0 и пройдите по строке один раз. Каждый раз, когда текущий символ совпадает с искомым, прибавляйте 1. Когда цикл завершится, значение счётчика и будет ответом, а выполнение займёт время O(n) и потребует O(1) дополнительной памяти.
Учитывается ли регистр символа при подсчёте?
В этой задаче — да: B и b — разные символы, поэтому в Banana нет b. Если вместо этого нужно подсчитать символы без учёта регистра, перед сравнением преобразуй и строку, и букву в нижний регистр.
Можно ли использовать встроенную функцию подсчёта на собеседовании?
Обычно да, если вы можете объяснить, сколько это стоит. Функции Python str.count и подобные им всё равно считывают всю строку, поэтому их сложность — O(n). Многие интервьюеры затем просят вас написать цикл самостоятельно, так что будьте готовы его показать.
Как посчитать все символы сразу?
Сделай один проход и подсчитывай количество каждого символа в хеш-таблице или в массиве из 52 счётчиков для английских букв. После этого прохода количество любой буквы можно получить за один поиск. Это лучший подход, если нужно узнать количество многих букв в одной и той же строке.
Похожие задачи
Задачи на те же идеи. Решите две или три, и приём запомнится.
Python
def countChar(s, c):
# Напишите код здесьСлучай 1
Случай 2
Ввод
s = "Mississippi" c = "s"
Ожидается
4