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