经过40多分钟才写出来,应该还是思路的问题。
但是通过了我就很开心
1 class Solution: 2 def judgeSquareSum(self, c: int) -> bool: 3 if c==0: 4 return True 5 6 i=int((c//2)**0.5) 7 j=int((c//2)**0.5)+1 8 while i<int(c**0.5)+1 and j>=0: 9 if i**2+j**2==c: 10 return True 11 elif i**2+j**2>c: 12 j=j-1 13 elif i**2+j**2<c: 14 i=i+1 15 else: 16 return False
执行用时 :940 ms, 在所有 Python3 提交中击败了5.23%的用户
内存消耗 :13.8 MB, 在所有 Python3 提交中击败了8.44%的用户
举个例子:
假如c=78
因为c大于8**2,小于9**2,
所以遍历的时候 i 的大小最大也就是8。因为是两个数的平方和,所以最公平的就是i**2和j**2各占c/2。
所以i的起始值就是从根号c/2开始,到根号c结束;
j从根号2/c+1开始,依次减小,到0结束。
遍历过程以及判断条件如程序中所示
![](https://img2018.cnblogs.com/blog/1783525/201909/1783525-20190925134853552-1666074380.png)
这个我竟然看不懂。。。。。。
然后发现,看不懂是因为我不知道这个定理:
''' 定理:某个正整数是两平方数之和,当且仅当该正整数的所有 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
这个跟我的思路一样,但是比我写的简洁清爽。
while i <= j: total = i * i + j * j
这一句用得很棒。
这就是区别啊,明明也想到了,但是就差一个火候
——2019.9.25