自行整理面試知識(JS篇)(四)[演算法篇2]
阿新 • • 發佈:2018-12-19
陣列插值
大致就是如果一個值在兩個值中間,則他跟這兩個值的差值要不然是異號的,要不然就是為0的,用這種方式可以無視排序的逆序或者正序,注意剪枝、
let a = [1,2,4,5,6,9,10,13]; const insertNum = (array,num) => { //剪枝 let idx = insertNumIndexOf(array,num,array[array.length-1] >= array[0]); if(idx === array.length){ array.push(num); return; } if(idx === 0){ array.unshift(num); return; } if(idx){ array.splice(idx+1,0,num); return; } } const insertNumIndexOf = (array,num,flag) => { //雙指標 //剪枝 if(flag && array[array.length-1] <= num)return array.length-1; if(!flag && array[0] <= num)return 0; if(flag && array[0] >= num)return 0 if(!flag && array[array.length-1] >= num)return array.length-1; let pre = 0,next = 0; for (let i of array){ ++next; let signPre = Math.sign(array[pre]-num); let signNext = Math.sign(array[next]-num); if(signPre != signNext || signPre === 0)return pre; pre++; } } insertNum(a,14); console.log(a);
科學計數法
let a = 1111123445411515; const changeNum = (num) => { let str = String(a); let modNum = str.length%3; let ansNum = Math.floor(str.length/3); let newstr = new Array(); for(let i = ansNum ; i > 0 ; i--){ let idx = i * 3 + modNum; newstr[i] = str.slice(idx-3,idx); } if(modNum == 0)newstr.shift(); else newstr[0] = str.slice(0,modNum); return newstr.join(","); } console.log(changeNum(a));
正則表示式的方法
let a = 1111123445411515;
const changeNum = (num) => {
let reg = /\B(?=((\d{3})+)$)/g;
return String(a).replace(reg,',');
}
console.log(changeNum(a));
匹配非單詞邊界(位置)且後面跟著三個數字的(三個數字可以零次或多次),且進行正向預查,即必須滿足前面的且後面不參與最後匹配的字元內容。
複雜陣列降維(就是深複製的閹割版)
let a = [2,3,4,[1,2,[1,3],[1,2]]]; let newa = []; const deepCopy = (array)=>{ for(let i of array){ let checkType = typeof(i); if(checkType != "object")newa.push(i); else{ deepCopy(i); } } } deepCopy(a); console.log(newa);
正序列最晚出現位置(二分查詢)
//二分查詢
let a = [1,1,1,1,1,1,2,5,6,7,8,9,10,11,12,12,13,14,14,14,14,14];
const findLastIndexOf = (array,num)=>{
let mid = Math.floor(a.length / 2);
let pos = -1;
let left = 0;
let right = array.length - 1;
if(num < a[0])return -1;
if(num > a[right])return -1;
if(num === a[right])return right;
while(Math.abs(left-right) != 1){
if(array[mid] === num){
pos = mid;
left = mid;
mid = Math.floor((left+right)/2);
}else if(array[mid] > num){
right = mid;
mid = Math.floor((left+right)/2);
}else{
left = mid;
mid = Math.floor((left+right)/2);
}
}
return pos;
}
console.log(findLastIndexOf(a,1));
注意剪枝,很重要
多個有序陣列的合併
//有序合併
let a = [1,2,3,4,5,9,18,33,666,788,999];
let b = [2,7,17,32,667,699,1111,2222];
let c = [0,1,2,3,4,6,7,9];
const mergeArrayAll = (...argument)=>{
return argument.reduce((newArray = [],item)=>{
return mergeArray(newArray,item);
})
}
const mergeArray = (arrayOne,arrayTwo) =>{
let newArray = [];
let pre = 0,next = 0;
while(pre <= arrayOne.length-1 && next <= arrayTwo.length-1){
let minNum;
if(arrayOne[pre] < arrayTwo[next]){
minNum = arrayOne[pre];
pre++;
}else{
minNum = arrayTwo[next];
next++;
}
newArray.push(minNum);
}
newArray = newArray.concat(arrayOne.slice(pre));
newArray = newArray.concat(arrayTwo.slice(next));
return newArray;
}
console.log(mergeArrayAll(a,b,c));
其思想大概就是兩個陣列對比,把最小的那個加入新陣列。把最後得到的陣列返回給高階函式繼續迭代出新的陣列
自然序列取值亂序查值問題
從1 - N的自然序列中隨機取出一個值,再打亂其順序,問如何最快發現那個值的位置
一般是相加,相乘,點陣圖(雜湊)。 巧妙的是異或( 我來給你們做證明: 設 123…^N(去掉了那個值的)為T 設去掉的值為n 則123…n…N為T^n 由於對任何數,都有N^N = 0 N^0 = N; 則有TnT為n^0 (自反律) 即為n 懂怎麼做了嗎??? 硬撕的是二分查詢(先排序,再比較下標的位移)
如果是多個值被移除,我推薦你使用點陣圖(即mark陣列啦)
大數加法/減法
//大數加法,減法
let a = 15161161111111;
let b = 9515616161111;
const bigNumAdd = (numOne, numTwo) => {
let strOne = numOne + "";
let strTwo = numTwo + "";
let result = [];
result = [...(strOne.length > strTwo.length ? strOne : strTwo)];
let maxLength = result.length;
let newNumArray = new Array(Math.abs(strOne.length - strTwo.length)).fill(0);
if (strOne.length > strTwo.length) newNumArray = newNumArray.concat([...strTwo]);
else newNumArray = newNumArray.concat([...strOne]);
console.log(newNumArray, result);
for (let i = maxLength - 1; i >= 0; i--) {
let ans = Number(result[i]) + Number(newNumArray[i]);
if (ans >= 10) {
ans = ans % 10;
result[i] = ans;
if (i != 0) {
result[i - 1] = Number(result[i - 1]) + 1;
} else {
result.unshift(1);
}
} else {
result[i] = ans;
}
}
return result.join('');
}
const bigNumSub = (numOne, numTwo) => {
let strOne = String(numOne);
let strTwo = String(numTwo);
let checkFlag = true;
if (strOne.length > strTwo.length) checkFlag = true;
else if (strOne.length < strTwo.length) checkFlag = false;
else {
if (strOne > strTwo) checkFlag = true;
else checkFlag = false;
}
let result = [...(checkFlag ? strOne : strTwo)];
let newNumArray = new Array(Math.abs(strOne.length - strTwo.length)).fill(0)
.concat([...(checkFlag ? strTwo : strOne)]);
let maxLength = checkFlag ? strOne.length : strTwo.length;
for (let i = maxLength - 1; i >= 0; i--) {
let ans = Number(result[i]) - Number(newNumArray[i]);
if (ans < 0) {
ans = ans + 10;
result[i] = ans;
result[i - 1] = Number(result[i - 1]) - 1;
if (result[i - 1] === 0 && i - 1 === 0) result.shift();
} else {
result[i] = ans;
}
}
if (!checkFlag) result.unshift("-");
return result.join("");
}
console.log(bigNumAdd(a, b));
console.log(bigNumSub(a, b));
乘法可以用拆開相乘相加的演算法做,也可以用每一位累加直到最後做進位的方法做,當然演算法大佬可以用很多奇怪的超強演算法搞定。。我等大概是。。難的。。