279. Perfect Squares

问题:

给定数字n,求将其分解为多个平方数的和,最少用多少个平方数可以得到。

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

  

解法:Binary Search(二分查找)BFS(广度优先搜索)

对于一个数n,

首先,需要找到与它最近的平方数,getmaxsq(n, formar_try)

♻️ 优化:减少查找的消耗:若有上次查找的结果formar_try,那么上限为min(formar_try, n)

base状态:由于题目给定的限制,

  • 1 <= n <= 10^4

那么查找上限,不超过100。

 

那么,BFS中,

  • queue里保存:剩下的当前数字cur,上次查找结果formar_try
    • 对于当前cur,我们可拆分的选择有:j:
      • getmaxsq(n, formar_try)获得的最大平方数->1 的所有选择。
    • 每次,做出选择后,cur-j^2 作为剩下的数字存入queue,待下一次继续拆解。
  • 遍历层数,即为所求最少的拆分次数。
  • 若此时cur-j^2==0,则找到完全拆分的一个解。由于res从小到大,那么第一次找到,即为最少。

 

代码参考:

 1 class Solution {
 2 public:
 3     int getmaxsq(int n, int right) {
 4         int l = 1, r = right;
 5         if(n<right) r = n;
 6         while(l<r) {
 7             int m = l+(r-l)/2;
 8             if(m*m >= n) {
 9                 r = m;
10             } else {
11                 l = m+1;
12             }
13         }
14         return l;
15     }
16     int numSquares(int n) {
17         int res=0;
18         if(n==1) return 1;
19         queue<pair<int,int>> q;//leftnum,formartry
20         q.push({n,getmaxsq(n,min(100,n))});
21         int sz = 0;
22         int cur=0, nextcur=0, trysq=100;
23         while(!q.empty()) {
24             sz=q.size();
25             res++;
26             for(int i=0; i<sz; i++) {
27                 cur = q.front().first;
28                 trysq = q.front().second;
29                 //printf("cur:%d, trysq:%d\n", cur, trysq);
30                 q.pop();
31                 for(int j=trysq; j>0; j--) {
32                     nextcur = cur-j*j;
33                     if(nextcur==0) return res;
34                     if(nextcur<0) continue;
35                     q.push({nextcur, getmaxsq(nextcur, j)});
36                 }
37             }
38             //printf("\n");
39         }
40         return res;
41     }
42 };

 

posted @ 2021-03-01 17:41  habibah_chang  阅读(57)  评论(0)    收藏  举报