python正整数平方根_Python3算法之四:x的平方根

关注微信公众号“酸痛鱼”,获得更多最新最全的文章。

本文中所涉及的代码,在未特殊声明的情况下,都是基于Python3程序设计语言编写的。

建议您在PC浏览器中阅读本文。

如果您未掌握知识提要中的内容,建议您先掌握这些内容之后再阅读本文。

知识提要

1、math库

2、int取整操作

3、牛顿迭代(未掌握不影响对本文的理解)

4、二分查找(未掌握不影响对本方的理解)

0

问题描述

给定一个非负整数x,求x的正数平方根r。要求:只保留正数根的整数部分。

例如:

当x = 2时,r = 1。(2的平方根约为1.414)

当x = 4时,r = 2。(4的平方根为2)

当x = 8时,r = 2。(8的平方根约为2.828)

为了表述方便,在本文中,我们直接将“正数平方根”称为“平方根”,在无歧义的情况下,会直接称为r。

1

系统函数法

大部分编程语言都提供了丰富的数值操作的系统函数,例如向上取整ceil,向下取整floor,求平方根sqrt,等等。Python当然也不例外。对于本章题目,最简单和最高效的解法,就是利用系统函数,先求x的平方根,再向下取整。

import math

def mySqrt(x):

# 求x的根,并向下取整,相当于math.floor(math.sqrt(x))

return int(math.sqrt(x))

如果这是一个竞赛题目,而没有禁止使用系统函数,那么如上的代码绝对是最优解。出于“学术”讨论和拓展学习的目的,我们将在本文中重点讨论其它的解题思路。

2

暴力破解法

对于任意大于1的正整数x,它的平方根一定不大于x的一半。利用这个特点,我们可以从x/2开始,不停地向左探索,直到到第一次找到一个数r,满足r的平方不大于x,此时,r就是我们的解。

def mySqrt(x):

if x <= 1: return x

r = x // 2

while r > 1:

if r * r <= x:

return r

else:

r -= 1

return 1

不得不提的是,这种解法是存在严重的效率问题。当x值为1亿的时候,在我的计算机上,大概花了4秒钟的运行时间。如果你在比赛中使用这种解法,极有可能因为运行时间过长而被判定为解题失败。

3

牛顿迭代法

在这里,我将假设你知道什么是牛顿迭代。不过如果你只是专注于题目本身的求解,你只需要知道牛顿迭代怎么用就行了,可以不必了解它的原理。

假设r{n}表示第n次迭代的值,那么迭代公式为:

r{n+1}= (r{n} + x/r{n})/2

由于我们求解的精度为保留小数点0位,即取整,所以我们只需要迭代到r{n+1}和r{n}的整数部分相等时即可。此时r{n+1}的整数部分就是我们的解。

def mySqrt(x):

r = 1

n = 0

while int(r) != int(n):

n = r

r = (n + x / n) / 2

return int(r)

4

二分查找法

给定一个整数q,在升序的有序整数数列A中,找到q的位置。我们用A(i)表示A的第i个元素,用A(i, j)表示A中第i个到第个j的元素集合。假如A的长度为len,则A的最大下标e=len-1。如果q是A中元素,那么q一定落在A(0,e)中。我们可以通以下的步骤进行有限次的迭代,得到结果:

A、令s = 0,e = len - 1

B、如果s > e;跳转到G

C、令m = (s + e) / 2

D、如果A(m) < q,q的范围缩小为A(m + 1, e);可令s = m + 1,跳转到B;

E、如果A(m) > q,q的范围缩小为A(s, m - 1);可令e = m - 1,跳转到B;

F、如果A(m) == q,那么m就是q在A中的位置;查找结束

G、q不在数组A中。查找结束

对于我们的题目,也就是求解x平方根r的题目来说,模型退化了,A相当于整数数组[1,2,3,……,x],而且一定有解。我们还需要稍微改造一下,就是在A(1, x)中,找到A(m),满足A(m)^2 <= x < A(m+1)^2。事实上,就是在1到x中,找到m,满足m^2 <= x < (m+1)^2。

def mySqrt(x):

if x <= 1: return x

s, e = 1, x # A

while s <= e: # B

m = (s + e) // 2 # C

val1, val2 = m * m, (m + 1) * (m + 1)

if val1 <= x < val2: # F

return m

if val1 < x: # D

s = m + 1

else: # E

e = m - 1

return -1 # G●微信 扫码关注会变帅哦

酸痛鱼,与你分享快乐的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值