前端練習52 字符串中的第一個唯一字符

已同步到個人博客,歡迎訪問

題目

題目來自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
};

如果將indexOflastIndexOf的時間複雜度都認爲是n,那麼這種方法的時間複雜度是O(n^3),但是執行用時反而會縮短一些,爲144ms,可能是瀏覽器對indexOflastIndexOf有優化吧

實現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

這道題的啓發是什麼呢。

那就是,智商真的很重要。

我只能勤能補一點點拙了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章