返回
洞悉先机,破译算法奥秘:十道必刷前端算法题全解析(二)
前端
2023-09-29 06:48:23
前言
在前端开发领域,算法能力是衡量程序员综合素质的重要标准之一。算法题是面试中常见的考察内容,也是前端开发工程师在实际工作中经常会遇到的难题。掌握扎实的算法功底,不仅可以帮助您轻松应对面试挑战,更能提升您解决复杂问题的能力,在职业发展中取得更大的成就。
十道精选前端算法题
为了帮助您系统地掌握算法知识,我们精心挑选了十道精选算法题,涵盖各种经典算法思想和数据结构,包括数组、链表、栈、队列、树、图等。每道题都附有详细的解析和代码示例,让您轻松理解算法精髓,掌握解决问题的关键技巧。
算法题解析
1. 两数之和
给定一个整数数组和一个目标值,找出数组中两个数的索引,使得它们的和等于目标值。
const 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 null;
};
2. 无重复字符的最长子串
给定一个字符串,找出不包含重复字符的最长子串的长度。
const lengthOfLongestSubstring = (str) => {
let start = 0;
let end = 0;
let maxLength = 0;
const set = new Set();
while (end < str.length) {
if (!set.has(str[end])) {
set.add(str[end]);
maxLength = Math.max(maxLength, end - start + 1);
end++;
} else {
set.delete(str[start]);
start++;
}
}
return maxLength;
};
3. 最长公共子序列
给定两个字符串,找出它们的公共子序列中最长字符串的长度。
const longestCommonSubsequence = (str1, str2) => {
const dp = Array(str1.length + 1).fill(0).map(() => 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];
};
4. 最长回文子串
给定一个字符串,找出它的最长回文子串。
const longestPalindrome = (str) => {
let start = 0;
let end = 0;
let maxLength = 0;
for (let i = 0; i < str.length; i++) {
const oddLength = expandAroundCenter(str, i, i);
const evenLength = expandAroundCenter(str, i, i + 1);
const currentLength = Math.max(oddLength, evenLength);
if (currentLength > maxLength) {
start = i - Math.floor((currentLength - 1) / 2);
end = i + Math.floor(currentLength / 2);
maxLength = currentLength;
}
}
return str.substring(start, end + 1);
function expandAroundCenter(str, left, right) {
while (left >= 0 && right < str.length && str[left] === str[right]) {
left--;
right++;
}
return right - left - 1;
}
};
5. 容器盛最多水的面积
给定一个非负整数数组,代表一个容器的形状,找出该容器能盛最多水的面积。
const maxArea = (heights) => {
let maxArea = 0;
let left = 0;
let right = heights.length - 1;
while (left < right) {
const currentArea = Math.min(heights[left], heights[right]) * (right - left);
maxArea = Math.max(maxArea, currentArea);
if (heights[left] < heights[right]) {
left++;
} else {
right--;
}
}
return maxArea;
};
6. 三数之和
给定一个整数数组和一个目标值,找出数组中三个数的索引,使得它们的和等于目标值。
const threeSum = (nums, target) => {
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;
let right = nums.length - 1;
while (left < right) {
const sum = nums[i] + nums[left] + nums[right];
if (sum === target) {
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 < target) {
left++;
} else {
right--;
}
}
}
return result;
};
7. 旋转数组中的最小数字
给定一个有序数组,该数组可能包含重复的元素,并被旋转过多次,找到数组中的最小数字。
const findMin = (nums) => {
let left = 0;
let right = nums.length - 1;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (nums[mid] > nums[right]) {
left = mid + 1;
} else if (nums[mid] < nums[right]) {
right = mid;
} else {
right--;
}
}
return nums[left];
};
8. 搜索旋转排序数组
给定一个有序数组,该数组可能包含重复的元素,并被旋转过多次,找到数组中目标值的索引,如果目标值不存在,则返回 -1。
const search = (nums, target) => {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (nums[mid] === target) {
return mid;
}
if (nums[left] <= nums[mid]) {
if (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
if (target > nums[mid] && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
};
9. 合并两个有序数组
给定两个有序数组,将它们合并为一个新的有序数组。
const merge = (