Привет кодеры,
Сегодня мы будем решать задачу Первый уникальный символ в строке в JavaScript (ES6). Разбираемся в проблеме:
Имея строку
s
, найти в ней первый неповторяющийся символ и вернуть его индекс. Если он не существует, вернуть-1
. Например:
Ввод:
s = "ilovejavascript"
Выход:
1
Объяснение:
l
— это первый уникальный символ в данной строке, и он присутствует в индексе1st
, поэтому мы возвращаем1
.
Ввод:
s = "aabbcc"
Выход:
-1
Объяснение: в данной строке нет уникальных символов, поэтому мы возвращаем -1.
Подход:
Первый подход: временная сложность O(n)
Мы собираемся отслеживать все символы, встречающиеся в строке, и проверять, уникальна она или нет. Для этого мы можем перебрать строку и сохранить characters
и их occurrences
в строке как пару key-value
в object
.
//If the given string is: s = "medium"; //the object will be: obj = {m:2,e:1,d=1,i=1,u=1}
Затем мы пройдем через keys
из object
и вернем index
из первого ключа, который будет иметь значение 1
. В этом случае мы вернем индекс e
в строке s
, так как это первый уникальный символ в строке. Таким образом, наш вывод будет 1
. Если уникального символа нет, возвращаем -1
.
Второй подход: временная сложность O(n)
Мы собираемся перебрать строку и проверить, равен ли первый индекс символа в строке последнему индексу символа в строке. Затем мы вернем индекс символа, который удовлетворяет этому условию в первый раз, так как это будет первый уникальный символ. Если уникального символа нет, возвращаем -1
.
Если заданная строка s = "medium"
:
Первый индекс символа m
— 0
, а последний индекс — 5
. А значит не уникальный.
Первый индекс символа e
равен 1
, а последний индекс - 1
. Это означает, что это уникальный символ, и мы возвращаем его index
в строке s
.
Решение с использованием первого подхода:
Создадим функцию firstUniqueChar
, которая принимает в качестве параметра строку s
. Также мы объявим объект charObj
, который будет хранить пары ключ-значение символов и их вхождения в строку.
const firstUniqueChar = (s) => { let charObj = {}; //... //... //... }
Теперь давайте создадим цикл, который будет использоваться для перебора строки s
. Я использую здесь оператор for…in
, вы также можете использовать обычный for loop
.
const firstUniqueChar = (s) => { let charObj = {}; for(i in s){ //... //... //... } //... }
Теперь мы проверим, присутствует ли уже в массиве key
в объекте charObj
, который является символом с индексом i,
. Если он уже присутствует в массиве, мы увеличим его, иначе мы присвоим его значение как 1
, так как это будет первое вхождение символа в строку. Я использовал для этого тернарный оператор, вы также можете использовать оператор if-else
.
const firstUniqueChar = (s) => { let charObj = {}; for(i in s){ charObj[s[i]] ? charObj[s[i]]++ : charObj[s[i]]=1; } //... //... }
Давайте пройдемся по объекту charObj
и проверим values
его keys
. Если value
равно 1
, мы вернем index
из key
в строке s
.
const firstUniqueChar = (s) => { let charObj = {}; for(i in s){ charObj[s[i]] ? charObj[s[i]]++ : charObj[s[i]]=1; } for(key of Object.keys(charObj)){ if(charObj[key]===1){ return s.indexOf(key); } } //... //... }
Метод
indexOf()
возвращает первый индекс, по которому данный элемент может быть найден в массиве, или -1, если он отсутствует.
А что если в строке s
нет уникального символа. Для этого мы можем просто вернуть -1
вне циклов, потому что, если в строке будет присутствовать уникальный символ, цикл for...of
, перебирающий объект, вернет его индекс. Единственный случай, когда последний оператор return будет выполнен, — это только в том случае, если в строке не будет уникального символа.
const firstUniqueChar = (s) => { let charObj = {}; for(i in s){ charObj[s[i]] ? charObj[s[i]]++ : charObj[s[i]]=1; } for(key of Object.keys(charObj)){ if(charObj[key]===1){ return s.indexOf(key); } } return -1; }
Вот и все! Это полная функция, использующая первый подход. Теперь рассмотрим второй подход.
Решение с использованием второго подхода:
Сначала мы создадим функцию firstUniqueChar
, которая принимает строку s
в качестве параметра.
const firstUniqueChar = (s) => { //... //... //... }
Теперь мы пройдемся по строке s
и проверим, равно ли first index
символа last index
символа, и если это так, мы вернем first index
этого символа. Мы будем использовать метод indexof()
для нахождения первого индекса символа и метод lastIndexOf()
для нахождения последнего индекса символа. Мы вернем -1
вне цикла, как и в первом подходе, чтобы обработать случай отсутствия уникальных символов в строке.
const firstUniqueChar = (s) => { for(i in s){ if(s.indexOf(s[i])===s.lastIndexOf(s[i])){ return i; } } return -1; }
Вот и все! Вот оно, решение той же проблемы, но с меньшим количеством строк кода и циклов.
Дайте мне знать, помогло ли это вам в разделе комментариев, а также дайте мне знать, как бы вы хотели решить эту проблему.
Большое спасибо, что пришли сюда!