279. 完全平方数
279. 完全平方数
一、题目描述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12 输出: 3 解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13 输出: 2 解释: 13 = 4 + 9.
二、题解
一、解题思路
对问题建模:
整个问题转化为一个图论问题。
从n到0,每个数字表示一个节点;
如果两个数字x到y相差一个完全平方数,则连接一条边。
我们得到了一个无权图。
原问题转化成,求这个无权图从n到0的最短路径。
n | 解释 | 个数 |
---|---|---|
1 | 1-->0 | 1 |
2 | 1-->1-->0 | 2 |
3 | 3-->2-->1-->0 | 3 |
4 | 4-->0 | 1 |
5 | 5-->1-->0 | 2 |
6 | 6-->2-->1-->0 | 3 |
7 | 7-->3-->2-->1-->0 | 4 |
8 | 8-->4-->0 | 2 |
9 | 9-->0 | 1 |
二、代码
public int numSquares(int n) { Queue<Pair<Integer, Integer>> queue = new ArrayDeque<>(); queue.add(new Pair<>(n, 0)); //访问标志的数组 进行路径优化 // 提前已经访问的节点即可证明之前路径比此路径短 boolean[] visited = new boolean[n + 1]; visited[n] = true; while (!queue.isEmpty()) { int num = queue.peek().getKey(); int step = queue.peek().getValue(); queue.poll(); for (int i = 1; ; i++) { int temp = num - i * i; if (temp < 0) break; if (temp == 0) return step + 1; if (!visited[temp]) { //该数之前已访问 通过此线的路径 绝不是最短路径 // 则可以不用将后续的节点入队列 queue.add(new Pair<>(temp, step + 1)); visited[temp] = true; } } } return -1; }
LeetCode题解 文章被收录于专栏
收录leetcode题解,专注于算法练习。