自行整理面试知识(JS篇)(五)[算法篇3]

这一次是来自牛客上面经看到的面试算法

位图转时间

将一串字符串转换为时间序列,
样例:
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);

一种是降低难度的,字符串是有序的,这个时候直接使用位图则可
一种则是使用双指针标记一个子串的开始和结束,做迭代和字符串拼接。

还有手撕图二叉树队列栈的。。就不写了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值