Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...
) which sum to n.
For example, given n = 12
, return 3
because 12 = 4 + 4 + 4
; given n = 13
, return 2
because 13 = 4 + 9
.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Subscribe to see which companies asked this question.
- 这道题的大致意思就是给定一个数,使这个数用完全平方数表示,并且完全平方数最少需要几个。其中完全平方数是开平方是整数的数(sqrt(n)=k,k=1,2,3...)
- 了解完题意思考解决思路:
- 本题可以转化为最短路径问题,从0到n为n+1个节点,如果从 i (属于0到n)到 j(属于0到n)相差一个完全平方数就可以将两个节点连接起来,这样所有的点就转化成了无向图,就把问题转化成了求n到0的最短路径
- 无权最短路径问题可以使用bfs
- 下面是一些节点的生成图
- 例如从不同节点到不同节点所需要的步数:
- 1. 从9到0,相差一个完全平方数9,即9 = 9 + 0,需要1步就可以到0了;
- 2. 从6到0,相差完全平方数4和完全平方数1,即6 = 4 + 1 + 1 + 0 需要三步就到0了;
- 3.同理 8 = 4 + 4 + 0需要两步到0;
- 实现:
- 借助队列的BFS,记录每走一步后 numpairs(剩余数字的大小,所走的步数);//记录每一个点到达其他节点步数然后对剩余数字的大小进行判断,看能否再变成完全平方数,也就是不断将剩余数字不断减小直到减为0,获取步数
-
for(int i = 1;i*i<=num;i++)//将num不断用完全平方数代表,直至其成为0,其中1是完全平方数所以总会有解 { int temp = num - i*i; if(visit[temp] == 0) { //将其中没有访问过的点标记,以及将改点所到达的路径录入 queue.add(new numpairs(temp,step+1)); visit[temp] = 1; } }
具体代码:
借助的pair类public class PerfectSquares { //使用广度搜索借助队列解决 public static int numSquares(int n) { if(n == 0) return 0; Queue<numpairs> queue = new LinkedList();//每次将剩余数字与已走步数入队 int[] visit = new int[n+1];//添加标记数组 numpairs pair = new numpairs(n,0);//记录每一个点到达其他节点步数 queue.add(pair); visit[n] = 1; while(!queue.isEmpty()) { pair = queue.poll(); int num = pair.getFirst();//获取剩余的数字与步数 int step = pair.getSecond(); for(int i = 1;i*i<=num;i++) { int temp = num - i*i; if(temp == 0) return step+1; if(visit[temp] == 0) { //将其中没有访问过的点标记,以及将改点所到达的路径录入 queue.add(new numpairs(temp,step+1)); visit[temp] = 1; // System.out.print(i*i+" "); } } } return 0; } public static void main(String[] args) { System.out.println(numSquares(2)); } }
public class numpairs { int first; int second; public numpairs(int a,int b) { setFirst(a); setSecond(b); } public int getFirst() { return first; } public void setFirst(int first) { this.first = first; } public int getSecond() { return second; } public void setSecond(int second) { this.second = second; } }