引言

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}