JavaScript 算法面试题精选 本文整理了常见的 JavaScript 编程面试题型,包含详细的代码示例与解析,帮助你应对技术面试中的编程挑战。
1. 字符串处理 1.1 判断回文字符串 判断一个字符串是否为回文字符串(正读和反读都一样)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 function isPalindrome (s ) { const cleanStr = s.toLowerCase ().replace (/[^a-z0-9]/g , "" ); let left = 0 , right = cleanStr.length - 1 ; while (left < right) { if (cleanStr[left] !== cleanStr[right]) { return false ; } left++; right--; } return true ; } console .log (isPalindrome ("A man, a plan, a canal: Panama" )); console .log (isPalindrome ("race a car" ));
1.2 最长不重复子串 找出字符串中最长的不包含重复字符的子串长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function lengthOfLongestSubstring (s ) { const charMap = new Map (); let maxLength = 0 ; let left = 0 ; for (let right = 0 ; right < s.length ; right++) { const currentChar = s[right]; if (charMap.has (currentChar) && charMap.get (currentChar) >= left) { left = charMap.get (currentChar) + 1 ; } maxLength = Math .max (maxLength, right - left + 1 ); charMap.set (currentChar, right); } return maxLength; } console .log (lengthOfLongestSubstring ("abcabcbb" )); console .log (lengthOfLongestSubstring ("bbbbb" ));
2. 数组处理 2.1 查找数组中的重复数字 找出数组中任意一个重复的数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function findDuplicate (nums ) { const seen = new Set (); for (const num of nums) { if (seen.has (num)) { return num; } seen.add (num); } return -1 ; } console .log (findDuplicate ([1 , 2 , 3 , 4 , 2 ])); console .log (findDuplicate ([1 , 2 , 3 , 4 ]));
2.2 旋转数组 将数组向右旋转 k 步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function rotateArray (nums, k ) { k = k % nums.length ; reverse (nums, 0 , nums.length - 1 ); reverse (nums, 0 , k - 1 ); reverse (nums, k, nums.length - 1 ); return nums; function reverse (arr, start, end ) { while (start < end) { [arr[start], arr[end]] = [arr[end], arr[start]]; start++; end--; } } } console .log (rotateArray ([1 , 2 , 3 , 4 , 5 , 6 , 7 ], 3 ));
3. 栈/队列 3.1 有效括号 判断括号是否有效闭合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function isValidParentheses (s ) { const stack = []; const pairs = { ")" : "(" , "}" : "{" , "]" : "[" , }; for (const char of s) { if (!pairs[char]) { stack.push (char); } else if (stack.pop () !== pairs[char]) { return false ; } } return stack.length === 0 ; } console .log (isValidParentheses ("()[]{}" )); console .log (isValidParentheses ("([)]" ));
3.2 逆波兰表达式求值 计算逆波兰表达式(后缀表达式)的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function evalRPN (tokens ) { const stack = []; const operators = { "+" : (a, b ) => a + b, "-" : (a, b ) => a - b, "*" : (a, b ) => a * b, "/" : (a, b ) => Math .trunc (a / b), }; for (const token of tokens) { if (operators[token]) { const b = stack.pop (); const a = stack.pop (); stack.push (operators[token](a, b)); } else { stack.push (Number (token)); } } return stack[0 ]; } console .log (evalRPN (["2" , "1" , "+" , "3" , "*" ])); console .log (evalRPN (["4" , "13" , "5" , "/" , "+" ]));
4. 哈希表 4.1 两数之和 找出数组中和为目标值的两个数的下标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 function twoSum (nums, target ) { const numMap = new Map (); for (let i = 0 ; i < nums.length ; i++) { const complement = target - nums[i]; if (numMap.has (complement)) { return [numMap.get (complement), i]; } numMap.set (nums[i], i); } return []; } console .log (twoSum ([2 , 7 , 11 , 15 ], 9 ));
4.2 找众数 找出数组中出现次数超过一半的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function majorityElement (nums ) { const countMap = new Map (); const threshold = nums.length / 2 ; for (const num of nums) { const count = (countMap.get (num) || 0 ) + 1 ; countMap.set (num, count); if (count > threshold) { return num; } } } console .log (majorityElement ([3 , 2 , 3 ])); console .log (majorityElement ([2 , 2 , 1 , 1 , 1 , 2 , 2 ]));
5. 排序/查找 5.1 合并重叠区间 合并所有重叠的区间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 function mergeIntervals (intervals ) { if (intervals.length <= 1 ) return intervals; intervals.sort ((a, b ) => a[0 ] - b[0 ]); const result = [intervals[0 ]]; for (let i = 1 ; i < intervals.length ; i++) { const currentInterval = intervals[i]; const lastMerged = result[result.length - 1 ]; if (currentInterval[0 ] <= lastMerged[1 ]) { lastMerged[1 ] = Math .max (lastMerged[1 ], currentInterval[1 ]); } else { result.push (currentInterval); } } return result; } console .log ( mergeIntervals ([ [1 , 3 ], [2 , 6 ], [8 , 10 ], [15 , 18 ], ]) );
5.2 手写快速排序 实现快速排序算法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function quickSort (arr ) { if (arr.length <= 1 ) return arr; const pivot = arr[Math .floor (arr.length / 2 )]; const left = []; const right = []; const equal = []; for (const num of arr) { if (num < pivot) { left.push (num); } else if (num > pivot) { right.push (num); } else { equal.push (num); } } return [...quickSort (left), ...equal, ...quickSort (right)]; } console .log (quickSort ([3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 ]));
6. 模拟类题 6.1 简易购物车系统 实现一个简单的购物车系统,支持添加、删除商品和计算总价。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 class ShoppingCart { constructor ( ) { this .items = new Map (); } addItem (product, quantity = 1 ) { const { id, name, price } = product; if (this .items .has (id)) { const item = this .items .get (id); item.quantity += quantity; } else { this .items .set (id, { product : { id, name, price }, quantity }); } console .log (`已添加 ${quantity} 个 ${name} 到购物车` ); } removeItem (productId, quantity = null ) { if (!this .items .has (productId)) { console .log ("购物车中没有该商品" ); return ; } const item = this .items .get (productId); if (quantity === null || quantity >= item.quantity ) { this .items .delete (productId); console .log (`已从购物车移除所有 ${item.product.name} ` ); } else { item.quantity -= quantity; console .log (`已从购物车移除 ${quantity} 个 ${item.product.name} ` ); } } getTotalPrice ( ) { let total = 0 ; for (const item of this .items .values ()) { total += item.product .price * item.quantity ; } return total; } viewCart ( ) { if (this .items .size === 0 ) { console .log ("购物车为空" ); return ; } console .log ("购物车内容:" ); for (const item of this .items .values ()) { const { name, price } = item.product ; console .log ( `${name} - 单价: ¥${price} x ${item.quantity} = ¥${ price * item.quantity } ` ); } console .log (`总价: ¥${this .getTotalPrice()} ` ); } } const cart = new ShoppingCart ();cart.addItem ({ id : "p1" , name : "iPad" , price : 3299 }); cart.addItem ({ id : "p2" , name : "AirPods" , price : 1299 }, 2 ); cart.viewCart (); cart.removeItem ("p1" ); cart.viewCart ();
7. 简易算法 7.1 斐波那契数列 计算斐波那契数列的第 n 项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function fibonacci (n ) { if (n <= 1 ) return n; let prev = 0 ; let curr = 1 ; for (let i = 2 ; i <= n; i++) { const next = prev + curr; prev = curr; curr = next; } return curr; } console .log (fibonacci (10 )); console .log (fibonacci (20 ));
7.2 最大公约数 计算两个数的最大公约数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function gcd (a, b ) { if (a < b) [a, b] = [b, a]; while (b !== 0 ) { const temp = b; b = a % b; a = temp; } return a; } console .log (gcd (54 , 24 )); console .log (gcd (105 , 45 ));
8. 数据结构 8.1 LRU 缓存实现 实现一个 LRU (最近最少使用) 缓存结构,支持 get 和 put 操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 class LRUCache { constructor (capacity ) { this .capacity = capacity; this .cache = new Map (); } get (key ) { if (!this .cache .has (key)) { return -1 ; } const value = this .cache .get (key); this .cache .delete (key); this .cache .set (key, value); return value; } put (key, value ) { if (this .cache .has (key)) { this .cache .delete (key); } else if (this .cache .size >= this .capacity ) { const oldestKey = this .cache .keys ().next ().value ; this .cache .delete (oldestKey); } this .cache .set (key, value); } } const lruCache = new LRUCache (2 );lruCache.put (1 , 1 ); lruCache.put (2 , 2 ); console .log (lruCache.get (1 )); lruCache.put (3 , 3 ); console .log (lruCache.get (2 ));
以上就是常见的 JavaScript 面试编程题整理,希望这些例子和解析能够帮助你准备技术面试。每种类型的题目都涵盖了相关的知识点,包括算法思想和 JavaScript 的特性运用。
祝面试顺利!
参考资料:
LeetCode 题库: https://leetcode.com/
JavaScript 数据结构与算法: https://github.com/trekhleb/javascript-algorithms