题目要求:
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n =12
输出: 3 解释:12 = 4 + 4 + 4.
示例 2:
输入: n =13
输出: 2 解释:13 = 4 + 9.
解题思路:
由于遍历范围为N,所以首先想象有1~N个点,将其构造为一个图结构,若某两点的距离为i(i = 1, 2, 3, 4...)的平方,则将其连接。使用单独队列,进行广度优先遍历。从N开始,通过将其与i^2相减,得到的值设为temp ,将其与步数记录在队列中;同时记录访问过的点,若temp减去i^2得到了访问过的点,由于已经是从N到该点的最小步数,于是跳过不予更新;最终返回最后的步数。用文字描述有点抽象,可以用设一个值单步运行一下就明了了。
示例代码:
int numSquares(int n)
{
queue<pair<int, int>> q;
q.push(make_pair(n, 0)); // 将初始的 值与步数 入队
vector<bool> visited(n, false); // 访问记录 的保存
int num;
int step;
while (!q.empty())
{
num = q.front().first;
step = q.front().second;
q.pop(); // 一个节点此时已经遍历了所有相邻的节点,故出队,进行下一个节点的遍历
int i = 1;
while (num - i * i >= 0) // 对每个节点所有可能相邻的点进行遍历,并更新步数
{
int temp = num - i * i;
if (temp == 0)
{
step++;
return step;
}
else if (!visited[temp - 1]) //访问过的节点已经是最小步数 所以不更新
{
q.push(make_pair(temp, step + 1));
visited[temp - 1] = true;
}
i++;
}
}
return step;
}