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

相关推荐

  • leetcode23-合并K个排序链表

    原题 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->…

    算法 2020年2月4日
    0170
  • leetcode215-数组中的第K个最大元素

    原题 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 示例1: 输入: [3,2,1,5,6,4] 和…

    算法 2020年2月10日
    0140
  • leetcode124-二叉树中的最大路径和

    原题 给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 示例 1: 输入: [1…

    算法 2020年4月26日
    0170
  • 数组元素左右两边最近较小元素

    原题(来源牛客网) 给定一个不含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。 实例: 输入: ar…

    算法 2020年4月26日
    0700
  • leetcode17-电话号码的字母组合

    原题 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例: 输入: "23" 输出: …

    2020年5月3日
    0130
  • leetcode191-位1的个数

    原题 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。 示例 1: 输入: 000000000000000000000000…

    算法 2020年4月15日
    0120
  • 剑指offer47-礼物的最大价值

    原题(来源Leetcode) 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一…

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

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

    2020年1月16日
    090
  • leetcode648-单词替换

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

    算法 2020年4月20日
    0140
  • leetcode540-有序数组中的单一元素

    原题 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。 示例1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例2: 输入…

    2020年2月25日
    0700

发表回复

登录后才能评论