題目
題目來自LeetCode
給定一個字符串,找到它的第一個不重複的字符,並返回它的索引。如果不存在,則返回-1
。
s = "leetcode"
// 返回 0.
s = "loveleetcode",
// 返回 2.
注意事項:您可以假定該字符串只包含小寫字母。
實現1
首先想到的是用空間來換取時間,第一個循環用一個臨時的數組來將所有的字符串都寸到對象中,並隨時更改出現的次數,第二個循環在判斷每一個字符串在對象中的值,如果只出現一次,返回當前的循環下標:
/**
* @param {string} s
* @return {number}
*/
var firstUniqChar = function (s) {
let temp = {};
for (let i = 0; i < s.length; i++) {
if (!temp[s[i]]) {
temp[s[i]] = 1;
} else {
temp[s[i]]++;
}
}
for (let i = 0; i < s.length; i++) {
if (temp[s[i]] === 1) {
return i
}
}
return -1
};
這種方法的時間複雜度是O(2n)
,執行結果不太理想,執行用時184mm
實現2
想到可以同時從正反查找字符串出現的位置,如果是同一個位置,那麼就返回改下標:
var firstUniqChar = function (s) {
const length = s.length;
for (let i = 0; i < length; i++) {
const str = s[i];
if (s.lastIndexOf(str) === s.indexOf(str)) {
return i
}
}
return -1
};
如果將indexOf
和lastIndexOf
的時間複雜度都認爲是n
,那麼這種方法的時間複雜度是O(n^3)
,但是執行用時反而會縮短一些,爲144ms,可能是瀏覽器對indexOf
和lastIndexOf
有優化吧
實現3
看了一下大神們100ms以內的實現方法,果然牛逼。
var firstUniqChar = function (s) {
const alpha = 'abcdefghijklmnopqrstuvwxyz';
let first = s.length;
for (let i = 0; i < alpha.length; ++i) {
let index = s.indexOf(alpha[i]);
if (index !== -1 && index === s.lastIndexOf(alpha[i])) {
if (index < first) {
first = index;
}
}
}
return first === s.length ? -1 : first;
};
本來是遍歷原先的字符串,結果變爲遍歷一個常量字符串。之所以這樣可以行,是因爲題目的備註中說明了“可以假定該字符串只包含小寫字母”
所以這樣的時間複雜度是O(n^2)
,下降了一個數量級,實際執行用時爲96ms
這道題的啓發是什麼呢。
那就是,智商真的很重要。
我只能勤能補一點點拙了。