题目描述
给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 。
算法思路
第一遍嵌套循环,本就想着可能超时。求超得超。
好在之后突然想到优化的方法:双指针
双指针
class Solution:
def judgeSquareSum(self, c: int) -> bool:
r=int(c**0.5)+1
l=0
while l<=r:
rec=l**2+r**2
if rec==c:return True
if rec>c:r-=1
elif rec<c:l+=1
return False
执行用时 :324 ms, 在所有 Python3 提交中击败了47.71%的用户
内存消耗 :13.3 MB, 在所有 Python3 提交中击败了6.22%的用户
class Solution:
def judgeSquareSum(self, c: int) -> bool:
l,r=0,int(math.sqrt(c))
while l<=r:
rec=l*l+r*r
if rec==c:return True
elif rec>c:r-=1
elif rec<c:l+=1
return False
class Solution:
def judgeSquareSum(self, c: int) -> bool:
j = int(math.sqrt(c))
i = 0
while i <= j:
total = i * i + j * j
if total > c:
j = j - 1
elif total < c:
i = i + 1
else:
return True
return False
执行用时 :124 ms, 在所有 Python3 提交中击败了93.30%的用户
内存消耗 :13.4 MB, 在所有 Python3 提交中击败了6.22%的用户
数学方法
if c <= 2:
return True
while c % 2 == 0:
c = c // 2
p = 3
while p * p <= c:
index = 0
while c % p == 0:
index += 1
c = c // p
if (p % 4 == 3) and (index % 2 == 1):
return False
p += 2
return c % 4 == 1
'''
解释下Python3最高记录的非双指针解法。 看上去会让人很费解,但是只要知道定理就很好理解了。
if c <= 2:
return True
while c % 2 == 0:
c = c // 2
p = 3
while p * p <= c:
index = 0
while c % p == 0:
index += 1
c = c // p
if (p % 4 == 3) and (index % 2 == 1):
return False
p += 2
return c % 4 == 1
定理:某个正整数是两平方数之和,当且仅当该正整数的所有 4k+3 型素因数的幂次均为偶数。 任何一个正整数都可以因数分解为 c = (2^r)*(p1^n1)*(p2^n2)*...*(pk^nk),其中p1...pk为素因数,n1...nk为因数的幂次。 也就是说有一个形如4k+3的素因数pi,如果ni为奇数,那它就不可能被写为两个整数的平方数之和了。
代码第一步就是将2全部去掉,做素因数分解。
if c <= 2:
return True
while c % 2 == 0:
c = c // 2
做因数分解的同时,判断素因数的类型和幂次。
p = 3
while p * p <= c:
index = 0
while c % p == 0:
index += 1
c = c // p
if (p % 4 == 3) and (index % 2 == 1):
return False
p += 2
分解到最后的c实际上是一个素数,这时候其实判断c是形如4k+1的素数,那肯定可以写为两整数平方和(也可以判断不是形如4k+3的素数也行)
return c % 4 == 1 # 或者 c % 4 != 3
'''