自行整理面試知識(JS篇)(五)[演算法篇3]
阿新 • • 發佈:2018-12-19
這一次是來自牛客上面經看到的面試演算法
點陣圖轉時間
將一串字串轉換為時間序列, 樣例: 110000010000000000000000000000000000000000000000即輸出 [“00:00-01:00”,“03:30-04:00”] 110000010000000000000000000000000000000000000001即輸出 [“00:00-01:00”,“03:30-04:00”,“23:30-24:00”]
let str = "110000010000000000000000000000000000001000000001"; let hour = ["00","01","02","03","04","05","06","07","08","09",10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; let check = 0; let checkMap = new Array(); [...str].forEach((item,idx)=>{ if(item === "0") { check++; return; } if(item === "1") { if(checkMap[check]){ checkMap[check].push(idx+1); }else{ checkMap[check] = [idx+1]; } }; }); let timeMap = checkMap.map((item,idx)=>{ let minite = item.length * 30 + item[0] * 30; let startTime = hour[Math.floor((item[0]-1)/2)] + (":" + ( ((item[0]-1)%2) == 0 ? "00" : "30")); let endTime = hour[Math.floor((item[item.length-1])/2)] + (":" + ( ((item[item.length-1])%2) == 0 ? "00" : "30")); return startTime + "-" + endTime; }).filter((item)=>{ return typeof(item) != "object" }); console.log(timeMap);
將連續的1推進同一個陣列中,將不連續的1分開,最後做字串拼接 不知道有沒有更簡便的方法。
深層陣列下劃線轉駝峰
const changeItemName = (name) => { let array = name.split("_"); if (!array.length) return name; return array.map((item, idx) => { if (idx != 0) return item.charAt(0).toUpperCase() + item.slice(1); else return item; }).join("") } let newArray = {}; const deepFind = (array, newArray = {}) => { for (let i in array) { let checkType = typeof (array[i]); let checkConstructor = typeof (array[i]); if (checkType != "object") newArray[changeItemName(i)] = array[i]; else { if (checkConstructor === "array") deepFind(array[i], newArray[changeItemName(i)]); else if (checkConstructor === "object") { deepFind(array[i], newArray[changeItemName(i)] = {}); } } } return newArray; } const testData = { a_v: 123, a_y: [1, 2, 3, 4], a_d: { s: 2, s_3: 3 }, a_f: [{ a_g: 5 }], a_a_d: 1 } console.log(changeItemName("c_d_a")); console.log(deepFind(testData));
深複製的原理
陣列右旋
let a = [1,2,3,-100,550];
const rotateArray = (array,num)=>{
if(array.length <= 1)return array;
let pos = num % array.length;
array.unshift(...array.splice(array.length - pos));
return array;
}
console.log(rotateArray(a,4));
直接從後數把需要位移的數切掉插到陣列前面就行了
陣列去重/不允許排序
前面其實寫過
let a = [1,2,3,1,2,3,5,4,6,3,2,1];
/*a = [...new Set(a)];*/
for(let i = 0 ; i < a.length ; i++){
for(let j = i+1 ; j < a.length ; j++){
if(a[i] === a[j])a.splice(j,1);
}
}
console.log(a.length,a);
兩種,一種優化雙迴圈去重,一種直接Set
陣列共同數
跟去重一個道理
let a = [1,2,3,4,6,8,9,11,13];
let b = [1,3,6,7,9,11,12,13,14,16];
let pre = 0 , next = 0 ;
let equalArray = [];
while(true){
if(pre === a.length || next === b.length)break;
if(a[pre] === b[next]){
equalArray.push(a[pre]);
pre++;
next++;
}else if(a[pre]<b[next]){
pre++;
}else{
next++;
}
}
console.log(equalArray);
Dom樹遍歷
const DFT_t(node){
let nodes = [];
if(node){
nodes.push(node);
let children = node.children;
for(let i = 0 ; i < node.length ; i++){
DFT(children[i]);
}
}
return nodes;
}
const DFT(node){
let nodes = [];
if(node){
let stack = [];
stack.push(node);
while(stack.length != 0){
let item = stack.pop();
nodes.push(item);
let children = item.children;
for(let i = children.length-1 ; i >= 0 ; i++){
stack.push(children[i]);
}
}
}
return nodes;
}
const BFT(node){
let nodes = [];
let query = [];
if(node){
query.push(node);
while(query.length > 0){
let item = query.shift();
nodes.push(item);
let children = node.children;
for(let i = 0 ; i < children.length ; i++){
query.push(children[i]);
}
}
}
return nodes;
}
深度遍歷和廣度遍歷
快排和冒泡
const quickSort = (array)=>{
if(array.length <= 1)return array;
let pos = Math.floor(array.length / 2);
let positem= array.splice(pos,1)[0];
let left = [];
let right = [];
for(let i = 0 ; i < array.length ; i++){
if(array[i]<=positem)left.push(array[i]);
else right.push(array[i]);
}
return quickSort(left).concat(positem,quickSort(right));
}
const bubbleSort = (array) => {
if(array.length <= 1)return array;
for(let i = 0 ; i < array.length ; i++){
for(let j = i+1 ; j < array.length; j++){
if(array[j] < array[i])[array[j],array[i]] = [array[i],array[j]];
}
}
return array;
}
let a = [2,6,9,7,2,1,3,4,5,67,55,44,22];
console.log(a=quickSort(a),bubbleSort(a));
最大連續子序列
let a = [1,3,-1,5,-5,4,12,8,-7,9,-8];
let dp = [];
for(let i in a){
if(dp.length < 1)dp[0] = a[i];
else{
dp[i] = Math.max(dp[i-1] + a[i] , a[i])
}
}
console.log(dp.reduce((max = dp[0],item)=>{
return max > item ? max : item;
}));
發生狀態轉移的只有兩種情況,一是前面的加該數比該數小,一是前面的加該數比該數大。 所以有dp[i] = MAX(dp[i-1] + num , num); 再遍歷dp陣列得到最大的則可
字串壓縮
let str = "aaaaccceeeeddaallpppsss";
str = [...str];
let pre = 0;
let next = 1;
let newstr = [];
while(true){
if(next === str.length - 1){
newstr.push((next-pre)+str[pre]);
break;
}
if(str[next] === str[pre])next++;
else{
console.log(pre,next);
newstr.push((next-pre)+str[pre]);
pre = next;
next++;
}
}
console.log(newstr);
一種是降低難度的,字串是有序的,這個時候直接使用點陣圖則可 一種則是使用雙指標標記一個子串的開始和結束,做迭代和字串拼接。
還有手撕圖二叉樹佇列棧的。。就不寫了。。