【JavaScript】前端演算法題 40道題+解析

我恨bug發表於2024-08-04

前言

最近練習了一些前端演算法題,現在做個總結,以下題目都是個人寫法,並不是標準答案,如有錯誤歡迎指出,有對某道題有新的想法的友友也可以在評論區發表想法,互相學習🤭

題目

題目一: 二維陣列中的查詢: 在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

function sortList(array, num) {
	// 解法一.迴圈indexOf查詢 有返回下標,沒有則返回-1
	// for (let i = 0; i < array.length; i++) {
	//     if (array[i].indexOf(num) != -1) {
	//         return console.log('有');
	//     }
	// }
	// 解法二.巢狀迴圈
	// for(let i=0;i<array.length;i++){
	//     for(let j=0;j<array[i].length;j++){
	//         if(array[i][j]==num){
	//             return '有'
	//         }
	//     }
	// }
	// 解法三.陣列扁平化,然後indexOf查詢
	let newArray = toStr(array)
	console.log(newArray)
	if (newArray.indexOf(num) != -1) {
		return console.log('有');
	}
	return console.log('沒有');
}

// 陣列扁平化
function toStr(arr) {
	return arr.toString().split(',').map(item => {
		return Number(item)
	})
}

let ary = [[1, 2, 3, 4], [2, 3, 4, 5]]
sortList(ary, 5)

題目二: 替換空格: 請實現一個函式,將一個字串中的空格替換成“%20”。例如,當字串為 We Are Happy.則經過替換之後的字串為 We%20Are%20Happy

function replaceSpace(str) {
	// 解法一:暴力for迴圈對比
	// let newStr=''
	// for(let i=0;i<str.length;i++){
	//     if(str[i]==' '){
	//         newStr+='%20'
	//     }else{
	//         newStr+=str[i]
	//     }
	// }
	// console.log(newStr)
	// return newStr

	// 解法二:split分割成陣列,再進行join轉字串
	// let newStr = str.split分割成陣列,再進行join轉字串(" ").join("%20");
	// console.log(newStr)
	// return newStr
	// 解法三:正則
	// var reg = / /g;
	// let newStr=str.replace(reg, "%20");
	// console.log(newStr)
	// return newStr
}
replaceSpace('We Are Happy')

題目三:從尾到頭列印連結串列: 輸入一個連結串列,從尾到頭列印連結串列每個節點的值。

思路,利用棧的特性先進後出,模擬壓棧,然後再進行出棧實現

class Node {
	constructor(data) {
		this.data = data
		this.next = null
	}
}

function printNode(node) {
	console.log(node)
	// 壓棧實現
	let stock = new Array()
	let NodeNextElm = node
	while (NodeNextElm !== null) {
		// console.log(stock)
		stock.push(NodeNextElm.data)
		NodeNextElm = NodeNextElm.next
	}
	while (stock.length > 0) {
		console.log(stock.pop())
	}
}

const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
node1.next = node2
node2.next = node3
printNode(node1)

題目四:重建二叉樹: 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列 {1,2,4,7,3,5,6,8}和中序遍歷序列 {4,7,2,1,5,3,8,6},則重建二叉樹並返回。

一.

①[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]-> val=>1 ->L([2,4,7],[4,7,2]) & R([3,5,6,8],[5,3,8,6]) 根節點 1 ,有左右節點

二.

①L([2,4,7],[4,7,2])-> val=>2 ->L([4,7],[4,7]) && R(null , null) 根節點2(屬1的左節點) ,有左節點,無右節點

②R([3,5,6,8],[5,3,8,6])-> val=>3 ->L([5],[5]) && R([6,8],[6,8]) 根節點3(屬1的右節點) ,有左右節點

三.

①L([4,7],[4,7]) ->val=>4 -> L(null , null) && R([7],[7]) 根節點4(屬2的左節點) ,有右節點,無左節點

②R([6,8],[8,6]) -> val=>6 -> L([8] , [8]) && R(null , null) 根節點6(屬3的右節點),有左節點,無右節點

③L([5],[5]) -> val=>5->(null,null)->終止 尾節點5(屬3的左節點)

四.

①R([7],[7]) -> val=>7 ->終止 尾節點7(屬4的右節點)

②L([8],[8]) -> val=>8 ->終止 尾節點8(屬6的左節點)


function rebuildBinaryTree(front, centre) {
	if (!front || front.length == 0) {
		return null;
	}
	var TreeNode = {
		val: front[0]
	};
	for (var i = 0; i < front.length; i++) {
		//找到中序遍歷根節點位置
		if (centre[i] === front[0]) {
			//對於中序遍歷,根節點左邊的節點位於二叉樹的左邊,根節點右邊的節點位於二叉樹的右邊
			TreeNode.left = rebuildBinaryTree(front.slice(1, i + 1), centre.slice(0, i));
			TreeNode.right = rebuildBinaryTree(front.slice(i + 1), centre.slice(i + 1));
		}
	}
	return TreeNode;
}
let tree = rebuildBinaryTree([1, 2, 4, 7, 3, 5, 6, 8], [4, 7, 2, 1, 5, 3, 8, 6])
console.log(tree)

題目五:用兩個棧實現佇列: 用兩個棧來實現一個佇列,完成佇列的 Push 和 Pop 操作。

思路:使用兩個陣列模擬棧,一個用於push一個用於pop

let stack_push = []
let stack_pop = []
function pushData(data) {
	stack_push.push(data)
}
function popData() {
	if (stack_pop.length > 0) {
		console.log(stack_pop.pop())
	} else {
		if (stack_push.length > 0) {
			while (stack_push.length > 0) {
				stack_pop.push(stack_push.pop())
			}
			console.log(stack_pop.pop());
		} else {
			console.log('佇列為空');
		}
	}
}
pushData(1)
pushData(2)
pushData(3)
pushData(4)
console.log(stack_push);
console.log(stack_pop);
popData()
console.log(stack_push);
console.log(stack_pop);
pushData(5)
console.log(stack_push);
console.log(stack_pop);
popData()
popData()
popData()
popData()
popData()
console.log(stack_push);
console.log(stack_pop);

題目六:旋轉陣列的最小數字: 把一個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。 輸入一個非遞減排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為 1。NOTE:給出的所有元素都大於 0,若陣列大小為 0,請返回 0。

function revoleArray(array) {
	let min = array[0];
	let index = 0;
	for (let i = 0; i < array.length; i++) {
		if (array[i] < min) {
			min = array[i]
			index = i
		}
	}
	let newArray = array.slice(0, index)
	let newArray2 = array.slice(index)
	return newArray2.concat(newArray)
}
let newArray = revoleArray([3, 4, 5, 1, 2])
console.log(newArray)

題目七:斐波那契數列: 大家都知道斐波那契數列,現在要求輸入一個整數 n,請你輸出斐波那契數列的第 n 項,n<=39。

思路:斐波那契數列:[1,1,2,3,5,8,13,...] 每個數等於前兩個數之和

//解法一:遞迴
function fbnq(n) {
	if (n <= 1) {
		return 1
	}
	return fbnq(n - 1) + fbnq(n - 2)
}
// 解法二:迴圈
function Fibonacci(n) {
	if (n <= 1) {
		return 1;
	} else {
		let before_one=0,before_two=0,result=0,List=[]
		for(let i=0;i<=n;i++){
			before_one=List[i-1]>=0?List[i-1]:0
			before_two=List[i-2]>=0?List[i-2]:0
			result=before_one + before_two
			if(result<=1)result=1
			List.push(result)
		}
		return List[n]
	}
}
let a = fbnq(5)
console.log(a);
let b = Fibonacci(5)
console.log(b);

題目八:跳臺階: 一隻青蛙一次可以跳上 1 級臺階,也可以跳上 2 級。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。

思路:jump(1)=1 jump(2)=2 jump(3)=3 jump(4)=5 jump(5)=8 類似於斐波那契數列只不過就是前兩項變為1,2

function jump(n){
	if(n<=2){
		return n;
	}
	return jump(n-1) + jump(n-2)
}
let jumpNum=jump(5)
console.log(jumpNum);

題目九:變態跳臺階: 一隻青蛙一次可以跳上 1 級臺階,也可以跳上 2 級……它也可以跳上 n 級。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。

思路:jump(1)=1 jump(2)=2 jump(3)=4 jump(4)=8 2的n次方

function btJump(n){
// 解法一:用位運算子       2的n次方最簡單就是用位運算子 1<<n(將1左移n位數)   1:0001   2:0010  4:0100  8:1000
	// return 1<<(--n);

	// 解法二:遞迴
	if(n<=1){
		return n
	}else{
		return 2*btJump(n-1) 
	}
}
let jumpNum=btJump(5)
console.log(jumpNum);

題目十:矩形覆蓋: 我們可以用 21 的小矩形橫著或者豎著去覆蓋更大的矩形。請問用 n 個 21 的小矩形無重疊地覆蓋一個 2*n 的大矩形,總共有多少種方法?


 function rectCover(number) {
	if (number <= 2) {
		return number;
	} else {
		return rectCover(number - 1) + rectCover(number - 2);
	}
}
let rectNum=rectCover(4)
console.log(rectNum);

題目十一:二進位制中 1 的個數: 輸入一個整數,輸出該數二進位制表示中 1 的個數。其中負數用補碼錶示。

思路:一、使用split('')將其轉換為字元陣列然後reduce進行累加 二、暴力for迴圈判斷


function countOneNum(num) {
	let count=0;
	// toString(2)轉化為二進位制
	// 解法一:使用split('')將其轉換為字元陣列然後reduce進行累加
	count = num.toString(2).split('').reduce((acc, cur) => {
		console.log(acc, cur)
		return acc + parseInt(cur)
	}, 0); 
	let Binary=num.toString(2)
	// 解法二:for迴圈
	for(let i=0;i<Binary.length;i++){
		if(Binary[i]==1)count++
	}
	return count
}
let count = countOneNum(5)
console.log(count);

題目十二:數值的整數次方: 給定一個 double 型別的浮點數 base 和 int 型別的整數 exponent。求 base 的 exponent 次方。


function md(base,exponent){
	if(exponent<0){
		if(base<0){
			return '我也不知道怎麼變負數'
		}else{
			return 1/md(base,-exponent)
		}
	}else if(exponent==0){
		return 1
	}else{
		return base*md(base,exponent-1)
	}
}
let total=md(2.33,-5)
console.log(total);

題目十三:調整陣列順序使奇數位於偶數前面: 輸入一個整數陣列,實現一個函式來調整該陣列中數字的順序,使得所有的奇數位於陣列的前半部分,所有的偶數位於位於陣列的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。

思路:迴圈找出奇偶列表,然後concat合併


function changeArray(array) {
	let jList = [], oList = []
	array.forEach(item => {
		if (item % 2 == 0) {
			oList.push(item)
		} else {
			jList.push(item)
		}
	});
	return jList.concat(oList)
}
let NewArray = changeArray([2, 3, 4, 5, 9, 8, 7])
console.log(NewArray);

題目十四:連結串列中倒數第 k 個節點: 輸入一個連結串列,輸出該連結串列中倒數第 k 個結點。

思路:模擬棧將連結串列push進棧,隨後判斷k是否大於等於連結串列的長度,反轉陣列再取出下標為k-1的節點


class Node{
	constructor(data){
		this.data=data
		this.next=null
	}
}
function getIndexNode(node,index){
	let stack=[]
	let nextNodeElm=node
	while(nextNodeElm!=null){
		stack.push(nextNodeElm.data)
		nextNodeElm=nextNodeElm.next
	}
	if(stack.length<index){
		return '輸入的節點請小於等於連結串列長度'
	}
	stack.reverse()
	return stack[index-1]
}
const node1=new Node(1)
const node2=new Node(2)
const node3=new Node(3)
const node4=new Node(4)
const node5=new Node(5)
node1.next=node2
node2.next=node3
node3.next=node4
node4.next=node5
let node=getIndexNode(node1,5)
console.log(node)

題目十五:反轉連結串列: 輸入一個連結串列,反轉連結串列後,輸出連結串列的所有元素。

class Node {
	constructor(data) {
		this.data = data
		this.next = null
	}
}

function revolveNode(node) {
	if (node == null) {
		return false;
	}
	let p1 = node, p2 = null, temp = null;
	while (p1) {
		temp = p1.next;
		p1.next = p2;
		p2 = p1;
		p1 = temp;
	}
	return p2;
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
const node4 = new Node(4)
const node5 = new Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
let node = revolveNode(node1)
console.log(node)

題目十六:合併兩個排序的連結串列: 輸入兩個單調遞增的連結串列,輸出兩個連結串列合成後的連結串列,當然我們需要合成後的連結串列滿足單調不減規則。

class Node {
	constructor(data) {
		this.data = data
		this.next = null
	}
}

function Merge(node1, node2) {
	console.log(node1, node2);
	if (node1 == null) {
		return node2;
	} else if (node2 == null) {
		return node1;
	}
	var result = {};
	if (node1.data < node2.data) {
		result = node1;
		result.next = Merge(node1.next, node2);
	} else {
		result = node2;
		result.next = Merge(node1, node2.next);
	}
	return result;
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
const node4 = new Node(4)
const node5 = new Node(5)
const node6 = new Node(6)
const node7 = new Node(7)
const node8 = new Node(8)
const node9 = new Node(9)
const node10 = new Node(10)
node1.next = node2
node2.next = node3
node3.next = node5
node4.next = node6
node5.next = node7
node6.next = node8
node8.next = node9
node9.next = node10
let newNode=Merge(node1,node4)
console.log(newNode);

題目十七:順時針列印矩陣: 輸入一個矩陣,按照從外向裡以順時針的順序依次列印出每一個數字

例如,如果輸入如下矩陣:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
則依次列印出數字 1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10
思路:依次順序列印出第一行,然後逆時針旋轉矩陣,繼續列印第一行,直到完成

function rotateMatrix90Clockwise(matrix) {
	const numRows = matrix.length;
	const numCols = matrix[0].length;
	let rotatedMatrix = new Array(numCols).fill(0).map(() => new Array(numRows));

	for (let i = 0; i < numRows; i++) {
		for (let j = 0; j < numCols; j++) {
			rotatedMatrix[numCols - j - 1][i] = matrix[i][j];
		}
	}

	return rotatedMatrix;
}
function printNum(array){
	let list=array.slice(0,1)[0]
	// console.log(list);
	let newList=list.reverse()
	while(newList.length>0){
		console.log(newList.pop())
	}
	// console.log(newList);
	array=array.slice(1,)
	if(array.length==0){
		return
	}
	let newArray=rotateMatrix90Clockwise(array)
	printNum(newArray)
}
const originalMatrix = [
	[1, 2, 3,4],
	[5, 6,7,8],
	[9,10,11,12],
	[13,14,15,16]
];

printNum(originalMatrix);

題目十八:定義一個棧,實現 min 函式:定義棧的資料結構,請在該型別中實現一個能夠得到棧最小元素的 min 函式。

let stack_push = []
let stack_pop = []
function pushData(data) {
	stack_push.push(data)
}

function popData() {
	if (stack_pop.length > 0) {
		console.log(stack_pop.pop());
	} else {
		if (stack_push.length > 0) {
			while (stack_push.length > 0) {
				stack_pop.push(stack_push.pop())
			}
			console.log(stack_pop.pop());
		} else {
			console.log('空棧')
		}
	}
}

function searchMin() {
	while (stack_pop.length > 0) {
		stack_push.push(stack_pop())
	}
	let min = stack_push[0]
	for (let index = 0; index < stack_push.length; index++) {
		if (stack_push[index] < min) {
			min = stack_push[index]
		}
	}
	return min
}
pushData(1)
pushData(2)
pushData(3)
pushData(0)
pushData(4)
let min = searchMin()
console.log(min);

題目十九:棧的壓入彈出:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為該棧的彈出順序。假設壓入棧的所有數字均不相等。

例如:序列 1,2,3,4,5 是某棧的壓入順序,序列 4,5,3,2,1 是該壓棧序列對應的一個彈出序列,但 4,3,5,1,2 就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

思路:一、模擬壓棧彈棧 二、直接反轉陣列進行pop比較

let stack_push = []
let stack_pop = []
function pushData(data) {
	stack_push.push(data)
}
function popData() {
	if (stack_pop.length > 0) {
		console.log(stack_pop.pop());
	} else {
		if (stack_push.length > 0) {
			while (stack_push.length > 0) {
				stack_pop.push(stack_push.pop())
			}
			console.log(stack_pop.pop());
		} else {
			console.log('空棧')
		}
	}
}
function testStack(pushStack,popStack){
	// 解法一:模擬壓棧彈棧
	// if(pushStack.length != popStack.length){
	//     return '不是'
	// }
	// let NewPushStack=pushStack.reverse()
	// let NewPopStack=popStack.reverse()
	// while(NewPushStack.length>0){
	//     pushData(NewPushStack.pop())
	// }
	// while(stack_push.length>0){
	//     if(stack_push.pop() != NewPopStack.pop())return '不對'
	// }
	// return '正確'

	// 解法二:直接反轉陣列進行pop比較
	if(pushStack.length != popStack.length){
		return '不是'
	}
	let NewPopStack=popStack.reverse()
	while(pushStack.length>0){
		if(pushStack.pop() != NewPopStack.pop())return '不對'
	}
	return '正確'
}
let result=testStack([1,2,3,4,5],[5,4,3,2,1])
console.log(result);

題目二十:複雜連結串列的複製:輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的 head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空)

function copyNode(pHead){
	console.log(pHead)
	if (!pHead) {
		return null;
	}
	// 複製頭結點
	var node = new Node(pHead.data);
	node.other = pHead.other;
	// 遞迴其他節點
	node.next = copyNode(pHead.next);
	return node;
}
class Node {
	constructor(data) {
		this.data = data
		this.next = null
		this.other = null
	}
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
node1.next = node2
node2.next = node3
node1.other = node2
node2.other = node3
node3.other = node1
let newNode=copyNode(node1)
console.log(newNode);

題目二十一:字串的排列:輸入一個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串 abc,則列印出由字元 a,b,c 所能排列出來的所有字串 abc,acb,bac,bca,cab 和 cba。輸入描述:輸入一個字串,長度不超過 9(可能有字元重複),字元只包括大小寫字母。

 function permute(str, left = 0, right = str.length - 1) {  //abc left 2
	console.log(left,right)
	// 如果左邊界等於右邊界,說明只剩下一個字元,列印它
	if (left === right) {
		console.log("結果:",str);
	} else {
		// 遍歷從l到r的每個位置
		for (let i = left; i <= right; i++) {
			// 將當前位置i的字元與左邊界l的字元交換
			str = swap(str, left, i);
			console.log("str:",str,"left:",left,"I:",i);
			// 遞迴地對剩餘的子字串進行排列(注意left+1表示排除已固定的字元)
			permute(str, left + 1, right);
			// 遞迴返回後,需要將字元交換回原來的位置,以便下一次迴圈使用原始字串
			str = swap(str, left, i);

		}
	}
}

function swap(str, i, j) {
	// 將字串轉換為字元陣列
	let arr = str.split('');
	// 解構交換元素
	[arr[i], arr[j]] = [arr[j], arr[i]];
	// 將修改後的陣列轉換回字串
	return arr.join('');
}

permute('abc');

題目二十二:陣列中出現次數超過一半的數字: 陣列中有一個數字出現的次數超過陣列長度的一半。請找出這個數字。例如輸入一個長度為 9 的陣列{1,2,3,2,2,2,5,4,2}。由於數字 2 在陣列中出現了 5 次,超過陣列長度的一半,因此輸出 2。如果不存在則輸出 0。

function moreAHalfNum(array){
	let length=array.length
	let maxLength=Math.floor(length/2)
	let computedTotal={}
	let maxNum=null
	array.forEach(item => {
		if(computedTotal[item]){
			computedTotal[item]++
			if(computedTotal[item]>maxLength)maxNum=item
		}else{
			computedTotal[item]=1
		}
	});
	return maxNum?maxNum:0
}
let num=moreAHalfNum([1,2,3,4,6,6,6,6,6])
console.log(num);

題目二十三:最小的 K 個數:輸入 n 個整數,找出其中最小的 K 個數。例如輸入 4,5,1,6,2,7,3,8 這 8 個數字,則最小的 4 個數字是 1,2,3,4 。

思路:先sort排序,此時陣列是從小到大排序,取前k個即可

function searchMinCountNum(array,K){
	let NewArray=array.sort()
	return NewArray.slice(0,K)
}
let countNum=searchMinCountNum([2,1,8,9,6,5],3)
console.log(countNum);

題目二十四:把陣列排成最小的數:輸入一個正整數陣列,把陣列裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。例如輸入陣列{3,32,321},則列印出這三個數字能排成的最小數字為 321323。

function PrintMinNumber(numbers) {
	numbers.sort(function (a, b) {
		var s1 = a + '' + b;
		var s2 = b + '' + a;
		for (var i = 0; i < s1.length; i++) {
			if (s1.charAt(i) > s2.charAt(i)) {
				return 1
			} else if (s1.charAt(i) < s2.charAt(i)) {
				return -1;
			}

		}
		return 1
	})
	console.log(numbers);
	var result = "";
	numbers.map(function (num) {
		result = result.concat(num)
	})
	return result;
}
let num=PrintMinNumber([32,3,321])
console.log(num);

題目二十五:醜數(待深入理解):把只包含質因子 2、3 和 5 的數稱作醜數。例如 6、8 都是醜數,但 14 不是,因為它包含因子 7。 習慣上我們把 1 當做是第一個醜數。求按從小到大的順序的第 N 個醜數。

function getUglyNumberSolution(index) {
	if (index == 0) return 0
	var uglys = [1];
	var factor2 = 0, factor3 = 0, factor5 = 0;
	for (var i = 1; i < index; i++) {
		uglys[i] = Math.min(uglys[factor2] * 2, uglys[factor3] * 3, uglys[factor5] * 5)
		if (uglys[i] == uglys[factor2] * 2) factor2++;
		if (uglys[i] == uglys[factor3] * 3) factor3++;
		if (uglys[i] == uglys[factor5] * 5) factor5++;
	}
	console.log(uglys);
	return uglys[index - 1]
}
let count=getUglyNumberSolution(11)
console.log(count);

題目二十六:第一個只出現一次的字元:在一個字串(1<=字串長度<=10000,全部由大寫字母組成)中找到第一個只出現一次的字元,並返回它的位置。

function getFirstChar(str){
	str=str.toUpperCase()
	let chat={}
	for (let i = 0; i < str.length; i++) {
		if(chat[str[i]]){
			chat[str[i]]++
		}else{
			chat[str[i]]=1
		}
	}
	console.log(chat);
	for (let i = 0; i <= str.length; i++) {
		if(chat[str[i]]==1){
			return str.indexOf(str[i]) +"=>"+str[i]
		}
	}
	return '無只出現一次的字元'
}
let index=getFirstChar('hheello')
console.log(index);

題目二十七:陣列中的逆序對:在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個陣列,求出這個陣列中的逆序對的總數 P。

function getReverseNum(array){
	let count=0
	let towNum=[]
	if(array.length>1){
		towNum=array.slice(0,2)
		console.log(towNum);
		if(towNum[0]>towNum[1]){
			count++
		}
		return count + getReverseNum(array.slice(2,))
	}
	return count
}
let num=getReverseNum([2,1,3,4,5,4,5,4,5,4,5,4])
console.log(num);

題目二十八:數字在排序陣列中出現的次數:統計一個數字:在排序陣列中出現的次數。例如輸入排序陣列{ 1, 2, 3, 3, 3, 3, 4, 5}和數字 3 ,由於 3 在這個陣列中出現了 4 次,因此輸出 4 。

function getNumFindCount(array,num){
	let count=0
	array.forEach(item => {
		if(item==num)count++
	});
	return count
}
let count=getNumFindCount([1,2,3,3,3,4,5],3)
console.log(count);

題目二十九:陣列中只出現一次的數字:一個整型陣列裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。

function getOnlyOneNum(array) {
	// 因為new Set去重後返回的是一個物件Set([1,2,...]),所以要用Array.from轉換為陣列
	let numList = Array.from(new Set(array))
	let onlyOneList = []
	numList.forEach(item => {
		let count = 0
		array.forEach(item2 => {
			if (item2 == item) count++
		})
		if (count == 1) onlyOneList.push(item)
	})
	console.log(onlyOneList);
}
getOnlyOneNum([1, 2, 2, 3, 3, 4])

題目三十:和為 S 的連續正數序列:小明很喜歡數學,有一天他在做數學作業時,要求計算出 9~16 的和,他馬上就寫出了正確答案是 100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為 100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為 100 的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和為 S 的連續正數序列?Good Luck!輸出描述:輸出所有和為 S 的連續正數序列。序列內按照從小至大的順序,序列間按照開始數字從小到大的順序。

function getTotalNum(sum) {
	if (sum < 2) return [];
	var result = [];
	var a = 0, b = 0, total = 0;
	while (a <= Math.floor(sum / 2)) {
		if (total < sum) {
			b++;
			total += b;
		} else if (total > sum) {
			total -= a
			a++;
		} else {
			var temp = [];
			for (var i = a; i <= b; i++) {
				temp.push(i)
			}
			result.push(temp)
			if (a + 1 < b) {
				total -= a;
				a++
			} else {
				break;
			}
		}
	}
	return result;
}
let list=getTotalNum(100)
console.log(list);

題目三十一:和為 S 的兩個數字:輸入一個遞增排序的陣列和一個數字 S,在陣列中查詢兩個數,是的他們的和正好是 S,如果有多對數字的和等於 S,輸出兩個數的乘積最小的。輸出描述:對應每個測試案例,輸出兩個數,小的先輸出。


function totaleqNum(array, sum) {
	let list = []
	for (let i = 0; i < array.length; i++) {
		for (let j = i + 1; j < array.length; j++) {
			if (array[i] + array[j] == sum) {
				let data = {
					list: [array[i], array[j]],
					result: array[i] * array[j]
				}
				list.push(data)
			}
		}
	}
	if (list.length > 1) {
		let min = list[0].result
		list.forEach(item => {

			if (item.result < min) {
				return item.list
			}
		})
		return list[0].list
	}

	return list[0].list
}
let result=totaleqNum([1, 2, 3, 4, 5, 6], 5)
console.log(result);

題目三十二:左旋轉字串:組合語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字串模擬這個指令的運算結果。對於一個給定的字元序列 S,請你把其迴圈左移 K 位後的序列輸出。例如,字元序列 S=”abcXYZdef”,要求輸出迴圈左移 3 位後的結果,即 “XYZdefabc”。

function transformStr(str,left){
	if(left>str.length){
		return '位移長度不能超過字元長度'
	}
	let leftStr=str.slice(left,)
	let rightStr=str.slice(0,left)
	return leftStr+rightStr
}
let newStr=transformStr('hello',2)
console.log(newStr);

題目三十三:翻轉單詞順序列:牛客最近來了一個新員工 Fish,每天早晨總是會拿著一本英文雜誌,寫些句子在本子上。同事 Cat 對 Fish 寫的內容頗感興趣,有一天他向 Fish 借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。後來才意識到,這傢伙原來把句子單詞的順序翻轉了 ,正確的句子應該是“I am a student.”。Cat 對一一的翻轉這些單詞順序可不在行,你能幫助他麼?

思路:split對字串按照空格分隔成陣列,然後reverse反轉陣列,最後join合併成字串

function revolveStr(str){
	return newStrList=str.split(" ").reverse().join(" ")
}
let newStr=revolveStr("I am a student.")
console.log(newStr);

題目三十四:1+2+3+...+n:求 1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case 等關鍵字及條件判斷語句(A?B:C)。

function totalNum(n){
	var sum=n;
	var a=(n>0)&&((sum+=totalNum(n-1))>0)
	return sum
}
let total=totalNum(3)
console.log(total);

題目三十五:把字串轉換成整數。:將一個字串轉換成一個整數,要求不能使用字串轉換整數的庫函式。數值為 0 或者字串不是一個合法的數值則返回 0。輸入描述:輸入一個字串,包括數字字母符號,可以為空。輸出描述:如果是合法的數值表達則返回該數字,否則返回 0。

思路:迴圈字串,判斷每個字元是否為數字,因為不能使用字串轉換整數的庫函式,所以要定義一個函式判斷字串是否在0~9之間,是即為數字。

function strToNumber(str){
	let newStr=''
	for (let i = 0; i < str.length; i++) {
		if(isNumber(str[i])){
			newStr+=str[i]
		}
	}
	return newStr
}
function isNumber(data){
	if(data>=0 || data<=9){
		return true
	}
	return false
}
let newStr=strToNumber('+2147#48^3647')
console.log(newStr);

題目三十六:陣列中重複的數字:在一個長度為 n 的陣列裡的所有數字都在 0 到 n-1 的範圍內。陣列中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。

思路,使用set對陣列進行去重,然後對陣列進行遍歷,再去遍歷原陣列,找出陣列裡第一個出現重複數字,隨機try catch丟擲異常進行中斷遍歷並進行返回

function searchFirstFindTwoNum(array) {
	try {
		Array.from(new Set(array)).forEach(item => {
			let count = 0
			array.forEach(item2 => {
				if (item == item2) count++
				if (count > 1) throw new Error(item)
			})
		})
	} catch (e) {
		return e.message
	}
	return '陣列內無重複數字'
}
let number = searchFirstFindTwoNum([1, 2, 3, 3, 4, 5])
console.log(number);

題目三十七:構建乘積陣列:給定一個陣列 A[0,1,...,n-1],請構建一個陣列 B[0,1,...,n-1],其中 B 中的元素 B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法。

function getTotalList(array) {
	let newArray = []
	for (let i = 0; i < array.length; i++) {
		newArray[i] = getTotal(array) * array[i-1]-array[i+1]
		console.log(newArray[i]);
	}
	return newArray
}
function getTotal(array) {
	let total = 1;
	array.forEach(item => total *= item);
	return total
}
let newArray = getTotalList([2, 4, 6, 7, 8])
console.log(newArray);

題目三十八:字元流中第一個不重複的字元:請實現一個函式用來找出字元流中第一個只出現一次的字元。例如,當從字元流中只讀出前兩個字元 "go" 時,第一個只出現一次的字元是 "g" 。當從該字元流中讀出前六個字元 "google" 時,第一個只出現一次的字元是 "l"。 輸出描述:如果當前字元流沒有存在出現一次的字元,返回#字元。

思路:先對原陣列進行去重獲取字元列表,隨後單個出現單詞給個預設值為首個字元,方便後續判斷,首先遍歷去重後的字元陣列,根據每個字元對原字串進行遍歷查詢是否重複,如果出現重複且重複詞與單個出現字元不一致,則證明出現首個單一字元,則丟擲異常結束遍歷並返回,當重複時單個出現字元為當前字元,如果是則表示前面並無單一字元,並判斷當前位置是否已經遍歷到最末端了,如果不是繼續下一個字元的遍歷,如果當前位置為字串倒數第二的位置,則下一個字元必定為單一出現單詞,則直接返回。

function searchFirstFindOneStr(str) {
	try {
		let array = Array.from(new Set(str.split("")))
		let keyword = array[0]
		array.forEach(item => {
			let count = 0
			for (let i = 0; i < str.length; i++) {
				if (item == str[i]) count++
				if (count > 1 && keyword != str[i]) throw new Error(keyword)
				if (count > 1 && keyword == str[i]) {
					count = 0
					if (i < str.length-1 && i < str.length - 2) keyword = str[i + 1]
					if (i == str.length - 2) throw new Error(str[str.length - 1])
				}
			}
		})
	} catch (e) {
		return e.message
	}
	return '#'
}
let str = searchFirstFindOneStr("hheello66")
console.log(str);

題目三十九:資料流中的中位數(待深入理解):如何得到一個資料流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有值排序之後位於中間的數值。如果資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。

function getCenterNum(array){ //[1,2,3,4,5]
	let index=Math.floor(array.length/2)
	let newArray=array.sort()
	if(newArray.length%2==0){
		return (newArray[index-1]+newArray[index])/2
	}else{
		return newArray[index]
	}
}
let num=getCenterNum([3,2,3,7,5,6])
console.log(num);

題目四十:滑動視窗中的最大值(待深入理解):給定一個陣列和滑動視窗的大小,找出所有滑動視窗裡數值的最大值。例如,如果輸入陣列{2,3,4,2,6,2,5,1}及滑動視窗的大小 3,那麼一共存在 6 個滑動視窗,他們的最大值分別為{4,4,6,6,6,5};

思路:針對陣列{2,3,4,2,6,2,5,1}的滑動視窗有以下 6 個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
最大值分別就是每個視窗[2,3,4],[3,4,2],[4,2,6],[2,6,2],[6,2,5],[2,5,1]中元素最大的一個,即為[4,4,6,6,6,5]

function slideWindowMax(array,size){
	let allWindows=[],allMax=[]
	while(array.length>=size){
		allWindows.push(array.slice(0,size))
		array=array.slice(1,)
	}
	allWindows.forEach(i => {
		let max=i[0]
		i.forEach(j=>{
			if(j>max)max=j
		})
		allMax.push(max)
	});
	return allMax
}
let maxList=slideWindowMax([2,3,4,2,6,2,5,1],3)
console.log(maxList);

上述為個人學習整理內容,水平有限,如有錯誤之處,望各位園友不吝賜教!如果覺得不錯,請點個贊和關注支援一下!謝謝~๑•́₃•̀๑ \❀❀❀

相關文章