四數相加
給定四個包含整數的數組列表 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