返回
前端常见算法题
前端
2023-10-06 17:49:08
本文将介绍前端面试中常见的一些算法题,并提供解决这些问题的思路和示例代码。本文适合初级到中级的前端工程师参考。文章中,我们将以 JavaScript 代码为例来解释算法,以便于前端工程师轻松理解和应用。
本文将涵盖以下算法题:
- 查找算法: 二分查找、哈希表查找
- 排序算法: 冒泡排序、快速排序、归并排序
- 搜索算法: 深度优先搜索、广度优先搜索
- 动态规划: 最长公共子序列、最短路径
- 贪心算法: 最小生成树、背包问题
以下是这些算法题的详细解释和示例代码:
查找算法:
- 二分查找: 二分查找是一种快速查找算法,适用于有序数组。它通过每次将搜索范围减半,快速缩小查找范围,直到找到目标元素或确定目标元素不存在。
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
- 哈希表查找: 哈希表查找是一种快速查找算法,适用于任何类型的数据。它使用哈希函数将键映射到值,以便于快速查找。
function hashTableLookup(hashTable, key) {
const hash = hashFunction(key);
const bucket = hashTable[hash];
for (const entry of bucket) {
if (entry.key === key) {
return entry.value;
}
}
return null;
}
排序算法:
- 冒泡排序: 冒泡排序是一种简单易懂的排序算法。它通过反复比较相邻元素,将较大的元素向后移动,直到数组完全有序。
function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
- 快速排序: 快速排序是一种快速高效的排序算法。它通过选择一个枢轴元素,将数组分为两部分,然后递归地对两部分进行排序。
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
const pivot = arr[Math.floor(arr.length / 2)];
const left = [];
const right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else if (arr[i] > pivot) {
right.push(arr[i]);
}
}
return quickSort(left).concat(pivot, quickSort(right));
}
- 归并排序: 归并排序是一种稳定且高效的排序算法。它通过将数组分成两部分,然后递归地对两部分进行排序,最后合并两个有序部分得到最终有序数组。
function mergeSort(arr) {
if (arr.length <= 1) {
return arr;
}
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
const merged = [];
let leftIndex = 0;
let rightIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
if (left[leftIndex] < right[rightIndex]) {
merged.push(left[leftIndex]);
leftIndex++;
} else {
merged.push(right[rightIndex]);
rightIndex++;
}
}
while (leftIndex < left.length) {
merged.push(left[leftIndex]);
leftIndex++;
}
while (rightIndex < right.length) {
merged.push(right[rightIndex]);
rightIndex++;
}
return merged;
}
搜索算法:
- 深度优先搜索: 深度优先搜索是一种遍历图或树的算法。它通过沿着一条路径搜索到底,然后再回溯并搜索其他路径。
function depthFirstSearch(graph, start) {
const visited = {};
const stack = [start];
while (stack.length > 0) {
const current = stack.pop();
if (!visited[current]) {
visited[current] = true;
console.log(current);
for (const neighbor of graph[current]) {
stack.push(neighbor);
}
}
}
}
- 广度优先搜索: 广度优先搜索是一种遍历图或树的算法。它通过逐层遍历节点,然后再搜索下一层节点。
function breadthFirstSearch(graph, start) {
const visited = {};
const queue = [start];
while (queue.length > 0) {
const current = queue.shift();
if (!visited[current]) {
visited[current] = true;
console.log(current);
for (const neighbor of graph[current]) {
queue.push(neighbor);
}
}
}
}
动态规划:
- 最长公共子序列: 最长公共子序列是一种动态规划算法。它通过计算两个字符串的最长公共子序列的长度,来比较两个字符串的相似性。
function longestCommonSubsequence(str1, str2) {
const dp = new Array(str1.length + 1).fill(0).map(() => new Array(str2.length + 1).fill(0));
for (let i = 1; i <= str1.length; i++) {
for (let j = 1; j <= str2.length; j++) {
if (str1[i - 1] === str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[str1.length][str2.length];
}
- 最短路径: 最短路径是一种动态规划算法。它通过计算从一个节点到另一个节点的最短路径的长度,来找到两个节点之间的最短路径。
function shortestPath(graph, start, end) {
const distances = new Array(graph.length).fill(Infinity);
distances[start] = 0;
const queue = [start];
while (queue.length > 0) {
const current = queue.shift();
for (const neighbor of graph[current]) {
const distance = distances[current] + graph[current][neighbor];
if (distance < distances[neighbor]) {
distances[neighbor] = distance;
queue.push(neighbor);
}
}
}
return distances[end];
}
贪心算法:
- 最小生成树: 最小生成树是一种贪心算法。它通过选择权重最小的边,来构建一个连接所有节点的最小生成树。
function minimumSpanningTree(graph) {
const edges = [];
for (const node in graph) {
for (const neighbor in graph[node]) {
edges.push({
node1: node,
node2: neighbor,
weight: graph[node][neighbor]
});
}