【力扣日记】633 平方数之和 | 双指针

题目描述

给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a 2 + b 2 = c a^2 + b^2 = c

算法思路

第一遍嵌套循环,本就想着可能超时。求超得超。
好在之后突然想到优化的方法:双指针

双指针

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
        '''
发布了210 篇原创文章 · 获赞 20 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Heart_for_Ling/article/details/104865550