算法中关于大数除法的精度问题
问题
大数除法会有浮点数误差(精度问题)。
解决方案
示例:294力扣周赛第3题表示一个折线图的最少线段数
其中需要计算斜率并比较。
转换为乘法
通常相到直接比较斜率(y3-y2)/(x3-x2)==(y2-y1)/(x2-x1)?
然而除法计算涉及到精度问题。
不妨将公式转化为乘法,乘法一定不存在精度问题!
(y3-y2)×(x2-x1)==(y2-y1)×(x3-x2) ?
class Solution:
def minimumLines(self, stockPrices):
n=len(stockPrices)
if n==1:
return 0
stockPrices.sort()
t=1
for i in range(2,n):
if (stockPrices[i][1]-stockPrices[i-1][1])*(stockPrices[i-1][0]-stockPrices[i-2][0])!=(stockPrices[i-1][1]-stockPrices[i-2][1])*(stockPrices[i][0]-stockPrices[i-1][0]):
t+=1
return t
辗转相除法
欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。计算公式gcd(a,b) = gcd(b,a mod b)。
gcd(greatest common divisor):最大公约数
e.g.,求 1997 和 615 两个正整数的最大公约数:
- 1997 / 615 = 3 (余 152)
- 615 / 152 = 4(余7)
- 152 / 7 = 21(余5)
- 7 / 5 = 1 (余2)
- 5 / 2 = 2 (余1)
- 2 / 1 = 2 (余0)
至此,最大公约数为1。
回到示例,核心思路是利用辗转相除法,化简斜率k的分子分母,将最简式进行比较。
from math import gcd
class Solution:
def minimumLines(self, stockPrices):
n=len(stockPrices)
if n==1:
return 0
stockPrices.sort()
prex=stockPrices[1][0]-stockPrices[0][0]
prey=stockPrices[1][1]-stockPrices[0][1]
g=gcd(abs(prex),abs(prey))
prex,prey=prex/g,prey/g
t=1
for i in range(2,n):
x = stockPrices[i][0] - stockPrices[i-1][0]
y = stockPrices[i][1] - stockPrices[i-1][1]
g=gcd(abs(x),abs(y))
x,y=x/g,y/g
if prex!=x or prey!=y:
t+=1
prex,prey=x,y
return t

浙公网安备 33010602011771号