引言
JavaScript 作为一种广泛使用的编程语言,其强大的功能和灵活性使其成为解决算法问题的理想选择。无论是面试准备、自我提升还是参与编程竞赛,掌握一定的算法知识和技巧都是必不可少的。本文将带你一起分析10个经典的算法题目,涵盖数组、字符串、递归、数据结构等多个方面,旨在提升你的算法思维和 JavaScript 编程能力。
1. 两数之和
题目描述:给定一个整数数组 nums
和一个目标值 target
,找出数组中和为目标值的两个数。你可以假设每个输入正好只有一个解决方案,而且同样的元素不能被重复利用。
示例:
Javascript
深色版本
1const nums = [2, 7, 11, 15];
2const target = 9;
3// 返回 [0, 1]
解答:
Javascript
深色版本
1function twoSum(nums, target) {
2 const map = new Map();
3 for (let i = 0; i < nums.length; i++) {
4 const complement = target - nums[i];
5 if (map.has(complement)) {
6 return [map.get(complement), i];
7 }
8 map.set(nums[i], i);
9 }
10 throw new Error("No two sum solution");
11}
2. 翻转字符串里的单词
题目描述:给定一个字符串,返回一个翻转顺序后每个单词的字符串,单词之间由一个空格分隔。
示例:
Javascript
深色版本
1const s = "the sky is blue";
2// 返回 "blue is sky the"
解答:
Javascript
深色版本
1function reverseWords(s) {
2 return s.split(" ").reverse().join(" ");
3}
3. 移除链表元素
题目描述:给定一个排序链表,删除所有重复的元素,使之每个元素只出现一次。
示例:
Javascript
深色版本
1const head = new ListNode(1, new ListNode(1, new ListNode(2)));
2// 返回 1 -> 2
解答:
Javascript
深色版本
1class ListNode {
2 constructor(val, next = null) {
3 this.val = val;
4 this.next = next;
5 }
6}
7
8function deleteDuplicates(head) {
9 let current = head;
10 while (current && current.next) {
11 if (current.val === current.next.val) {
12 current.next = current.next.next;
13 } else {
14 current = current.next;
15 }
16 }
17 return head;
18}
4. 字母异位词分组
题目描述:给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
Javascript
深色版本
1const strs = ["eat", "tea", "tan", "ate", "nat", "bat"];
2// 返回 [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]
解答:
Javascript
深色版本
1function groupAnagrams(strs) {
2 const map = {};
3 for (const str of strs) {
4 const key = str.split("").sort().join("");
5 if (!map[key]) map[key] = [];
6 map[key].push(str);
7 }
8 return Object.values(map);
9}
5. 有效的括号
题目描述:给定一个只包含三种字符的字符串:'(', ')' 和 '*',写一个函数来检验这个字符串是否为有效字符串。
示例:
Javascript
深色版本
1const s = "()";
2// 返回 true
解答:
Javascript
深色版本
1function checkValidString(s) {
2 let leftCount = 0;
3 let starCount = 0;
4 for (let char of s) {
5 if (char === '(') {
6 leftCount++;
7 } else if (char === ')') {
8 if (leftCount > 0) {
9 leftCount--;
10 } else if (starCount > 0) {
11 starCount--;
12 } else {
13 return false;
14 }
15 } else {
16 starCount++;
17 }
18 }
19 return leftCount <= starCount;
20}
6. 最长公共前缀
题目描述:编写一个函数来查找字符串数组中的最长公共前缀。
示例:
Javascript
深色版本
1const strs = ["flower","flow","flight"];
2// 返回 "fl"
解答:
Javascript
深色版本
1function longestCommonPrefix(strs) {
2 if (strs.length === 0) return "";
3 let prefix = strs[0];
4 for (let i = 1; i < strs.length; i++) {
5 while (strs[i].indexOf(prefix) !== 0) {
6 prefix = prefix.substring(0, prefix.length - 1);
7 if (prefix.length === 0) return "";
8 }
9 }
10 return prefix;
11}
7. 最长回文子串
题目描述:给定一个字符串 s
,找到 s
中最长的回文子串。
示例:
Javascript
深色版本
1const s = "babad";
2// 返回 "bab" 或 "aba"
解答:
Javascript
深色版本
1function longestPalindrome(s) {
2 function expandAroundCenter(left, right) {
3 while (left >= 0 && right < s.length && s[left] === s[right]) {
4 left--;
5 right++;
6 }
7 return right - left - 1;
8 }
9
10 if (s.length < 2 || s === s.split('').reverse().join('')) {
11 return s;
12 }
13
14 let start = 0, end = 0;
15 for (let i = 0; i < s.length; i++) {
16 const len1 = expandAroundCenter(i, i);
17 const len2 = expandAroundCenter(i, i + 1);
18 const maxLen = Math.max(len1, len2);
19 if (maxLen > end - start) {
20 start = i - Math.floor((maxLen - 1) / 2);
21 end = i + Math.floor(maxLen / 2);
22 }
23 }
24 return s.substring(start, end + 1);
25}
8. 旋转数组
题目描述:将一个数组中的元素向右旋转 k
个位置。
示例:
Javascript
深色版本
1const nums = [-1, -100, 3, 99];
2const k = 2;
3// 返回 [3, 99, -1, -100]
解答:
Javascript
深色版本
1function rotate(nums, k) {
2 k %= nums.length;
3 reverse(nums, 0, nums.length - 1);
4 reverse(nums, 0, k - 1);
5 reverse(nums, k, nums.length - 1);
6}
7
8function reverse(nums, start, end) {
9 while (start < end) {
10 const temp = nums[start];
11 nums[start] = nums[end];
12 nums[end] = temp;
13 start++;
14 end--;
15 }
16}
9. 二叉树的层次遍历
题目描述:给定一个二叉树,返回其节点值的层次遍历。
示例:
Javascript
深色版本
1const tree = new TreeNode(3, new TreeNode(9), new TreeNode(20, new TreeNode(15), new TreeNode(7)));
2// 返回 [[3],[9,20],[15,7]]
解答:
Javascript
深色版本
1class TreeNode {
2 constructor(val, left = null, right = null) {
3 this.val = val;
4 this.left = left;
5 this.right = right;
6 }
7}
8
9function levelOrder(root) {
10 const result = [];
11 if (!root) return result;
12
13 const queue = [root];
14 while (queue.length) {
15 const levelSize = queue.length;
16 const currentLevel = [];
17 for (let i = 0; i < levelSize; i++) {
18 const currentNode = queue.shift();
19 currentLevel.push(currentNode.val);
20 if (currentNode.left) queue.push(currentNode.left);
21 if (currentNode.right) queue.push(currentNode.right);
22 }
23 result.push(currentLevel);
24 }
25 return result;
26}
10. 两数相加
题目描述:给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
示例:
Javascript
深色版本
1const l1 = new ListNode(2, new ListNode(4, new ListNode(3)));
2const l2 = new ListNode(5, new ListNode(6, new ListNode(4)));
3// 返回 7 -> 0 -> 8
解答:
Javascript
深色版本
1function addTwoNumbers(l1, l2) {
2 let dummyHead = new ListNode(0);
3 let current = dummyHead;
4 let carry = 0;
5 while (l1 || l2) {
6 let x = l1 ? l1.val : 0;
7 let y = l2 ? l2.val : 0;
8 let sum = carry + x + y;
9 carry = Math.floor(sum / 10);
10 current.next = new ListNode(sum % 10);
11 current = current.next;
12 if (l1) l1 = l1.next;
13 if (l2) l2 = l2.next;
14 }
15 if (carry > 0) {
16 current.next = new ListNode(carry);
17 }
18 return dummyHead.next;
19}