如你須要掌握三種核心的能力:編程、寫做、設計??
這個活動是從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
}
複製代碼
四期結束,但願有更多的小夥伴加入。
關注公衆號回覆算法,一塊兒學習吧。