Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
菜鸟就要从第20题继续
一、题目描述:
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。
示例 :
输入: s = "leetcode" 输出: 0 示例 2:
输入: s = "loveleetcode" 输出: 2 示例 3:
输入: s = "aabb" 输出: -1 提示:
1 <= s.length <= 105 s 只包含小写字母
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
第一版(错误代码):开始看到这个题目,直观想到了map的新增删除,但写完发现对于"aaa",类的出现奇数个的是无法正常计算的,因此不能采用delete的方案。
同时存次数、索引:如果还考虑在第一版基础上改,可以把储存的value变为次数和位置,然后找到次数为1的那一个,取其位置。
只存索引:还在第一版上改,只存索引,不用delete而是重置为-1,最后再遍历找到不是-1的那一个最小值。(这里是摘抄了官方解决,他对于字符串的遍历,采用了Array.from(s).entries()
Array.from()方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例entries()方法返回一个数组的迭代对象,该对象包含数组的键值对 (key/value)。迭代对象中数组的索引值作为 key, 数组元素作为 value。
只存次数:思路上也很清晰,先存次数,最后找到为1的那一个。官方的写法很有趣
_.countBy()创建一个对象,对数组或者对象的每个元素或属性调用iteratee迭代器后生成这个对象的键,键的值是这个键出现的次数
队列思路:这个思路开始时我想过,后来感觉比较复杂,并不直观就没写,重点就在于要在每次有变化的时候重新处理前面的删除内容。
三、AC 代码:
1、第一版(错误代码)
/**
* @param {number} x
* @return {number}
*/
var firstUniqChar = function(s) {
let map = new Map()
for(let i=0;i<s.length;i++){
if(map.has(s[i])){
map.delete(s[i])
}
else{
map.set(s[i],i)
}
}
if(map.size==0){
return -1
}
else {return map.entries().next().value[1]}
};
2、同时存次数、索引
/**
* @param {number} x
* @return {number}
*/
var firstUniqChar = function(s) {
let map = new Map()
for(let i=0;i<s.length;i++){
map.set(s[i],[i,(map.get(s[i]) || 0) + 1])
}
for (let [index, occurrences] of map.values()) {
if (occurrences === 1) {
return index;
}
}
return -1;
};
3、只存索引
/**
* @param {number} x
* @return {number}
*/
var firstUniqChar = function(s) {
const position = new Map();
const n = s.length;
for (let [i, ch] of Array.from(s).entries()) {
if (position.has(ch)) {
position.set(ch, -1);
} else {
position.set(ch, i);
}
}
let first = n;
for (let pos of position.values()) {
if (pos !== -1 && pos < first) {
first = pos;
}
}
if (first === n) {
first = -1;
}
return first;
};
4、只存次数
/**
* @param {number} x
* @return {number}
*/
var firstUniqChar = function(s) {
const frequency = _.countBy(s);
for (const [i, ch] of Array.from(s).entries()) {
if (frequency[ch] === 1) {
return i;
}
}
return -1;
};
5、队列思路
/**
* @param {number} x
* @return {number}
*/
var firstUniqChar = function(s) {
const position = new Map();
const q = [];
const n = s.length;
for (let [i, ch] of Array.from(s).entries()) {
if (!position.has(ch)) {
position.set(ch, i);
q.push([s[i], i]);
} else {
position.set(ch, -1);
while (q.length && position.get(q[0][0]) === -1) {
q.shift();
}
}
}
return q.length ? q[0][1] : -1;
};