【leetcode】Perfect Squares

题目描述:

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3 
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2

解释: 13 = 4 + 9.

分析:问题的实质是图的广度优先搜索,寻找无权图的最短路径问题;最直观的想法是想到了贪心的解法,但是这道题贪心是不可以的,因为比如例子中的12,如果使用贪心的思想,12=9+1+1+1 输出是4 实际结果应该为3;另外问题是一定有解的,因为1是一个完全平方数,任何数n都可以用n个1构成;

对问题进行建模,可以将n个数字,每个数字看成是图的一个结点,如果两个数字之间相差一个完全平方数,则就有一条边相连,这样这个问题的实质就是,找到从n出发,到达0的最短路径;

import java.util.LinkedList;
class Solution {
    public int numSquares(int n) {
        //问题的实质是图的BFS
        LinkedList q=new LinkedList();//一个队列 存放每个数字
        int step=0;//累计走过的步数 即二叉树的层序遍历的层数
        boolean[] visited=new boolean[n+1];//记录n个数是否被访问过
        visited[n]=true;//初始化n是访问过的
        q.offer(n);
        q.offer(-1);
        while(!q.isEmpty()){
            int num=q.pop();
            if(num==-1){//如果访问到了-1,说明当前层访问结束,步数累加,并在队列末尾压进-1
                step++;
                q.offer(-1);
                continue;
            } 
            for(int i=1;;i++){//找到num可达的所有数字,即与num相差一个完全平方数的所有合法数字
                int a=num-i*i;
                if(a==0)//如果num减去一个完全平方数后直接就等于0了,说明再另外走一步就到了 直接返回值
                    return step+1;
                if(a<0)
                    break;
                if(visited[a]==false){
                    q.offer(a);
                    visited[a]=true;
                }else{
                    continue;
                }       
            }
        }
        return step+1;
    }
}

本质是写图的BFS代码,设置一个布尔型的数组visited的目的是记录n个数字某一个是否被访问过,如果被访问过则不再重复加入队列中,这里区别于树的层序遍历,图的BFS要考虑一个结点重复到达很多次的问题


你可能感兴趣的:(撸代码笔记)