1. 程式人生 > >自行整理面試知識(JS篇)(五)[演算法篇3]

自行整理面試知識(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);

一種是降低難度的,字串是有序的,這個時候直接使用點陣圖則可 一種則是使用雙指標標記一個子串的開始和結束,做迭代和字串拼接。

還有手撕圖二叉樹佇列棧的。。就不寫了。。