https://leetcode-cn.com/problems/perfect-squares/
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
我一开始想的是动态规划
自己没有写就搬运了别人的
但dp的时间复杂度硬伤
class Solution {
public:
int numSquares(int n) {
vector<int> det(n+1, INT_MAX);
det[0] = 0;
for(int i = 1; i <= n; i++){
int temp = sqrt(i);
if(temp * temp == i) det[i] = 1;
else{
for(int j = 1; j <= temp; j++)
det[i] = min(det[i], 1 + det[i-j*j]);
}
}
return det[n];
}
};
居居的方法:广搜
居居:“dp的时间复杂度太高了。”
but事实是用时上广搜也没好到哪里去并且debug用了相当久……
class Solution {
public:
struct node{
int x,f;
};
queue<node> q;
int numSquares(int n) {
int vis[1000005]={0};
node a,p;
a.x=n;
a.f=0;
q.push(a);
vis[n]=1;
while(!q.empty()){
a=q.front();
q.pop();
for(int i=1;i*i<=n;i++){
int t=a.x-i*i;
if(t==0)return a.f+1;
if(t>0&&!vis[t]){
p.x=t;
p.f=a.f+1;
vis[t]=1;
q.push(p);
}
}
}
return 0;
}
};
最后发现这是个数学问题……
四平方定理: 任何一个正整数都可以表示成不超过四个整数的平方之和。
推论:满足四数平方和定理的数n(四个整数的情况),必定满足 n=4^a(8b+7)
看到的证明清晰且有拓展的网站:https://www.changhai.org/articles/science/mathematics/four_square_theorem.php
class Solution {
public:
int numSquares(int n) {
while(n%4==0)n/=4;
if(n%8==7)return 4;
for(int a=0;a*a<=n;a++) {
int b=sqrt(n-a*a);
if(a*a+b*b==n){
if(!a||!b)
return 1;
return 2;
}
}
return 3;
}
};
网友评论