Skip to content

Commit 220c483

Browse files
authoredJun 3, 2024··
feat: update solutions to lc problem: No.367 (#3002)
No.0367.Valid Perfect Square
1 parent c4828ac commit 220c483

File tree

9 files changed

+130
-195
lines changed

9 files changed

+130
-195
lines changed
 

‎solution/0300-0399/0367.Valid Perfect Square/README.md

+44-64
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ tags:
5757

5858
### 方法一:二分查找
5959

60-
不断循环二分枚举数字,判断该数的平方与 `num` 的大小关系,进而缩短空间,继续循环直至 $left \lt right$ 不成立。循环结束判断 $left^2$ 与 `num` 是否相等
60+
我们可以使用二分查找来解决这个问题。定义二分查找的左边界 $l = 1$,右边界 $r = num$,然后在 $[l, r]$ 的范围内查找满足 $x^2 \geq num$ 的最小整数 $x$。最后,如果 $x^2 = num$,则说明 $num$ 是一个完全平方数
6161

62-
时间复杂度$O(logN)$。
62+
时间复杂度 $O(\log n)$,其中 $n$ 是给定的数字。空间复杂度 $O(1)$。
6363

6464
<!-- tabs:start -->
6565

@@ -68,31 +68,25 @@ tags:
6868
```python
6969
class Solution:
7070
def isPerfectSquare(self, num: int) -> bool:
71-
left, right = 1, num
72-
while left < right:
73-
mid = (left + right) >> 1
74-
if mid * mid >= num:
75-
right = mid
76-
else:
77-
left = mid + 1
78-
return left * left == num
71+
l = bisect_left(range(1, num + 1), num, key=lambda x: x * x) + 1
72+
return l * l == num
7973
```
8074

8175
#### Java
8276

8377
```java
8478
class Solution {
8579
public boolean isPerfectSquare(int num) {
86-
long left = 1, right = num;
87-
while (left < right) {
88-
long mid = (left + right) >>> 1;
89-
if (mid * mid >= num) {
90-
right = mid;
80+
int l = 1, r = num;
81+
while (l < r) {
82+
int mid = (l + r) >>> 1;
83+
if (1L * mid * mid >= num) {
84+
r = mid;
9185
} else {
92-
left = mid + 1;
86+
l = mid + 1;
9387
}
9488
}
95-
return left * left == num;
89+
return l * l == num;
9690
}
9791
}
9892
```
@@ -103,15 +97,16 @@ class Solution {
10397
class Solution {
10498
public:
10599
bool isPerfectSquare(int num) {
106-
long left = 1, right = num;
107-
while (left < right) {
108-
long mid = left + right >> 1;
109-
if (mid * mid >= num)
110-
right = mid;
111-
else
112-
left = mid + 1;
100+
int l = 1, r = num;
101+
while (l < r) {
102+
int mid = l + (r - l) / 2;
103+
if (1LL * mid * mid >= num) {
104+
r = mid;
105+
} else {
106+
l = mid + 1;
107+
}
113108
}
114-
return left * left == num;
109+
return 1LL * l * l == num;
115110
}
116111
};
117112
```
@@ -120,61 +115,44 @@ public:
120115
121116
```go
122117
func isPerfectSquare(num int) bool {
123-
left, right := 1, num
124-
for left < right {
125-
mid := (left + right) >> 1
126-
if mid*mid >= num {
127-
right = mid
128-
} else {
129-
left = mid + 1
130-
}
131-
}
132-
return left*left == num
118+
l := sort.Search(num, func(i int) bool { return i*i >= num })
119+
return l*l == num
133120
}
134121
```
135122

136123
#### TypeScript
137124

138125
```ts
139126
function isPerfectSquare(num: number): boolean {
140-
let left = 1;
141-
let right = num >> 1;
142-
while (left < right) {
143-
const mid = (left + right) >>> 1;
144-
if (mid * mid < num) {
145-
left = mid + 1;
127+
let [l, r] = [1, num];
128+
while (l < r) {
129+
const mid = (l + r) >> 1;
130+
if (mid >= num / mid) {
131+
r = mid;
146132
} else {
147-
right = mid;
133+
l = mid + 1;
148134
}
149135
}
150-
return left * left === num;
136+
return l * l === num;
151137
}
152138
```
153139

154140
#### Rust
155141

156142
```rust
157-
use std::cmp::Ordering;
158143
impl Solution {
159144
pub fn is_perfect_square(num: i32) -> bool {
160-
let num: i64 = num as i64;
161-
let mut left = 1;
162-
let mut right = num >> 1;
163-
while left < right {
164-
let mid = left + (right - left) / 2;
165-
match (mid * mid).cmp(&num) {
166-
Ordering::Less => {
167-
left = mid + 1;
168-
}
169-
Ordering::Greater => {
170-
right = mid - 1;
171-
}
172-
Ordering::Equal => {
173-
return true;
174-
}
145+
let mut l = 1;
146+
let mut r = num as i64;
147+
while l < r {
148+
let mid = (l + r) / 2;
149+
if mid * mid >= (num as i64) {
150+
r = mid;
151+
} else {
152+
l = mid + 1;
175153
}
176154
}
177-
left * left == num
155+
l * l == (num as i64)
178156
}
179157
}
180158
```
@@ -185,11 +163,11 @@ impl Solution {
185163

186164
<!-- solution:start -->
187165

188-
### 方法二:转换为数学问题
166+
### 方法二:数学
189167

190-
由于 `n² = 1 + 3 + 5 + ... + (2n-1)`,对数字 `num` 不断减去 $i$ (`i = 1, 3, 5, ...`) 直至 `num` 不大于 0,如果最终 `num` 等于 0,说明是一个有效的完全平方数
168+
由于 $1 + 3 + 5 + \cdots + (2n - 1) = n^2$,我们可以将 $num$ 逐渐减去 $1, 3, 5, \cdots$,如果最后 $num = 0$,则说明 $num$ 是一个完全平方数
191169

192-
时间复杂度$O(sqrt(N))$。
170+
时间复杂度 $O(\sqrt n)$,空间复杂度 $O(1)$。
193171

194172
<!-- tabs:start -->
195173

@@ -224,7 +202,9 @@ class Solution {
224202
class Solution {
225203
public:
226204
bool isPerfectSquare(int num) {
227-
for (int i = 1; num > 0; i += 2) num -= i;
205+
for (int i = 1; num > 0; i += 2) {
206+
num -= i;
207+
}
228208
return num == 0;
229209
}
230210
};

‎solution/0300-0399/0367.Valid Perfect Square/README_EN.md

+47-72
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ tags:
5353

5454
<!-- solution:start -->
5555

56-
### Solution 1: Binary search
56+
### Solution 1: Binary Search
57+
58+
We can use binary search to solve this problem. Define the left boundary $l = 1$ and the right boundary $r = num$ of the binary search, then find the smallest integer $x$ that satisfies $x^2 \geq num$ in the range $[l, r]$. Finally, if $x^2 = num$, then $num$ is a perfect square.
59+
60+
The time complexity is $O(\log n)$, where $n$ is the given number. The space complexity is $O(1)$.
5761

5862
<!-- tabs:start -->
5963

@@ -62,31 +66,25 @@ tags:
6266
```python
6367
class Solution:
6468
def isPerfectSquare(self, num: int) -> bool:
65-
left, right = 1, num
66-
while left < right:
67-
mid = (left + right) >> 1
68-
if mid * mid >= num:
69-
right = mid
70-
else:
71-
left = mid + 1
72-
return left * left == num
69+
l = bisect_left(range(1, num + 1), num, key=lambda x: x * x) + 1
70+
return l * l == num
7371
```
7472

7573
#### Java
7674

7775
```java
7876
class Solution {
7977
public boolean isPerfectSquare(int num) {
80-
long left = 1, right = num;
81-
while (left < right) {
82-
long mid = (left + right) >>> 1;
83-
if (mid * mid >= num) {
84-
right = mid;
78+
int l = 1, r = num;
79+
while (l < r) {
80+
int mid = (l + r) >>> 1;
81+
if (1L * mid * mid >= num) {
82+
r = mid;
8583
} else {
86-
left = mid + 1;
84+
l = mid + 1;
8785
}
8886
}
89-
return left * left == num;
87+
return l * l == num;
9088
}
9189
}
9290
```
@@ -97,15 +95,16 @@ class Solution {
9795
class Solution {
9896
public:
9997
bool isPerfectSquare(int num) {
100-
long left = 1, right = num;
101-
while (left < right) {
102-
long mid = left + right >> 1;
103-
if (mid * mid >= num)
104-
right = mid;
105-
else
106-
left = mid + 1;
98+
int l = 1, r = num;
99+
while (l < r) {
100+
int mid = l + (r - l) / 2;
101+
if (1LL * mid * mid >= num) {
102+
r = mid;
103+
} else {
104+
l = mid + 1;
105+
}
107106
}
108-
return left * left == num;
107+
return 1LL * l * l == num;
109108
}
110109
};
111110
```
@@ -114,61 +113,44 @@ public:
114113
115114
```go
116115
func isPerfectSquare(num int) bool {
117-
left, right := 1, num
118-
for left < right {
119-
mid := (left + right) >> 1
120-
if mid*mid >= num {
121-
right = mid
122-
} else {
123-
left = mid + 1
124-
}
125-
}
126-
return left*left == num
116+
l := sort.Search(num, func(i int) bool { return i*i >= num })
117+
return l*l == num
127118
}
128119
```
129120

130121
#### TypeScript
131122

132123
```ts
133124
function isPerfectSquare(num: number): boolean {
134-
let left = 1;
135-
let right = num >> 1;
136-
while (left < right) {
137-
const mid = (left + right) >>> 1;
138-
if (mid * mid < num) {
139-
left = mid + 1;
125+
let [l, r] = [1, num];
126+
while (l < r) {
127+
const mid = (l + r) >> 1;
128+
if (mid >= num / mid) {
129+
r = mid;
140130
} else {
141-
right = mid;
131+
l = mid + 1;
142132
}
143133
}
144-
return left * left === num;
134+
return l * l === num;
145135
}
146136
```
147137

148138
#### Rust
149139

150140
```rust
151-
use std::cmp::Ordering;
152141
impl Solution {
153142
pub fn is_perfect_square(num: i32) -> bool {
154-
let num: i64 = num as i64;
155-
let mut left = 1;
156-
let mut right = num >> 1;
157-
while left < right {
158-
let mid = left + (right - left) / 2;
159-
match (mid * mid).cmp(&num) {
160-
Ordering::Less => {
161-
left = mid + 1;
162-
}
163-
Ordering::Greater => {
164-
right = mid - 1;
165-
}
166-
Ordering::Equal => {
167-
return true;
168-
}
143+
let mut l = 1;
144+
let mut r = num as i64;
145+
while l < r {
146+
let mid = (l + r) / 2;
147+
if mid * mid >= (num as i64) {
148+
r = mid;
149+
} else {
150+
l = mid + 1;
169151
}
170152
}
171-
left * left == num
153+
l * l == (num as i64)
172154
}
173155
}
174156
```
@@ -179,20 +161,11 @@ impl Solution {
179161

180162
<!-- solution:start -->
181163

182-
### Solution 2: Math trick
164+
### Solution 2: Mathematics
183165

184-
This is a math problem:
166+
Since $1 + 3 + 5 + \cdots + (2n - 1) = n^2$, we can gradually subtract $1, 3, 5, \cdots$ from $num$. If $num$ finally equals $0$, then $num$ is a perfect square.
185167

186-
```bash
187-
1 = 1
188-
4 = 1 + 3
189-
9 = 1 + 3 + 5
190-
16 = 1 + 3 + 5 + 7
191-
25 = 1 + 3 + 5 + 7 + 9
192-
36 = 1 + 3 + 5 + 7 + 9 + 11
193-
....
194-
so 1+3+...+(2n-1) = (2n-1 + 1)n/2 = n²
195-
```
168+
The time complexity is $O(\sqrt n)$, and the space complexity is $O(1)$.
196169

197170
<!-- tabs:start -->
198171

@@ -227,7 +200,9 @@ class Solution {
227200
class Solution {
228201
public:
229202
bool isPerfectSquare(int num) {
230-
for (int i = 1; num > 0; i += 2) num -= i;
203+
for (int i = 1; num > 0; i += 2) {
204+
num -= i;
205+
}
231206
return num == 0;
232207
}
233208
};
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
class Solution {
22
public:
33
bool isPerfectSquare(int num) {
4-
long left = 1, right = num;
5-
while (left < right) {
6-
long mid = left + right >> 1;
7-
if (mid * mid >= num)
8-
right = mid;
9-
else
10-
left = mid + 1;
4+
int l = 1, r = num;
5+
while (l < r) {
6+
int mid = l + (r - l) / 2;
7+
if (1LL * mid * mid >= num) {
8+
r = mid;
9+
} else {
10+
l = mid + 1;
11+
}
1112
}
12-
return left * left == num;
13+
return 1LL * l * l == num;
1314
}
1415
};
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
func isPerfectSquare(num int) bool {
2-
left, right := 1, num
3-
for left < right {
4-
mid := (left + right) >> 1
5-
if mid*mid >= num {
6-
right = mid
7-
} else {
8-
left = mid + 1
9-
}
10-
}
11-
return left*left == num
2+
l := sort.Search(num, func(i int) bool { return i*i >= num })
3+
return l*l == num
124
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
class Solution {
22
public boolean isPerfectSquare(int num) {
3-
long left = 1, right = num;
4-
while (left < right) {
5-
long mid = (left + right) >>> 1;
6-
if (mid * mid >= num) {
7-
right = mid;
3+
int l = 1, r = num;
4+
while (l < r) {
5+
int mid = (l + r) >>> 1;
6+
if (1L * mid * mid >= num) {
7+
r = mid;
88
} else {
9-
left = mid + 1;
9+
l = mid + 1;
1010
}
1111
}
12-
return left * left == num;
12+
return l * l == num;
1313
}
1414
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
class Solution:
22
def isPerfectSquare(self, num: int) -> bool:
3-
left, right = 1, num
4-
while left < right:
5-
mid = (left + right) >> 1
6-
if mid * mid >= num:
7-
right = mid
8-
else:
9-
left = mid + 1
10-
return left * left == num
3+
l = bisect_left(range(1, num + 1), num, key=lambda x: x * x) + 1
4+
return l * l == num
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
1-
use std::cmp::Ordering;
21
impl Solution {
32
pub fn is_perfect_square(num: i32) -> bool {
4-
let num: i64 = num as i64;
5-
let mut left = 1;
6-
let mut right = num >> 1;
7-
while left < right {
8-
let mid = left + (right - left) / 2;
9-
match (mid * mid).cmp(&num) {
10-
Ordering::Less => {
11-
left = mid + 1;
12-
}
13-
Ordering::Greater => {
14-
right = mid - 1;
15-
}
16-
Ordering::Equal => {
17-
return true;
18-
}
3+
let mut l = 1;
4+
let mut r = num as i64;
5+
while l < r {
6+
let mid = (l + r) / 2;
7+
if mid * mid >= (num as i64) {
8+
r = mid;
9+
} else {
10+
l = mid + 1;
1911
}
2012
}
21-
left * left == num
13+
l * l == (num as i64)
2214
}
2315
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
function isPerfectSquare(num: number): boolean {
2-
let left = 1;
3-
let right = num >> 1;
4-
while (left < right) {
5-
const mid = (left + right) >>> 1;
6-
if (mid * mid < num) {
7-
left = mid + 1;
2+
let [l, r] = [1, num];
3+
while (l < r) {
4+
const mid = (l + r) >> 1;
5+
if (mid >= num / mid) {
6+
r = mid;
87
} else {
9-
right = mid;
8+
l = mid + 1;
109
}
1110
}
12-
return left * left === num;
11+
return l * l === num;
1312
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
class Solution {
22
public:
33
bool isPerfectSquare(int num) {
4-
for (int i = 1; num > 0; i += 2) num -= i;
4+
for (int i = 1; num > 0; i += 2) {
5+
num -= i;
6+
}
57
return num == 0;
68
}
79
};

0 commit comments

Comments
 (0)
Please sign in to comment.