以下是针对前端面试精选的 20 道算法题及 JavaScript 解答,涵盖高频考点和实际应用场景:
1. 两数之和
题目:给定数组和整数 target,返回和为 target 的两个元素的索引
function twoSum(nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (map.has(complement)) {
return [map.get(complement), i];
}
map.set(nums[i], i);
}
return [];
}
2. 有效的括号
题目:判断只包含 ()[]{} 的字符串是否有效
function isValid(s) {
const stack = [];
const map = { '(': ')', '[': ']', '{': '}' };
for (let char of s) {
if (map[char]) {
stack.push(char);
} else {
if (stack.length === 0) return false;
const top = stack.pop();
if (map[top] !== char) return false;
}
}
return stack.length === 0;
}
3. 反转链表
题目:反转单链表
function reverseList(head) {
let prev = null;
let curr = head;
while (curr) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
4. 合并两个有序数组
题目:将 nums2 合并到 nums1 中(nums1 有足够空间)
function merge(nums1, m, nums2, n) {
let i = m - 1, j = n - 1, k = m + n - 1;
while (j >= 0) {
nums1[k--] = (i >= 0 && nums1[i] > nums2[j])
? nums1[i--]
: nums2[j--];
}
}
5. 二叉树的层序遍历
题目:返回二叉树节点值的层序遍历结果
function levelOrder(root) {
if (!root) return [];
const result = [];
const queue = [root];
while (queue.length) {
const level = [];
const size = queue.length;
for (let i = 0; i < size; i++) {
const node = queue.shift();
level.push(node.val);
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
result.push(level);
}
return result;
}
6. 最长无重复子串
题目:给定字符串,返回最长无重复字符的子串长度
function lengthOfLongestSubstring(s) {
const map = new Map();
let max = 0;
let left = 0;
for (let right = 0; right < s.length; right++) {
const char = s[right];
if (map.has(char) && map.get(char) >= left) {
left = map.get(char) + 1;
}
map.set(char, right);
max = Math.max(max, right - left + 1);
}
return max;
}
7. 三数之和
题目:在数组中找到所有和为 0 的三元组
function threeSum(nums) {
nums.sort((a, b) => a - b);
const result = [];
for (let i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue;
let left = i + 1, right = nums.length - 1;
while (left < right) {
const sum = nums[i] + nums[left] + nums[right];
if (sum === 0) {
result.push([nums[i], nums[left], nums[right]]);
while (left < right && nums[left] === nums[left + 1]) left++;
while (left < right && nums[right] === nums[right - 1]) right--;
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return result;
}
8. 最长回文子串
题目:返回字符串中的最长回文子串
function longestPalindrome(s) {
let max = "";
for (let i = 0; i < s.length; i++) {
// 奇数和偶数长度回文
for (let j = 0; j < 2; j++) {
let left = i, right = i + j;
while (left >= 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
const substr = s.substring(left + 1, right);
if (substr.length > max.length) max = substr;
}
}
return max;
}
9. 爬楼梯
题目:每次爬 1 或 2 阶,到 n 阶有多少种方法
function climbStairs(n) {
if (n <= 2) return n;
let a = 1, b = 2;
for (let i = 3; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
}
10. 最大子数组和
题目:返回具有最大和的连续子数组的和
function maxSubArray(nums) {
let max = nums[0];
let current = nums[0];
for (let i = 1; i < nums.length; i++) {
current = Math.max(nums[i], current + nums[i]);
max = Math.max(max, current);
}
return max;
}
11. 二叉树的最大深度
题目:计算二叉树的最大深度
function maxDepth(root) {
if (!root) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
12. 买卖股票最佳时机
题目:只允许一次交易的最大利润
function maxProfit(prices) {
let min = Infinity;
let max = 0;
for (let price of prices) {
min = Math.min(min, price);
max = Math.max(max, price - min);
}
return max;
}
13. 字符串相加
题目:用字符串表示的大数相加
function addStrings(num1, num2) {
let i = num1.length - 1, j = num2.length - 1;
let carry = 0, res = "";
while (i >= 0 || j >= 0 || carry) {
const n1 = i >= 0 ? +num1[i--] : 0;
const n2 = j >= 0 ? +num2[j--] : 0;
const sum = n1 + n2 + carry;
carry = Math.floor(sum / 10);
res = (sum % 10) + res;
}
return res;
}
14. 缺失的第一个正数
题目:找出未排序数组中缺失的最小正整数
function firstMissingPositive(nums) {
const n = nums.length;
// 标记非正数
for (let i = 0; i < n; i++) {
if (nums[i] <= 0) nums[i] = n + 1;
}
// 用索引标记存在性
for (let i = 0; i < n; i++) {
const num = Math.abs(nums[i]);
if (num <= n) {
nums[num - 1] = -Math.abs(nums[num - 1]);
}
}
// 找第一个正数索引
for (let i = 0; i < n; i++) {
if (nums[i] > 0) return i + 1;
}
return n + 1;
}
15. 接雨水
题目:计算柱子间能接多少雨水
function trap(height) {
let left = 0, right = height.length - 1;
let leftMax = 0, rightMax = 0;
let water = 0;
while (left < right) {
if (height[left] < height[right]) {
leftMax = Math.max(leftMax, height[left]);
water += leftMax - height[left];
left++;
} else {
rightMax = Math.max(rightMax, height[right]);
water += rightMax - height[right];
right--;
}
}
return water;
}
16. LRU 缓存
题目:设计实现 LRU 缓存
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.map = new Map();
}
get(key) {
if (!this.map.has(key)) return -1;
const val = this.map.get(key);
this.map.delete(key);
this.map.set(key, val);
return val;
}
put(key, value) {
if (this.map.has(key)) this.map.delete(key);
this.map.set(key, value);
if (this.map.size > this.capacity) {
this.map.delete(this.map.keys().next().value);
}
}
}
17. 全排列
题目:返回数组所有可能的全排列
function permute(nums) {
const result = [];
backtrack([], nums, result);
return result;
}
function backtrack(path, nums, result) {
if (path.length === nums.length) {
result.push([...path]);
return;
}
for (let num of nums) {
if (path.includes(num)) continue;
path.push(num);
backtrack(path, nums, result);
path.pop();
}
}
18. 岛屿数量
题目:计算二维网格中的岛屿数量
function numIslands(grid) {
let count = 0;
function dfs(i, j) {
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] === '0') return;
grid[i][j] = '0';
dfs(i + 1, j);
dfs(i - 1, j);
dfs(i, j + 1);
dfs(i, j - 1);
}
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] === '1') {
count++;
dfs(i, j);
}
}
}
return count;
}
19. 前 K 个高频元素
题目:返回数组中出现频率前 k 高的元素
function topKFrequent(nums, k) {
const freqMap = new Map();
for (const num of nums) {
freqMap.set(num, (freqMap.get(num) || 0) + 1);
}
return [...freqMap.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, k)
.map(entry => entry[0]);
}
20. 二叉搜索树中第K小元素
题目:在 BST 中查找第 k 个最小元素
function kthSmallest(root, k) {
const stack = [];
let curr = root;
while (curr || stack.length) {
while (curr) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
if (--k === 0) return curr.val;
curr = curr.right;
}
}
算法题考察重点
- 数据结构运用:数组/链表/树/哈希表的操作
- 双指针技巧:滑动窗口/快慢指针/左右指针
- 递归思维:DFS/回溯/分治算法
- 动态规划:状态转移/空间优化
- 贪心算法:局部最优解
- 边界处理:空值/极端值/特殊输入
- 时空复杂度:分析最优解法
💡 提示:面试时先厘清题意,举例说明思路,再编码实现,最后用测试用例验证