这一次是来自牛客上面经看到的面试算法
位图转时间
将一串字符串转换为时间序列,
样例:
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);
一种是降低难度的,字符串是有序的,这个时候直接使用位图则可
一种则是使用双指针标记一个子串的开始和结束,做迭代和字符串拼接。
还有手撕图二叉树队列栈的。。就不写了。。