JS靈活選擇鍵值

四數相加

給定四個包含整數的數組列表 A , B , C , D ,計算有多少個元組 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。爲了使問題簡單化,所有的 A, B, C, D 具有相同的長度 N,且 0 ≤ N ≤ 500 。所有整數的範圍在 -228 到 228 - 1 之間,最終結果不會超過 231 - 1

示例:

輸入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]

輸出:
2

解釋:
兩個元組如下:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
  • 解題思路
    • 暴力解法,時間複雜度 O(n^4)
    • D 中的元素放入查找表,時間複雜度 O(n^3)
    • 將 A + B 的每一種可能放入查找表,然後 兩重循環對在查找表中尋找是否存在 -(C[i] + D[i]),時間複雜度爲 O(n^2)。兩數相加的和作爲鍵值
//執行用時 :144 ms, 在所有 javascript 提交中擊敗了81.95%的用戶
//內存消耗 :51.3 MB, 在所有 javascript 提交中擊敗了69.23%的用戶
var fourSumCount = function (A, B, C, D) {
  let sumMap = new Map();
  let count = 0;

  for (let a of A) {
    for (let b of B) {
      sumMap.set(a + b, sumMap.get(a + b) ? sumMap.get(a + b) + 1 : 1);
    }
  }

  for (let c of C) {
    for (let d of D) {
      let target = 0 - c - d;
      if (sumMap.has(target)) {
        count += sumMap.get(target);
      }
    }
  }
  return count;
};

字母異位詞分組

給定一個字符串數組,將字母異位詞組合在一起。字母異位詞指字母相同,但排列不同的字符串。說明:所有輸入均爲小寫字母且不考慮答案輸出的順序。

示例:

輸入: ["eat", "tea", "tan", "ate", "nat", "bat"],
輸出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]
  • 排序後的字符串作爲key
//執行用時 :156 ms, 在所有 javascript 提交中擊敗了62.75%的用戶
//內存消耗 :45.7 MB, 在所有 javascript 提交中擊敗了55.43%的用戶
var groupAnagrams = function (strs) {
  var tag = {};
  var res = [];
  strs.forEach((item) => {
    let oderStr = item.split('').sort().join('');
    if (tag.hasOwnProperty(oderStr)) {
      tag[oderStr].push(item);
    } else {
      tag[oderStr] = [item];
    }
  })

  for (var key in tag) {
    res.push(tag[key]);
  }

  return res;
};
  • map
//執行用時 :144 ms, 在所有 javascript 提交中擊敗了83.75%的用戶
//內存消耗 :47.1 MB, 在所有 javascript 提交中擊敗了29.34%的用戶
const groupAnagrams = function (strs) {
  let sMap = new Map();
  for (let ss of strs) {
    let curr = ss.split('').sort(function (a, b) {
      return a.charCodeAt(0) - b.charCodeAt(0);
    }).join('');
    let tmp = (sMap.get(curr) || []);
    tmp.push(ss);
    sMap.set(curr, tmp);
  }
  return Array.from(sMap.values());  //return [... sMap.values()];
};

迴旋鏢的數量

給定平面上 n 對不同的點,“迴旋鏢” 是由點表示的元組 (i, j, k) ,其中 i 和 j 之間的距離和 i 和 k 之間的距離相等(需要考慮元組的順序)。找到所有迴旋鏢的數量。你可以假設 n 最大爲 500,所有點的座標在閉區間 [-10000, 10000] 中。

示例:

輸入:
[[0,0],[1,0],[2,0]]

輸出:
2

解釋:
兩個迴旋鏢爲 [[1,0],[0,0],[2,0]] 和 [[1,0],[2,0],[0,0]]
  • 解題思路
    • 暴力解法:三重循環枚舉所有的可能性。 時間複雜度爲:O(n^3)
    • 使用查找表:觀察到 i 是一個 “樞紐”,對於每個點i,遍歷其餘點到 i 的距離對於每個樞紐i,計算它到其它點j的距離,並將距離作爲鍵存入字典 dict 中,value爲距離的個數。時間複雜度爲:O(n^2)。 距離作爲鍵值
//執行用時 :180 ms, 在所有 javascript 提交中擊敗了89.47%的用戶
//內存消耗 :41.7 MB, 在所有 javascript 提交中擊敗了59.38%的用戶
var numberOfBoomerangs = function (points) {
  var len = points.length;

  var count = 0;
  for (let i = 0; i < len; i++) {
    let sumMap = new Map();
    for (let j = 0; j < len; j++) {
      if (i === j) continue;
      let sum = getDis(points[i], points[j]);  //節省內存可以直接計算d = dx * dx + dy * dy
      if (sumMap.has(sum)) {
        let num = sumMap.get(sum);
        count += num;
        sumMap.set(sum, num + 1);
      } else {
        sumMap.set(sum, 1);
      }
      //上述map條件判斷可以簡寫爲 let count = ~~map.get(dis);
    }
  }
  return count * 2;
};

function getDis(point1, point2) {
  return (point1[0] - point2[0]) * (point1[0] - point2[0]) + (point1[1] - point2[1]) * (point1[1] - point2[1]);
}

直線上最多的點數

給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。

示例:

輸入: [[1,1],[2,2],[3,3]]
輸出: 3
解釋:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4
輸入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
輸出: 4
解釋:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6
  • 兩點可以確定一條直線,那麼選擇固定一個點,求其他點與固定點的斜率,如果斜率相同,那麼斜率相同的點在同一條直線上。同時要考慮,斜率可能爲無窮大,也有可能兩個點爲同一個點。鍵值應該爲:斜率
//執行用時 :88 ms, 在所有 javascript 提交中擊敗了78.05%的用戶
//內存消耗 :38 MB, 在所有 javascript 提交中擊敗了60.00%的用戶
var maxPoints = function (points) {
  //求最大公約數
  function gcd(x, y) {
    if (y === 0) {
      return x;
    }
    return gcd(y, x % y);
  }

  if (points.length <= 2) {
    return points.length;
  }

  let result = Number.MIN_SAFE_INTEGER;

  for (let i = 0; i < points.length - 1; ++i) {
    let max = 0;
    let repeat = 0;
    let slope = new Map();

    for (let j = i + 1; j < points.length; ++j) {
      let dx = points[i][0] - points[j][0];
      let dy = points[i][1] - points[j][1];

      if (dy === 0 && dx === 0) {
        ++repeat;
        continue;
      }

      const g = gcd(dy, dx);  
      if (g !== 0) {
        dx /= g;
        dy /= g;
      }

      const key = `${dx}/${dy}`;
      let count = (slope.get(key) || 0) + 1;

      slope.set(key, count);
      max = Math.max(max, count);
    }
    result = Math.max(result, repeat + max + 1);
  }

  return result;
};

//執行用時 :112 ms, 在所有 javascript 提交中擊敗了48.78%的用戶
//內存消耗 :38.5 MB, 在所有 javascript 提交中擊敗了60.00%的用戶
var maxPoints = function (points) {
  if (points.length == 0)
    return 0;
  var result = 0,
    pointsMap = new Map();
  for (var i = 0; i < points.length; i++) {
    if (pointsMap.has(points[i].toString())) {
      pointsMap.set(points[i].toString(), pointsMap.get(points[i].toString()) + 1);  //統計相同座標數
    } else {
      pointsMap.set(points[i].toString(), 1);
    }
  }
  var pointsArr = [...pointsMap];  //解構賦值,包含key和value的二維數組
  console.log(pointsArr);
  if (pointsArr.length == 1)
    return pointsArr[0][1];
  for (var i = 0; i < pointsArr.length; i++) {
    var map = new Map();
    for (var ii = i + 1; ii < pointsArr.length; ii++) {
      var res = 0;
      if (pointsArr[i][0].split(",")[0] - pointsArr[ii][0].split(",")[0] === 0)  //x軸座標相同
        res = "y";
      if (pointsArr[i][0].split(",")[1] - pointsArr[ii][0].split(",")[1] === 0)  //y軸座標相同
        res = "x";
      res = res == 0 ? (pointsArr[i][0].split(",")[0] - pointsArr[ii][0].split(",")[0]) / (pointsArr[i][0].split(",")[1] - pointsArr[ii][0].split(",")[1]) : res;   //
      if (map.has(res)) {
        map.set(res, map.get(res) + pointsArr[ii][1]);   //相同斜率下,相同y座標的數量
      } else {
        map.set(res, pointsArr[ii][1] + pointsArr[i][1]);  //重複座標數
      }
    }
    map.forEach((value, key) => {
      result = result > value ? result : value;
    });
  }
  return result;
};

來源:力扣(LeetCode)https://leetcode-cn.com

發佈了54 篇原創文章 · 獲贊 13 · 訪問量 9144
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章