博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode279完全平方数
阅读量:5891 次
发布时间:2019-06-19

本文共 2035 字,大约阅读时间需要 6 分钟。

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

示例 1:

输入: n = 12输出: 3 解释: 12 = 4 + 4 + 4复制代码

示例 2:

输入: n = 13输出: 2解释: 13 = 4 + 9复制代码

我的心历路程: 碰到最少、最短这种字眼的话,现在我一开始想到的就是广度优先遍历 + 队列来解决这种类似问题。

思路就用图来解释吧

  1. 我们把给定的正整数12作为根节点,依次减去符合条件的完全平方数(小于n的完全平方数)
  2. 减去后得到了 11 8 3 这三个数字,三个数字继续减去 1 4 9 ,又得到了他们的差
  3. 继续减 1 4 9,直到碰到第一个0为止,说明找到了最短的路径。对应的层数就是最少个数

“Talk is cheap. Show me the code.” --Linus Torvalds

/** * 广度优先搜索,耗时严重,思路: *  1. 计算出可能的完全平方数的数组 *  2. 设置一个数组,初始化元素为传入的正整数 *  3. 设置一个step为0 *  3. 循环这个数组,让数组中的每个元素都删除完全平方数中的每一个元素,第一个差为0的,说明就是最短路径*/var numSquares = function(n) {  let MaxSquare = Math.ceil(Math.sqrt(n));  function getAvailableSquareArr(num) {    let arr = [];    for (let i = 1; i<=num; i++) {      arr.push(Math.pow(i, 2));    }    return arr;  }  let squareArr = getAvailableSquareArr(MaxSquare); // 可能的完全平方数组成的数组  let squareLength = squareArr.length; // 完全平方数组长度  let subArr = [n]; // 用来存放每次减去完全平方数的数组,初始值为传入的正整数  let step = 0;  while(subArr.length) {    step++;    let len = subArr.length;    for (let j = 0; j < len; j++) {      let value = subArr.shift(); // 队首出队列      for (let i = 0; i < squareLength; i++) {        let sub = value - squareArr[i];        if (sub === 0) return step;        if (sub < 0) {          break;        }        if (!subArr.includes(sub)) {          subArr.push(sub);        }      }    }  }  return step;};复制代码

上面的这种解法我们看一下执行耗时

竟然要解决6s的时间,可见这种方式固然能够求出结果,但是其计算的效率并不高。我们来分析一下他的时间复杂度是多少:

  1. 最外层一个while循环
  2. 内部一个嵌套的for循环

得到时间复杂度为O(n^3),这里时间复杂度我个人也不大确定是否为O(n^3),如果您知道怎么算,请在评论解惑。

所以我们需要一种更高效的方式来计算。于是引入了动态规划的方式解决该题。

来自wiki百科:动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。

动态规划解决这个问题我也在leecode上看过解释,但是自己就是看不大懂。直到写文章的今天我也还是一知半解。所以使用动态规范解决的方式我现在的水平还讲不清楚,但是我先把动态规划解决的代码放在这,待日后补充具体的思路。各位大佬如果觉得能够讲清楚,也可以在留言处写下自己的思路。带带小弟我。

function numSquares(n) {  const dp = [0];    for (let i = 1; i <= n; i++) {    dp[i] = Number.MAX_VALUE;    for (let j = 1; j*j <= i; j++) {      dp[i] = Math.min(dp[i], dp[i-j*j]+1);    }   }    return dp[n];}复制代码

转载地址:http://bobsx.baihongyu.com/

你可能感兴趣的文章
让浏览器不再显示 https 页面中的 http 请求警报
查看>>
hdu4893Wow! Such Sequence! (线段树)
查看>>
Android 最简单的SD卡文件遍历程序
查看>>
JavaScript获取DOM元素位置和尺寸大小
查看>>
1065: 贝贝的加密工作
查看>>
lintcode 单词接龙II
查看>>
WEB版一次选择多个文件进行批量上传(WebUploader)的解决方案
查看>>
Redis之 命令行 操作
查看>>
Jvm(46),指令集----对象创建与访问指令
查看>>
EL 表达式小结
查看>>
内部排序
查看>>
jQuery EasyUI API 中文文档 - 组合(Combo)
查看>>
10个关于 Dropbox 的另类功用(知乎问答精编)[还是转来了]
查看>>
Oracle体系结构
查看>>
用Modelsim仿真QII FFT IP核的时候出现的Error: Illegal target for defparam
查看>>
javascript Error对象详解
查看>>
nc 局域网聊天+文件传输(netcat)
查看>>
每天一个linux命令(25):linux文件属性详解
查看>>
go微服务框架go-micro深度学习(三) Registry服务的注册和发现
查看>>
python 重载方法有哪些特点 - 老王python - 博客园
查看>>