如你须要掌握三种核心的能力:编程、写做、设计??
这个活动是从2019年7月中旬开始的,人数不算多,也就几个好友和好友的好友,过程当中也会有人由于工做的缘故或其余缘由放弃,或许将来还会有人离开。javascript
活动的主要形式就是在leetcode刷题,每一个工做日一道题,每周作总结,目前已是第十四期,接下来我会把每期的题作一个总结,因为我是侧重javascript,因此活动中的每道题都是以js语言来实现解题方法。java
活动的规则比较严谨,群里天天早上10点以前发题,晚上10点审核,审核有管理员专门审核,称为打卡,没有打卡的人,须要发红包给管理员做为天天统计费用。node
活动的目的就是培养算法思惟,了解常见的算法,好比分治算法、贪心算法、动态优化等等。面试
微信公众号惊天码盗同步天天一道算法题(第四期)算法
上期回顾:编程
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。可是,每一个孩子最多只能给一块饼干。对每一个孩子 i ,都有一个胃口值 gi ,这是能让孩子们知足胃口的饼干的最小尺寸;而且每块饼干 j ,都有一个尺寸 sj 。若是 sj >= gi ,咱们能够将这个饼干 j 分配给孩子 i ,这个孩子会获得知足。你的目标是尽量知足越多数量的孩子,并输出这个最大数值。数组
注意:bash
你能够假设胃口值为正。
一个小朋友最多只能拥有一块饼干。微信
示例 1:app
输入: [1,2,3], [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,因为他们的尺寸都是1,你只能让胃口值是1的孩子知足。因此你应该输出1。复制代码
示例 2:
输入: [1,2], [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。你拥有的饼干数量和尺寸都足以让全部孩子知足。因此你应该输出2.复制代码
题解:
思路1:逐位查找法
有一数组长为0,则返回为0,先排序,而后循环小孩胃口值,num用来存储返回值;ll用来存储饼干的索引(跟以前跳针法相似);当小孩的胃口值大于饼干的时候,须要在饼干中查找大于等于相应饼干尺寸,若是没找到返回最大值,若是找到则记录索引;而后进入下次循环。
执行用时:192ms;内存消耗:38.7MB;
var findContentChildren = function(g, s) {
let {num=0,ll=0}={};
if(!s.length||!g.length)return 0;
let gArray=g.sort((a,b)=>a-b);
let sArray=s.sort((a,b)=>a-b);
for(let i=0;i<g.length;i++){
if(sArray[ll]){
if(gArray[i]>sArray[ll]){
const cur=sArray.filter(a=>a>=gArray[i])[0]||null;
if(cur){
ll=sArray.indexOf(cur)+1
num++
}
}else{
ll++
num++
}
}
}
return num
}
复制代码
思路2:倒序递减法
饼干尺寸和胃口值都从大到小排序,循环胃口值,逐一删除饼干尺寸。(经常从小到大排序,偶尔换个思路可能更方便)
执行用时:144ms;内存消耗:37.6MB;
var findContentChildren = function(g, s) {
let num=0;
let gArray=g.sort((a,b)=>b-a);
let sArray=s.sort((a,b)=>b-a);
gArray.forEach((item,i)=>{
if(sArray[0]>=item){
num++;
sArray.shift()
}
})
return num
}
复制代码
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.
示例 1:
输入:
3
/ \
9 20
/ \
15 7
输出: [3, 14.5, 11]
解释:第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 所以返回 [3, 14.5, 11].复制代码
注意:
1.节点值的范围在32位有符号整数范围内。
题析:
关于图形算法,是比较复杂的,尤为是树的遍历,涉及到递归的逻辑。通常简单的状况下能够用条件语句while等来实现简单的递归。这道题一样能够,不管使用递归仍是while语句均可以实现。
这道题的结果是一数组,数组的每个值是当前层的节点值除以节点数;因此咱们要明确咱们须要获得的东西,层数,层数表示咱们数组的长度;当前层的节点值与当前层的节点数。
这道题的核心思路有两,一是层序遍历,一层一层推动只有当前层执行完才能够推动下一层;另外一种是不限制,不管当前层是否执行完,均可以执行下一层。这就会涉及到图形的两个概念:广度优先搜索和深度优先搜索。
题解:
思路1:广度优先遍历法
利用广度优先搜索的方法,逐层推动。利用queue的长度来限制是否向下推动,当所在层无值时向下推动。
执行用时:108ms;内存消耗:35.7MB;
var averageOfLevels = function(root) {
let queue = [root], result = [], arr = [], sum = 0, length = 1
while (queue.length) {
let node = queue.shift()
sum += node.val
node.left && arr.push(node.left)
node.right && arr.push(node.right)
if (queue.length === 0) {
result.push(sum/length)
queue = arr
length = queue.length
arr = []
sum = 0
}
}
return result
}
复制代码
思路2:深度优先遍历法
经过每层的索引来肯定当前的值。同层相加。
执行用时:100ms;内存消耗:38.1MB;
var averageOfLevels = function(root) {
let ans = [];
let levelNum = [];//每一层的节点数
let levelSum = [];//每一层的节点总数
//递归函数
let rescurse=(node, index, levelNum, levelSum)=>{
if (node == null) {
return;
}
if (levelNum.length <= index) {
levelNum.push(1);
levelSum.push(node.val);
} else {
levelNum[index]++;
levelSum[index]+=node.val
}
rescurse(node.left, index + 1, levelNum, levelSum);
rescurse(node.right, index + 1, levelNum, levelSum);
}
rescurse(root, 0, levelNum, levelSum);
for (let i = 0; i < levelNum.length; i++) {
ans.push(levelSum[i] / levelNum[i]);
}
return ans;
}
复制代码
给出一个 32 位的有符号整数,你须要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321复制代码
示例 2:
输入: -123
输出: -321复制代码
示例 3:
输入: 120
输出: 21复制代码
注意:
假设咱们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,若是反转后整数溢出那么就返回 0。
题解:
思路1:数组化
先转化为数组,反转后,再转化为字符串,须要逐一限制条件。
这个思路是数组思惟。
执行用时:108ms;内存消耗:35.7MB;
var reverse = function(x) {
let num=String(Math.abs(x)).split('').reverse().join('');
if(Math.pow(2,31)>=num&&x>0){
return Number(num)
}
if(0-Math.pow(2,31)<0-num&&x<0){
return 0-Number(num)
}
return 0
}
复制代码
思路2:分离取余法
先分离数字(123),取得余数(3)和剩余数(12),而后余数乘十(30)加剩余数的余数(2);记录每次相加后所得余数(32)与剩余数(1);依次循环,获得终数。
这个思路是利用的数学思惟。
执行用时:100ms;内存消耗:35.7MB;
var reverse = function (x) {
let re = 0;
while (parseInt(x / 10)) {
re = 10 * re + x - 10 * parseInt(x / 10);
x = parseInt(x / 10);
}
if (re > 214748364 || re < -214748364) return 0;
if ((re == 214748364 && x > 7) || (re == 214748364 && x < -8)) return 0;
re = 10 * re + x;
return re
}
复制代码
思路3:字符倒序法
转化为字符串,反转字符串,而后在循环中逐一添加。须要注意的是,转的时候要绝对值化,转以后要取整。
这个思路是字符串思惟。
执行用时:112ms;内存消耗:35.7MB;
var reverse = function(x) {
Math.abs(x)>(2**31-1)?x=0:x;
if(x == 0) return 0
let y = Math.abs(x).toString(),len='';
for(var i =0;i<y.length;i++){len += y[y.length-i-1]}
return parseInt(Math.abs(len)>(2**31-1)?len=0:(x<0?-len:len));
}
复制代码
判断一个整数是不是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是同样的整数。
示例 1:
输入: 121
输出: true复制代码
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。从右向左读, 为 121- 。所以它不是一个回文数。复制代码
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。所以它不是一个回文数。复制代码
进阶:
你能不将整数转为字符串来解决这个问题吗?
题析:
这道题本质上和上面整数反转是一个题目,因此上面的思路下面都能用到,惟一的区别就是正负数。因此下面题解不会过多的介绍思路。
题解:
思路1:分离取余法
先转化为数组,反转后,再转化为字符串,须要逐一限制条件。
执行用时:360ms;内存消耗:42.5MB;
var isPalindrome = function(x) {
if (x < 0) return false;
let result = 0;
let before = x;
while (x > 0){
result = result*10 + x%10;
x = parseInt(x / 10);
}
return before == result?true:false;
}
复制代码
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。若是不存在,则返回 -1。
示例 1:
输入: haystack = "hello", needle = "ll"
输出: 2复制代码
示例 2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1复制代码
说明:
当 needle
是空字符串时,咱们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时咱们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
题解:
思路1:字符串索引法
利用字符串方法一步到位。
执行用时:64ms;内存消耗:33.8MB;
var strStr = function(haystack, needle) {
if(!needle)return 0;
return haystack.indexOf(needle)
}
复制代码
执行用时:76ms;内存消耗:36MB;
var strStr = function (haystack, needle) {
if (needle === "") return 0
for (var i = 0; i < haystack.length; i++) {
if (haystack[i] === needle[0]) {
if (haystack.substring(i, i + needle.length) === needle) return i;
}
}
return -1
}
复制代码
四期结束,但愿有更多的小伙伴加入。
关注公众号回复算法,一块儿学习吧。