-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathperfect_squares.dart
281 lines (237 loc) · 6.89 KB
/
perfect_squares.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
-* 279. Perfect Squares *-
Given an integer n, return the least number of perfect square numbers that sum to n.
A perfect square is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, 1, 4, 9, and 16 are perfect squares while 3 and 11 are not.
Example 1:
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
Example 2:
Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.
Constraints:
1 <= n <= 104
*/
import 'dart:collection';
import 'dart:math';
class A {
// recursion TLE ut solution is perfect
int helper(int n) {
if (n == 0) return 0;
int minimumCount = 104;
for (int number = 1; number <= sqrt(n); number++) {
int squareNumber = number * number;
int currentCount = 1 + helper(n - squareNumber);
minimumCount = min(minimumCount, currentCount);
}
return minimumCount;
}
int numSquares(int n) {
return helper(n);
}
}
class B {
// TLE 2575ms which is large
int numSquares(int n) {
if (n == 0) return 0;
int minimumCount = 104;
for (int number = 1; number <= sqrt(n); number++) {
int squareNumber = number * number;
int currentCount = 1 + numSquares(n - squareNumber);
minimumCount = min(minimumCount, currentCount);
}
return minimumCount;
}
}
class C {
// Memoization
int helper(int n, List<int> dp) {
if (n == 0) return 0;
if (dp[n] != -1) return dp[n];
int minimumCount = 104;
for (int number = 1; number <= sqrt(n); number++) {
int sqNum = number * number;
int currCount = 1 + helper(n - sqNum, dp);
minimumCount = min(minimumCount, currCount);
}
return dp[n] = minimumCount;
}
int numSquares(int n) {
List<int> dp = List.filled(n + 1, -1);
return helper(n, dp);
}
}
class D {
// Dp
int helper(int n) {
List<int> dp = List.filled(n + 1, 104);
dp[0] = 0;
for (int target = 1; target <= n; target++) {
int mnCount = 104;
for (int num = 1; num <= sqrt(target); num++) {
int sqNum = num * num;
int currCount = 1 + dp[target - sqNum];
mnCount = min(mnCount, currCount);
}
dp[target] = mnCount;
}
return dp[n];
}
int numSquares(int n) {
return helper(n);
}
}
class E {
// dfs
int numSquares(int n) {
Queue<int> q = Queue();
HashSet<int> visited = HashSet();
q.add(0);
visited.add(0);
int depth = 0;
while (q.isNotEmpty) {
int size = q.length;
depth++;
while (size-- > 0) {
int u = q.removeLast();
for (int i = 1; i * i <= n; i++) {
int v = u + i * i;
if (v == n) {
return depth;
}
if (v > n) {
break;
}
if (!visited.contains(v)) {
q.add(v);
visited.add(v);
}
}
}
}
return depth;
}
}
class F {
// static dp
int numSquares(int n) {
if (n <= 0) {
return 0;
}
// cntPerfectSquares[i] = the least number of perfect square numbers
// which sum to i. Since cntPerfectSquares is a static vector, if
// cntPerfectSquares.size() > n, we have already calculated the result
// during previous function calls and we can just return the result now.
List<int> cntPerfectSquares = ([0]);
// While cntPerfectSquares.size() <= n, we need to incrementally
// calculate the next result until we get the result for n.
while (cntPerfectSquares.length <= n) {
int m = cntPerfectSquares.length;
int cntSquares = 104;
for (int i = 1; i * i <= m; i++) {
cntSquares = min(cntSquares, cntPerfectSquares[m - i * i] + 1);
}
cntPerfectSquares.add(cntSquares);
}
return cntPerfectSquares[n];
}
}
class G {
// math
// Runtime: 310 ms, faster than 100.00% of Dart online submissions for Perfect Squares.
// Memory Usage: 158.6 MB, less than 20.00% of Dart online submissions for Perfect Squares.
bool isSquare(int n) {
int sqrt_n = sqrt(n).toInt();
return (sqrt_n * sqrt_n) == n;
}
int numSquares(int n) {
if (isSquare(n)) {
return 1;
}
// The result is 4 if and only if n can be written in the
// form of 4^k*(8*m + 7). Please refer to
// Legendre's three-square theorem.
while ((n & 3) == 0) // n%4 == 0
{
n >>= 2;
}
if ((n & 7) == 7) // n%8 == 7
{
return 4;
}
// Check whether 2 is the result.
int sqrt_n = sqrt(n).toInt();
for (int i = 1; i <= sqrt_n; i++) {
if (isSquare(n - i * i)) {
return 2;
}
}
return 3;
}
}
class H {
// bfs
int numSquares(int n) {
if (n <= 0) {
return 0;
}
// perfectSquares contain all perfect square numbers which
// are smaller than or equal to n.
List<int> perfectSquares = [];
// cntPerfectSquares[i - 1] = the least number of perfect
// square numbers which sum to i.
List<int> cntPerfectSquares = List.filled(n, 0);
// Get all the perfect square numbers which are smaller than
// or equal to n.
for (int i = 1; i * i <= n; i++) {
perfectSquares.add(i * i);
cntPerfectSquares[i * i - 1] = 1;
}
// If n is a perfect square number, return 1 immediately.
if (perfectSquares.last == n) {
return 1;
}
// Consider a graph which consists of number 0, 1,...,n as
// its nodes. Node j is connected to node i via an edge if
// and only if either j = i + (a perfect square number) or
// i = j + (a perfect square number). Starting from node 0,
// do the breadth-first search. If we reach node n at step
// m, then the least number of perfect square numbers which
// sum to n is m. Here since we have already obtained the
// perfect square numbers, we have actually finished the
// search at step 1.
Queue<int> searchQ = Queue();
for (int i in perfectSquares) {
searchQ.add(i);
}
int currCntPerfectSquares = 1;
while (searchQ.isNotEmpty) {
currCntPerfectSquares++;
int searchQSize = searchQ.length;
for (int i = 0; i < searchQSize; i++) {
int tmp = searchQ.first;
// Check the neighbors of node tmp which are the sum
// of tmp and a perfect square number.
for (int j in perfectSquares) {
if (tmp + j == n) {
// We have reached node n.
return currCntPerfectSquares;
} else if ((tmp + j < n) && (cntPerfectSquares[tmp + j - 1] == 0)) {
// If cntPerfectSquares[tmp + j - 1] > 0, this is not
// the first time that we visit this node and we should
// skip the node (tmp + j).
cntPerfectSquares[tmp + j - 1] = currCntPerfectSquares;
searchQ.add(tmp + j);
} else if (tmp + j > n) {
// We don't need to consider the nodes which are greater ]
// than n.
break;
}
}
searchQ.removeFirst();
}
}
return 0;
}
}