zoukankan      html  css  js  c++  java
  • 再论力扣第279题--完全平方数

    题目

    给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

    示例1:

    输入: n = 12
    输出: 3 
    解释: 12 = 4 + 4 + 4.

    示例2

    输入: n = 13
    输出: 2
    解释: 13 = 4 + 9.

    分析:

      之前曾做过一次这道题,当时是刚学了动态规划算法,然后正好拿这个题进行练习,通过定义一个状态转移数组,也顺利的解决了,但是经过力扣的测试,运行效率十分地的感人,运行时间长达上前毫秒,可见用动态规划算法实现的程序的性能并不怎么好。正好最近在温习了广度优先算法,那么这个题也正好可以通过BFS解决,所以就再研究一下咯。并且没想到,虽然程序写的更为复杂了,但是运行时间大大的缩减了,甚至优于百分之九十以上的人的程序。好吧,废话不多说,开始进行正式的分析。

      我们知道,任何一个正整数都可以由若干个完全平方数相加而得到,最简单的就是数值是几,就由多少个1相加,这是组成和的完全平方数最为多的情况。而题目中要求的是最少的情况,其实可以抽象为求最短路径。也就是说,将n设置为起点,目的地是0,而n每一次向0靠近的时候,可以向前走的距离是1~n之间的所有平方数,比如:

      n = 13   目的地:0 ,设置一个计数值用于记录遍历的层数,到达0时的计数值就是最终的结果;

      从13出发,作为BFS遍历的第一层,那么此时向0靠近时,可以走的距离分别由1、4、9,那么我们就都走一下试试;

      分别按照这三个距离向前走,到达的点分别是12、9、4,此时这三个点算作BFS遍历的第二层;

      开启遍历第二层,计数值加1,获取第二层的结点个数,分别向0靠近遍历,可走的距离依旧是小于等于各自顶点值的所有平方数,遍历完当前层的所有顶点之后,就得到了下一层的所有顶点;

      继续重复上述工作,到达目的地0时,就立马返回计数值。

      注意必须遍历完一层的顶点之后才能开始下一层,开启一层计数值就+1

    代码:

    public int numSquares(int n) {
    
            if ((int)Math.sqrt(n) * (int)Math.sqrt(n) == n){
                return 1;
            }
            List<Integer> squares = generateSquare(n);
    
            LinkedList<Integer> queue = new LinkedList<>();
            boolean[] isVisited = new boolean[n + 1];
    
            isVisited[n] = true;
            queue.offer(n);
            int count = 0;
            while (!queue.isEmpty()){
                int unum = queue.size();
                count++;
    
                while (unum-- > 0){
                    Integer u = queue.poll();
                    for (Integer square : squares) {
    
                        int next = u - square;
    
                        if (next == 0){
                            return count;
                        }else if (next < 0){
                            break;
                        }else {
                            if (isVisited[next]){
                                continue;
                            }else {
                                isVisited[next] = true;
                                queue.offer(next);
                            }
                        }
    
                    }
                }
    
            }
            return count;
        }
    
        private List<Integer> generateSquare(int n){
    
            ArrayList<Integer> res = new ArrayList<>();
            for (int i = 1; i*i <= n; i++) {
                res.add(i*i);
            }
    
            return res;
        }
  • 相关阅读:
    idea 配置git
    mybatisgenerator自动生成Mapper.dao.entity
    Eclipse中设置作者日期等Java注释模板
    二分图匹配KM算法
    网络流最小费用最大流
    图论tarjan
    STL的一些基本操作
    图论拓扑排序
    字符串的一些基本操作
    网络流最大流
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13149858.html
Copyright © 2011-2022 走看看