1. 问题背景与核心挑战
在二维平面上给定一组坐标点,如何高效找出位于同一条直线上的最多点数?这是LeetCode 149题的经典算法问题。乍看简单,实则暗藏多个技术难点:
浮点精度陷阱:直接计算斜率(y2-y1)/(x2-x1)会导致浮点数比较误差。例如1/3与2/6数学上相等,但计算机浮点表示可能判定为不同。
边界情况处理:垂直线(x坐标相同)和水平线(y坐标相同)需要特殊处理,避免除零错误。
算法效率:当点数达到300时,暴力解法O(n³)的时间复杂度将导致性能瓶颈。
我在实际解题中发现,采用斜率统计法配合最大公约数(GCD)约分,能完美解决上述问题。下面详细解析这个方案的实现细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法核心思路拆解
2.1 数学基础:三点共线判定
判断三个点(x1,y1)、(x2,y2)、(x3,y3)是否共线,可通过向量叉积是否为0来确定:
code复制(x2-x1)*(y3-y1) == (x3-x1)*(y2-y1)
这个等式避免了除法运算,但直接用于所有三点组合会导致O(n³)时间复杂度。
2.2 斜率统计法优化
更聪明的做法是固定一个基点,计算与其他点的斜率:
- 遍历每个点作为基点
- 计算该点与其余各点的斜率
- 统计相同斜率出现的次数
- 最大出现次数+1即为当前基点的共线点数
关键突破:用分数的最简形式表示斜率,通过GCD约分避免浮点误差。例如:
- 斜率4/2约分为2/1
- 斜率3/9约分为1/3
2.3 特殊斜率处理
- 垂直线:dx=0时,统一表示为(0,1)
- 水平线:dy=0时,统一表示为(1,0)
- 重合点:虽然题目说明点互异,但实际编码时可增加计数器处理
3. C语言实现详解
3.1 GCD辅助函数
c复制int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
使用欧几里得算法递归求解最大公约数。例如gcd(12,8)计算过程:
- gcd(12,8) → gcd(8,4)
- gcd(8,4) → gcd(4,0)
- 返回4
3.2 主算法实现
c复制int ma
