leetcode279-完全平方数

原题

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

示例 1:

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

示例 2:

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

解法

思想

以12为例。

这道题确实对时间要求比较严格,如果不过滤掉重复计算的部分会无法通过。

从目标数出发自顶向下:

leetcode279-完全平方数

由已知的目标数出发,减去比它小的平方数,这样一层一层减下去,直到获得0的那一层的层数就是答案。

需要过滤掉数值重复的节点,比如11-4和8-1。

从平方数出发自底向上:

leetcode279-完全平方数

由比已知目标数小的所有平方数出发,每层做一个组合加法,但是有一些地方需要处理:

  1. 遇到数值相等的节点,如1+4和4+1,跳过该节点。
  2. 在组合的时候遇到从一个数开始,加上它就会大于目标数,那么它之后的平方数都可以不做组合了,因为都比它大。

代码

自顶向下:

class Node{
    public int value;
    public int depth;
    public Node(int value,int depth){
        this.value = value;
        this.depth = depth;
    }
}

class Solution {
    public int numSquares(int n) {
        int mark[] = new int[n];
        if(n<4) return n;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(new Node(n,0));
        while(!queue.isEmpty()){
            Node node = queue.poll();
            if(node.value==0) return node.depth; 
            int sqrt = (int)Math.sqrt(node.value);
            for(int i = sqrt; i > 0 ; i--){
                if(mark[node.value-i*i]==0){
                    queue.offer(new Node(node.value-i*i,node.depth+1));
                    mark[node.value-i*i] = 1;
                }
            }

        }
        return -1;
    }
}

自底向上

class Node{
    public int value;
    public int depth;
    public Node(int value,int depth){
        this.value = value;
        this.depth = depth;
    }
}

class Solution {
    public int numSquares(int n) {
        Queue<Node> queue = new LinkedList<>();
        int a = (int)Math.sqrt(n);
        int[] mark = new int[n+1];
        for(int i = a;i>a/2;i--){
            queue.offer(new Node(i*i,1));
            mark[i*i] = 1;
        }

        while(!queue.isEmpty()){
            Node node = queue.poll();
            int value = node.value;
            if(value==n) return node.depth;
            for(int i = 1;i<=a;i++){
                if(value+i*i>n) break;
                if(mark[value+i*i]==1) continue;
                queue.offer(new Node(value+i*i,node.depth+1));
                mark[value+i*i] = 1;
            }
        }
        return -1;
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode279-%e5%ae%8c%e5%85%a8%e5%b9%b3%e6%96%b9%e6%95%b0/

(0)
彭晨涛彭晨涛管理者
上一篇 2019年12月10日 18:05
下一篇 2019年12月12日 18:05

相关推荐

  • leetcode260-只出现一次的数字III

    原题 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。 示例: 输入: [1,2,1,3,2,5] 输出: [3,5…

    算法 2020年4月28日
    0150
  • leetcode771-宝石与石头

    原题 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 J 中的字母不重复,J …

    算法 2019年12月26日
    0360
  • leetcode278-第一个错误的版本

    原题 你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。 假…

    算法 2020年1月2日
    090
  • 拉帮结派的数据结构-并查集

    本文参考资源: 超超有爱爱-----并查集~~~chen_zan_yu的博客-CSDN博客 概述 并查集通常用作集合的合并。 并查集是一种树形结构,又叫“不相交集合”,保持了一组不…

    2020年2月17日
    0140
  • leetcode122-买卖股票的最佳时机II

    原题 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意: 你不能同…

    算法 2020年2月7日
    080
  • leetcode648-单词替换

    原题 在英语中,我们有一个叫做 词根(root)的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 oth…

    算法 2020年4月20日
    0150
  • leetcode54-螺旋矩阵

    原题 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6…

    算法 2019年11月15日
    090
  • leetcode79-单词搜索

    原题 给定一个二维网格和一个单词,找出该单词是否存在于网格中。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格…

    算法 2020年4月12日
    0130
  • leetcode450-删除二叉搜索树中的节点

    原题 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。 一…

    2020年1月16日
    090
  • leetcode1-两数之和

    原题 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能…

    算法 2019年12月20日
    0110

发表回复

登录后才能评论