149. 直线上最多的点数
题目: 给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
解法1:暴力求解
思路: 利用基准点和斜率(y1-y2/x1-x2),两层循环,每次将与基准点构成的不同斜率存在hash中,相同则计数,一趟下来求max。
注意点:需要区别y1-y2 === 0 和 x1-x2 === 0 的情况。
时间复杂度: O(n^2)
空间复杂度:O(n)
var maxPoints = function(points) {
// 经过某点的斜率
let max = 0;
for(let i = 0; i < points.length; i++) {
max === 0 ? max = 1 : null;
const hash = {};
for(let j = i+1; j < points.length; j++) {
const k = points[i][0]-points[j][0] === 0 ? '+0' : (points[i][1]-points[j][1])/(points[i][0]-points[j][0]);
hash[k] ? hash[k]++ : hash[k] = 2;
};
for(let i in hash) {
max = Math.max(max, hash[i]);
}
}
return max;
};
优化:
- 在点的总数量小于等于 2 的情况下,我们总可以用一条直线将所有点串联,此时我们直接返回点的总数量即可;
- 当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
- 当我们枚举到点 i(假设编号从 0 开始)时,我们至多只能找到 n−i 个点共线。假设此前找到的共线的点的数量的最大值为 k,如果有 k≥n−i,那么此时我们即可停止枚举,因为不可能再找到更大的答案了。
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/max-points-on-a-line/solution/zhi-xian-shang-zui-duo-de-dian-shu-by-le-tq8f/
var maxPoints = function(points) {
// 经过某点的斜率
let max = 0;
// 优化1
if (points.length <= 2) return points.length;
for(let i = 0; i < points.length; i++) {
// 优化2
if (max > Math.floor(points.length / 2) || max >= points.length - i) {
break;
}
const hash = {};
for(let j = i+1; j < points.length; j++) {
const k = points[i][0]-points[j][0] === 0 ? '+0' : (points[i][1]-points[j][1])/(points[i][0]-points[j][0]);
hash[k] ? hash[k]++ : hash[k] = 2;
};
for(let i in hash) {
max = Math.max(max, hash[i]);
}
}
return max;
};
学生方阵(huawei机试)
思路: 分别在各个方向上统计连续1的个数,取max。
时间复杂度O(n^m
m^n
2(Math(m, n)^n
Math(m,n)^m))
// 定义女:0, 男: 1
// 分类讨论
// 水平方向
var row = function (arr) {
let max = 0;
for(let i = 0; i < arr.length; i++) {
let front, count = 0;
for(let j = 0; j < arr[i].length; j++) {
if (arr[i][j]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
return max;
}
// 竖直方向
var column = function (arr) {
let max = 0;
for(let i = 0; i < arr[0].length; i++) {
let front, count = 0;
for(let j = 0; j < arr.length; j++) {
if (arr[j][i]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
return max;
}
// 对角线
var xie = function (arr) {
let max = 0;
// 下三角
for(let l = 0; l < arr.length ; l++) {
let front, count = 0;
for(let i = l, j = 0; i < arr.length && j < arr[0].length; j++, i++) {
if (arr[i][j]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
// 上三角
for(let l = 1; l < arr[0].length ; l++) {
let front, count = 0;
for(let i = 0, j = l; i < arr.length && j < arr[0].length; j++, i++) {
if (arr[i][j]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
return max;
}
var fanXie = function (arr) {
let max = 0;
// 上三角
for(let l = 0; l < arr[0].length ; l++) {
let front, count = 0;
for(let i = 0, j = l; i < arr.length && j > -1; j--, i++) {
if (arr[i][j]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
// 下三角
for(let l = 1; l < arr.length ; l++) {
let front, count = 0;
for(let i = l, j = arr[0].length - 1; i < arr.length && j > -1; j--, i++) {
if (arr[i][j]) {
count = front ? count + 1 : 1;
front = 1;
} else {
front = 0;
}
max = Math.max(max, count);
}
}
return max;
}
var getLianCount = function (arr) {
let rowMax = row(arr);
let colMax = column(arr);
let xieMax = xie(arr);
let fanXieMax = fanXie(arr);
return Math.max(rowMax, colMax, xieMax, fanXieMax);
}
console.log(getLianCount([
[1,0,0,1],
[1,1,0,1],
[1,1,1,0]
]))