🔗 🟡 633. Sum of Square Numbers

題意

給定一個非負整數 cc ,檢查是否存在兩個整數 aabb ,使得 a2+b2=ca^2 + b^2 = c

若存在則返回 true\text{true} ,否則返回 false\text{false}

思路

方法一:枚舉(Enumeration)

如果能夠確定 aa 的值,那便可以透過計算 b=ca2b = \sqrt{c - a^2} 來確定 bb 的值。因此,可以從 a=0a = 0 開始 枚舉(Enumeration) ,直到 a2ca^2 \leq c 為止,計算 bb 的值,檢查是否存在整數解滿足 a2+b2=ca^2 + b^2 = c 的條件。

檢查是否滿足條件時,可以檢查 bb 是否為整數,也可以透過計算 a2+b2a^2 + b^2 是否等於 cc 來判斷,但前者的計算量較小。

複雜度分析

  • 時間複雜度:O(c)\mathcal{O}(\sqrt{c}),枚舉 aa 的範圍為 [0,c][0, \sqrt{c}]
  • 空間複雜度:O(1)\mathcal{O}(1)
1
2
3
4
5
6
7
8
class Solution:
def judgeSquareSum(self, c: int) -> bool:
for x in range(int(c**0.5)+1):
# 也可以用 double y,然後判斷 y == int(y)
y = int((c - x**2)**0.5)
if x ** 2 + y ** 2 == c:
return True
return False
1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
bool judgeSquareSum(int c) {
for (LL x = 0; x * x <= c; x++){
double y = sqrt(c - x * x);
if (y == (int)y){
return true;
}
}
return false;
}
};

方法二:雙指標(Two Pointers)

由於 a,b[0,c]a, b \isin [0, \sqrt{c}] ,可以假設 aba \leq b ,並使用 雙指針(Two Pointers) 的方法來解決問題。

初始化兩個指標 aabb ,分別指向範圍 [0,c][0, \sqrt{c}] 的兩端,並根據目前指向的值的平方和與 cc 的大小關係調整指針的位置。

  • 如果 a2+b2=ca^2 + b^2 = c ,則返回 true\text{true} ,表示找到解。
  • 如果 a2+b2<ca^2 + b^2 < c ,則表示目前的和太小,需要增加和,移動 aa 指針。
  • 如果 a2+b2>ca^2 + b^2 > c ,則表示目前的和太大,需要減少和,移動 bb 指針。

重複上述步驟,直到 a>ba > b 為止,表示沒有找到解,返回 false\text{false}

複雜度分析

  • 時間複雜度:O(c)\mathcal{O}(\sqrt{c}),在範圍 [0,c][0, \sqrt{c}] 內移動兩個指針。
  • 時間複雜度:O(1)\mathcal{O}(1)
1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def judgeSquareSum(self, c: int) -> bool:
left, right = 0, int(c**0.5)
while left <= right:
cur = left**2 + right**2
if cur == c:
return True
elif cur < c: # 太小
left += 1
else: # 太大
right -= 1
return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
bool judgeSquareSum(int c) {
LL l = 0, r = sqrt(c);
while (l <= r){
LL cur = l * l + r * r;
if (cur == c){
return true;
} else if (cur > c){
r--;
} else {
l++;
}
}
return false;
}
};

寫在最後

Cover photo is generated by @ゴリラの素材屋さん, thanks for their work!