leetcode刷題記錄(3)

1.移除元素

題目:

給你一個數組 nums 和一個值 val,你需要 原地 移除所有數值等於 val 的元素,並返回移除後數組的新長度。

不要使用額外的數組空間,你必須僅使用 O(1) 額外空間並 原地 修改輸入數組。

元素的順序可以改變。你不需要考慮數組中超出新長度後面的元素。

和昨天的重複排序類似。

思路:單次遍歷,並聲明一個變量記錄當前有效的長度,比較時,如果相等則直接進入下一輪循環,如果不相等,先把當前元素賦值給當前變量下標,然後變量自增1,(順序不能弄錯)

var removeElement = function(nums, val) {
  let l = nums.length,
    res = 0;
  for (let i = 0; i < l; i++) {
    if (nums[i] !== val) {
      nums[res] = nums[i];
      res++;
    }
  }
  return res;
};

沒啥優化空間,單次遍歷,也沒遞歸,時間複雜度和空間複雜度都是最低了。

2.實現strStr()

題目:

實現 strStr() 函數。

給定一個 haystack 字符串和一個 needle 字符串,在 haystack 字符串中找出 needle 字符串出現的第一個位置 (從0開始)。如果不存在,則返回  -1。

思路:其實就是字符串的indexOf方法,不過咱肯定用原生寫。

和冒泡排序十分類似,。

思路:雙重循環,依次比較

var strStr = function(haystack, needle) {
  let l = needle.length;
  if (!l) return l;
  let l2 = haystack.length;
  if (l > l2) return -1;
  for (let i = 0; i < l2; i++) {
    for (let j = 0; j < l; j++) {
      if (haystack[i + j] !== needle[j]) break;
      if (j === l - 1) {
        return i;
      }
    }
  }
  return -1;
};

問題:每個都遍歷,耗時太長

優化方向:提早跳出不必要的循環。可以在外層循環比較haystack剩餘字符串長度和needle的長度,如果前者更小,則直接跳出循環返回-1即可。

var strStr = function(haystack, needle) {
  let l = needle.length;
  if (!l) return l;
  let l2 = haystack.length;
  if (!l2) return -1;
  if (l > l2) return -1;
  for (let i = 0; i < l2; i++) {
    if (l2 - i < l) return -1;
    for (let j = 0; j < l; j++) {
      if (haystack[i + j] !== needle[j]) break;
      if (j === l - 1) {
        return i;
      }
    }
  }
  return -1
};

3.搜索插入位置

題目:

給定一個排序數組和一個目標值,在數組中找到目標值,並返回其索引。如果目標值不存在於數組中,返回它將會被按順序插入的位置。

你可以假設數組中無重複元素。

思路:分兩種情況,一是有相等的元素,二是沒有相等的元素。

相等的情況很容易區分,不相等的時候,可以這樣,因爲原數組是排序號的,我們一直記錄比目標值小的成員的下標即可,最後返回+1的值

  let l = nums.length,
    j = -1;
  for (let i = 0; i < l; i++) {
    if (nums[i] === target) return i;
    if (nums[i] < target) j = i;
  }
  return j+1;

優化方向:提前終止循環

  let l = nums.length,
    j = -1;
  if (target <= nums[0]) return 0;
  if (target > nums[l - 1]) return l;
  for (let i = 0; i < l; i++) {
    if (nums[i] === target) return i;
    if (nums[i] < target) j = i;
  }
  return j + 1;

優化方向:二分法查找,而非單次遍歷,減少比較次數:

    let left = 0;
    let right = nums.length - 1;
    if (target > nums[right]){ return right + 1; }
    if(target<=nums[0])return 0
    while (left < right) {
        let index = (left + right) >>> 1;//取左中位數
        if (nums[index] < target){
            left = index + 1;
        }else{
            right = index;
        }
    }
    return left;

4.外觀數列

題目:

「外觀數列」是一個整數序列,從數字 1 開始,序列中的每一項都是對前一項的描述。前五項如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
1 被讀作  "one 1"  ("一個一") , 即 11。
11 被讀作 "two 1s" ("兩個一"), 即 21。
21 被讀作 "one 2",  "one 1" ("一個二" ,  "一個一") , 即 1211。

給定一個正整數 n(1 ≤ n ≤ 30),輸出外觀數列的第 n 項。

注意:整數序列中的每一項將表示爲一個字符串。

思路:從左到右,雙重循環,第一次循環是記錄n的值,第二輪循環是遍歷上一輪循環的結果,根據上一輪的結果得到這一輪的結果。所以首先需要一個變量保存上一輪的結果,一個變量計算這一輪的結果。

此外,還要有一個變量記錄當前遇到的數是什麼數,一個變量記錄當前數出現的次數

遍歷上一輪的結果,比較每一個字符串和當前字符串,如果相同,則變量+1,如果不同,則先對結果拼接,然後更新當前的數,

var countAndSay = function (n) {
  if (n == 1) return "1";
  let res = "1",
    v = "0",
    a = 0,
    r = "";
  for (let i = 1; i < n; i++) {
    let l = res.length;
    for (let j = 0; j < l; j++) {
      if (res[j] !== v) {
        if (a) {
          r += `${a}${v}`;
        }
        v = res[j];
        a = 1;
      } else {
        a++;
      }
    }
    if (a) {
      r += `${a}${v}`;
    }
    v = "0";
    res = r;
    a = 0;
    r = "";
  }
  return res;
};

 

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