js解leetcode(32)-中等

一笑而泯發表於2020-11-23

1.替換後的最長重複字串

題目:

給你一個僅由大寫英文字母組成的字串,你可以將任意位置上的字元替換成另外的字元,總共可最多替換 k 次。在執行上述操作後,找到包含重複字母的最長子串的長度。

注意:
字串長度 和 k 不會超過 104。

思路:雙指標法,用一個left指向字串的左側位置,一個map記錄每個字元出現的次數。遍歷字串,更新出現次數最多的字串出現的次數,並判斷此時的刪除字元的數量,如果刪除的字元比k大,那麼left右移,更新出現最多的字元次數。

時間複雜度O(n),空間複雜度O(n)


/**
 * @param {string} s
 * @param {number} k
 * @return {number}
 */
var characterReplacement = function(s, k) {
  const l = s.length;
  if (k >= l - 1) return l;
  const map = {
    [s[0]]: 1,
  };
  let max = 1;
  let res = 0;
  let left = 0;
  for (let i = 1; i < l; i++) {
    map[s[i]] = (map[s[i]] || 0) + 1;
    max = Math.max(map[s[i]], max);
    while (i + 1 - left - max > k) {
      map[s[left]]--;
      left++;
      const keys = Object.keys(map);
      max = 0;
      keys.forEach((item) => {
        max = Math.max(map[item], max);
      });
    }
    res = Math.max(res, i - left + 1);
  }
  return res;
};

注意到,left左移之後,只需要減去對應字元的出現,不需要遍歷map更新字元出現次數

時間複雜度O(n),空間複雜度O(1)

/**
 * @param {string} s
 * @param {number} k
 * @return {number}
 */
var characterReplacement = function(s, k) {
  let left = 0,
    max = 0;
  const map = new Map();
  for (let i = 0; i < s.length; i++) {
    map.set(s[i], (map.get(s[i]) || 0) + 1);
    max = Math.max(map.get(s[i]), max);
    if (i - left + 1 - max > k) {
      map.set(s[left], map.get(s[left]) - 1);
      left++;
    }
  }
  return s.length - left;
};

2.建立四叉樹

題目:

給你一個 n * n 矩陣 grid ,矩陣由若干 0 和 1 組成。請你用四叉樹表示該矩陣 grid 。

你需要返回能表示矩陣的 四叉樹 的根結點。

注意,當 isLeaf 為 False 時,你可以把 True 或者 False 賦值給節點,兩種值都會被判題機制 接受 。

四叉樹資料結構中,每個內部節點只有四個子節點。此外,每個節點都有兩個屬性:

  • val:儲存葉子結點所代表的區域的值。1 對應 True,0 對應 False
  • isLeaf: 當這個節點是一個葉子結點時為 True,如果它有 4 個子節點則為 False 。

思路:dfs遞迴處理

/**
 * // Definition for a QuadTree node.
 * function Node(val,isLeaf,topLeft,topRight,bottomLeft,bottomRight) {
 *    this.val = val;
 *    this.isLeaf = isLeaf;
 *    this.topLeft = topLeft;
 *    this.topRight = topRight;
 *    this.bottomLeft = bottomLeft;
 *    this.bottomRight = bottomRight;
 * };
 */

/**
 * @param {number[][]} grid
 * @return {Node}
 */
var construct = function(grid) {
        function subConstruct(grid, i, j, length) {
        if (length === 1) return new Node(grid[i][j] === 1 ? true : false, true)
        let mark = true
        let num = grid[i][j]
        for (let a = i; a < i + length; a++) {
            for (let b = j; b < j + length; b++) {
                if (num !== grid[a][b]) {
                    mark = false
                    break;
                }
            }
        }
        if (mark) return new Node(grid[i][j] === 1 ? true : false, true)
        let now = new Node(true, false)
        now.topLeft = subConstruct(grid, i, j, length >> 1)
        now.topRight = subConstruct(grid, i, j + (length >> 1), length >> 1)
        now.bottomLeft = subConstruct(grid, i + (length >> 1), j, length >> 1)
        now.bottomRight = subConstruct(grid, i + (length >> 1), j + (length >> 1), length >> 1)
        return now
    }
    return subConstruct(grid, 0, 0, grid.length)
};

 3.N叉樹的層序遍歷

題目:給定一個 N 叉樹,返回其節點值的層序遍歷。 (即從左到右,逐層遍歷)。

思路:和二叉樹幾乎一樣

迭代:

/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
  const res = [];
  if (!root) return res;
  let stack = [root];
  while (stack.length) {
    res.push(stack.map((item) => item.val));
    stack = stack.reduce((res, item) => {
      res.push(...item.children);
      return res;
    }, []);
  }
  return res;
};

遞迴:


/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node} root
 * @return {number[][]}
 */
var levelOrder = function (root, level = 0, res = []) {
  if (!root) return res;
  if (res[level]) {
    res[level].push(root.val);
  } else {
    res[level] = [root.val];
  }
  return root.children.reduce(
    (res, item) => levelOrder(item, level + 1, res),
    res
  );
};

4.扁平化多級雙向連結串列

題目:

多級雙向連結串列中,除了指向下一個節點和前一個節點指標之外,它還有一個子連結串列指標,可能指向單獨的雙向連結串列。這些子列表也可能會有一個或多個自己的子項,依此類推,生成多級資料結構,如下面的示例所示。

給你位於列表第一級的頭節點,請你扁平化列表,使所有結點出現在單級雙連結串列中。

思路:借用棧,對於一個節點,先將下級節點入棧,然後將child入棧,這其實就是child優先處理,也就是dfs。用一個變數記錄上一輪處理的節點,記得入棧之後,重置當前節點的child和next為null即可

/**
 * // Definition for a Node.
 * function Node(val,prev,next,child) {
 *    this.val = val;
 *    this.prev = prev;
 *    this.next = next;
 *    this.child = child;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var flatten = function(head) {
  if (!head) return null;
  const stack = [head.child, head.next];
  head.next = null;
  head.child = null;
  head.child = unf;
  let cur = head;
  while (stack.length) {
    const item = stack.shift();
    if (!item) continue;
    stack.unshift(item.child, item.next);
    cur.next = item;
    item.prev = cur;
    item.child = null;
    item.next = null;
    cur = item;
  }
  return head;
};

5.最小基因變化

題目:

一條基因序列由一個帶有8個字元的字串表示,其中每個字元都屬於 "A""C""G""T"中的任意一個。

假設我們要調查一個基因序列的變化。一次基因變化意味著這個基因序列中的一個字元發生了變化。

例如,基因序列由"AACCGGTT" 變化至 "AACCGGTA" 即發生了一次基因變化。

與此同時,每一次基因變化的結果,都需要是一個合法的基因串,即該結果屬於一個基因庫。

現在給定3個引數 — start, end, bank,分別代表起始基因序列,目標基因序列及基因庫,請找出能夠使起始基因序列變化為目標基因序列所需的最少變化次數。如果無法實現目標變化,請返回 -1。

注意:

  1. 起始基因序列預設是合法的,但是它並不一定會出現在基因庫中。
  2. 所有的目標基因序列必須是合法的。
  3. 假定起始基因序列與目標基因序列是不一樣的。

思路:這題和之前一題路徑的很像。對於起點,進行dfs遍歷,找到和它相差1的字元,然後繼續遞迴處理。可以將使用過的字元標記,這樣就不會迴圈了

/**
 * @param {string} start
 * @param {string} end
 * @param {string[]} bank
 * @return {number}
 */
var minMutation = function(start, end, bank) {
    if(start == end){
        return 0;
    }else if(!bank || bank.length == 0){
        return -1;
    }
    var visited = new Map();
    var minLevel = Number.MAX_SAFE_INTEGER;
    var level = 0;
    function recurse(start,level){
        if(start == end){
            minLevel = Math.min(minLevel,level);
        }
        for(var i = 0;i<bank.length;i++){
            var tmpBank = bank[i];
            var diff = 0;
            for(var r = 0;r<tmpBank.length;r++){
                if(start[r] != tmpBank[r]){
                    diff++;
                    if(diff > 1){
                        break;
                    }
                }
            }
            if(diff == 1 && !visited.has(tmpBank)){
                visited.set(tmpBank,true);
                recurse(tmpBank,level+1);
                visited.delete(tmpBank);
            }
        }
    }
   recurse(start,level);
   return (minLevel === Number.MAX_SAFE_INTEGER)  ? -1 : minLevel;

};

 

 

相關文章