leetcode刷題記錄(2)

1.最長公共前綴

題目:

編寫一個函數來查找字符串數組中的最長公共前綴。

如果不存在公共前綴,返回空字符串 ""

思路:以第一個字符串爲基準,如果,從第一個字符開始依次和其他成員比較,如果通過則拼接,不通過直接返回當前的結果

var longestCommonPrefix = function(strs) {
  const s1 = strs[0];
  if (!s1) return "";
  const l1 = s1.length,
    l2 = strs.length;
  if (l2 < 2) return s1;
  let res = "";
  for (let i = 0; i < l1; i++) {
    for (let j = l2 - 1; j; j--) {
      if (s1[i] !== strs[j][i]) {
        return res;
      }
    }
    res += s1[i];
  }
  return res
};

問題:每次拼接沒有必要,

優化思路:只需要記錄下標即可,最後直接用下標截取

  var s1 = strs[0],
    l = strs.length;
  if (!s1) return "";
  if (l < 2) return s1;
  var l1 = s1.length,
    i = 0,
    j,m;
  while (i < l1) {
    j = l - 1;
    m=s1[i]
    while (j) {
      if (m !== strs[j][i]) {
        return s1.substr(0, i);
      }
      j--;
    }
    i++;
  }
  return s1;

2.有效的括號

題目:

給定一個只包括 '(',')','{','}','[',']' 的字符串,判斷字符串是否有效。

有效字符串需滿足:

左括號必須用相同類型的右括號閉合。
左括號必須以正確的順序閉合。
注意空字符串可被認爲是有效字符串。

思路:遍歷字符串,區分(、[、{三種情況,找到對應的右邊字符的位置,注意嵌套的情況,所以用個計數器來記錄相同字符的次數。然後切割當前成對字符中間的字符以及剩餘字符,做一個遞歸處理。如果先遇到右邊的字符直接返回false

var isValid = function(s) {
  var l = s.length;
  if (!l) return true;
  if (l % 2) return false;
  var m,
    i = 0;
  var f = (q, v) => {
    var c = 0;
    for (let j = 1; j < l; j++) {
      if (s[j] === v && !c) return j;
      if (s[j] === q) c++;
      if (s[j] === v) c--;
    }
    return false;
  };
  switch (s[0]) {
    case "(":
      m = f("(", ")");
      if (!m || !(m % 2)) return false;
      return isValid(s.slice(1, m)) && isValid(s.slice(m + 1));
    case "{":
      m = f("{", "}");
      if (!m || !(m % 2)) return false;
      return isValid(s.slice(1, m)) && isValid(s.slice(m + 1));
    case "[":
      m = f("[", "]");
      if (!m || !(m % 2)) return false;
      return isValid(s.slice(1, m)) && isValid(s.slice(m + 1));
    default:
      return false;
  }
};

問題:回溯太多,遞歸次數太多,每個字符都在遍歷,並且可能會遍歷好幾次

優化方向:匹配過程就是相鄰匹配,且內部優先。只有知道右邊的字符,才能匹配相鄰的字符,所以先把左邊的字符放進棧裏,然後遇到右邊的字符,就取最近的一個字符,如果匹配成功則繼續往下遍歷,否則直接返回false

var isValid = function(s) {
  var l = s.length;
  if (l % 2) return false;
  var a = [],
    item,
    v;
  for (let i = 0; i < l; i++) {
    item = s[i];
    if (item === "(" || item === "[" || item === "{") {
      a.push(item);
    } else {
      if (!a.length) return false;
      v = a.pop();
      if (
        (item === ")" && v !== "(") ||
        (item === "]" && v !== "[") ||
        (item === "}" && v !== "{")
      ) {
        return false;
      }
    }
  }
  return !a.length;

};

3.合併兩個有序鏈表

題目:將兩個升序鏈表合併爲一個新的 升序 鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。 

思路:這個和歸併排序的最後一步很像,可以分遞歸和循環兩種方式處理

遞歸:

遞歸的思路,就是每次都找到當前的節點,然後將next指向調用剩下兩個鏈表的結果,最終遞歸處理得到最終的結果

var mergeTwoLists = function(l1, l2) {
  if (!l1 || !l2) {
    return l1 || l2;
  }
  if (l1.val > l2.val) {
    l2.next = mergeTwoLists(l1, l2.next);
    return l2;
  } else {
    l1.next = mergeTwoLists(l1.next, l2);
    return l1;
  }
};

循環:

循環:

循環的思路,是找到每次比較的當前節點,然後用一個變量記錄最終的結果,一個變量記錄上一次比較的結果,這樣在下次得到結果之後把上一次的結果的next指向當前的結果。最後將剩下的節點加入到最後

var mergeTwoLists = function(l1, l2) {
  if (!l1 || !l2) {
    return l1 || l2;
  }
  var res, s;
  while (l1 && l2) {
    if (l1.val > l2.val) {
      s = s || res;
      if (s) {
        s.next = l2;
        s = s.next;
      }
      res = res || l2;
      l2 = l2.next;
    } else {
      s = s || res;
      if (s) {
        s.next = l1;
        s = s.next;
      }
      res = res || l1;
      l1 = l1.next;
    }
  }
  if (s) {
    s.next = l1 || l2;
  } else {
    res.next = l1 || l2;
  }
  return res;
};

4.刪除排序數組中的重複項

題目:

給定一個排序數組,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後數組的新長度。 不要使用額外的數組空間,你必須在 原地 修改輸入數組 並在使用 O(1) 額外空間的條件下完成。

思路:用雙指針的方式,第一個指針就是當前不重複元素的下標,第二個指針是此輪遍歷元素的下標,單次遍歷,從第二項開始,兩個指針上的值比較,如果相等,就進入下一輪循環,如果不相等,就把當前項的值賦值給第一個指針的下一個元素,同時第一個指針加一,進入下一輪循環。

var removeDuplicates = function(nums) {
  var l = nums.length;
  if (l < 2) return l;
  var temp,
    res = 0;
  for (var i = 1; i < l; i++) {
    if (nums[res] !== nums[i]) {
      temp = nums[i];
      nums[i] = nums[res + 1];
      nums[res + 1] = temp;
      res++;
    }
  }
  return res + 1;
};

 

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