JavaScript TypeError:无法读取undefined的属性'0'及共线点数问题解决
计算共线最大点数时的TypeError问题分析与解决
问题场景
在实现计算给定坐标点数组中共线最大点数的JavaScript函数时,出现TypeError: Cannot read properties of undefined (reading '0')错误。
原代码
/** * @param {number[][]} points * @return {number} */ var maxPoints = function(points) { n=0 for(let i=0;i<=points.length;i++){ let x=points[i] const y=points[i+1] let dx=y[0]-x[0] let dy=y[1]-x[1] m=dy/dx b = y[1]-m*y[0] newy=m*y[0]+b if(newy==y[1]){ n++ } console.log(y) } return(n) };
报错信息
Line 10 in solution.js let deltax=y[0]-x[0] ^ TypeError: Cannot read properties of undefined (reading '0') Line 10: Char 17 in solution.js (maxPoints) Line 31: Char 19 in solution.js (Object.<anonymous>) Line 16: Char 8 in runner.js (Object.runner) Line 22: Char 26 in solution.js (Object.<anonymous>) at Module._compile (node:internal/modules/cjs/loader:1101:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) at node:internal/main/run_main_module:17:47
错误原因
- 循环边界错误:循环条件
i<=points.length会让i取到points.length的值,此时points[i]是undefined(数组索引从0开始,最大有效索引为points.length-1),points[i+1]更是超出数组范围,直接导致y变量为undefined,访问y[0]触发类型错误。 - 核心逻辑错误:原代码仅遍历相邻点计算直线方程并验证,完全没覆盖所有点之间的共线情况,同时忽略了垂直直线(dx=0时会出现除以0的NaN)、重复点等特殊场景,根本无法正确计算共线最大点数。
解决方法
步骤1:临时修复报错(仅解决边界问题)
将循环条件改为i < points.length - 1,确保points[i]和points[i+1]都能取到有效元素,但这只是临时解决报错,无法完成正确功能。
步骤2:实现正确的共线点数计算逻辑
正确的算法思路是通过统计每个基准点与其他点的斜率(用分数形式避免浮点数精度问题),来统计共线点的数量:
/** * @param {number[][]} points * @return {number} */ var maxPoints = function(points) { const len = points.length; // 点数<=2时,所有点必然共线 if (len <= 2) return len; let maxCount = 1; // 遍历每个点作为基准点 for (let i = 0; i < len; i++) { const slopeMap = new Map(); let samePointCount = 0; let currentMax = 0; const [x1, y1] = points[i]; // 遍历其他点,计算与基准点的斜率 for (let j = 0; j < len; j++) { if (i === j) continue; const [x2, y2] = points[j]; let dx = x2 - x1; let dy = y2 - y1; // 处理重复点(和基准点坐标完全相同) if (dx === 0 && dy === 0) { samePointCount++; continue; } // 计算最简分数形式的斜率,避免浮点数精度问题 const gcdVal = gcd(Math.abs(dx), Math.abs(dy)); // 统一符号,避免不同key对应同一斜率 const key = `${dy / gcdVal}/${dx / gcdVal}`; slopeMap.set(key, (slopeMap.get(key) || 0) + 1); currentMax = Math.max(currentMax, slopeMap.get(key)); } // 当前基准点的最大共线点数 = 同斜率点数 + 重复点数 + 基准点自身 maxCount = Math.max(maxCount, currentMax + samePointCount + 1); } return maxCount; }; // 辅助函数:计算最大公约数 function gcd(a, b) { while (b !== 0) { [a, b] = [b, a % b]; } return a; }
代码说明
- 特殊情况处理:当点数≤2时直接返回点数,无需额外计算。
- 斜率统计:用
Map存储每个斜率对应的点数量,通过最大公约数将斜率转为最简分数字符串,避免浮点数精度误差(比如0.1和0.1000000001被误判为不同斜率)。 - 重复点处理:单独统计与基准点完全相同的点,这些点必然和基准点共线。
- 最大值计算:每个基准点的最大共线点数为同斜率点数量+重复点数量+基准点自身,最终取全局最大值。
内容的提问来源于stack exchange,提问作者jeevan Kumar
相关产品推荐
相关产品推荐

