当前位置: 首页 > news >正文

LeetCode Hot100题解

目录

一、数组 & 字符串

1. 两数之和(简单)

2. 删除有序数组中的重复项(简单)

3. 移除元素(简单)

4. 合并两个有序数组(简单)

5. 买卖股票的最佳时机(简单)

6. 多数元素(简单)

7. 移动零(简单)

8. 三数之和(中等)

9. 无重复字符的最长子串(中等)

10. 最长回文子串(中等)

二、链表

1. 合并两个有序链表(简单)

2. 环形链表(简单)

3. 相交链表(简单)

4. 反转链表(简单)

5. 两数相加(中等)

6. 删除链表的倒数第N个结点(中等)

7. 环形链表 II(中等)

总结

三、二叉树

1. 对称二叉树(简单)

2. 二叉树的最大深度(简单)

3. 二叉树的中序遍历(中等)

4. 二叉树的层序遍历(中等)

5. 从前序与中序遍历序列构造二叉树(中等)

6. 二叉树展开为链表(中等)

总结

四、栈和队列

1. 有效的括号(简单)

2. 最小栈(中等)

3. 字符串解码(中等)

五、双指针与滑动窗口

1. 验证回文串(简单)

2. 盛最多水的容器(中等)

3. 替换后的最长重复字符(中等)

4. 字符串的排列(中等)

总结

六、动态规划

1. 爬楼梯(简单)

2. 杨辉三角(简单)

3. 最大子数组和(中等)

4. 不同路径(中等)

5. 最小路径和(中等)

6. 最长递增子序列(中等)

总结

七、回溯 & DFS

1. 括号生成(中等)

2. 全排列(中等)

3. 子集(中等)

4. 单词搜索(中等)

八、设计题

1. LRU缓存(中等)

九、排序 & 贪心

1. 合并区间(中等)

2. 颜色分类(中等)

十、位运算

1. 只出现一次的数字(简单)

总结

JavaScript实现代码

一、数组 & 字符串

1. 两数之和(Two Sum)

2. 删除有序数组中的重复项(Remove Duplicates from Sorted Array)

3. 移除元素(Remove Element)

4. 合并两个有序数组(Merge Sorted Array)

5. 买卖股票的最佳时机(Best Time to Buy and Sell Stock)

6. 多数元素(Majority Element)

7. 移动零(Move Zeroes)

8. 三数之和(3Sum)

9. 无重复字符的最长子串(Longest Substring Without Repeating Characters)

10. 最长回文子串(Longest Palindromic Substring)

二、链表

1. 合并两个有序链表(Merge Two Sorted Lists)

2. 环形链表(Linked List Cycle)

3. 相交链表(Intersection of Two Linked Lists)

4. 反转链表(Reverse Linked List)

5. 两数相加(Add Two Numbers)

6. 删除链表的倒数第N个结点(Remove Nth Node From End of List)

7. 环形链表 II(Linked List Cycle II)

三、二叉树

1. 对称二叉树(Symmetric Tree)

2. 二叉树的最大深度(Maximum Depth of Binary Tree)

3. 二叉树的中序遍历(Binary Tree Inorder Traversal)

4. 二叉树的层序遍历(Binary Tree Level Order Traversal)

5. 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal)

6. 二叉树展开为链表(Flatten Binary Tree to Linked List)

四、栈 & 队列

1. 有效的括号(Valid Parentheses)

2. 最小栈(Min Stack)

3. 字符串解码(Decode String)

五、双指针 & 滑动窗口

1. 验证回文串(Valid Palindrome)

2. 盛最多水的容器(Container With Most Water)

3. 替换后的最长重复字符(Longest Repeating Character Replacement)

4. 字符串的排列(Permutation in String)

六、动态规划

1. 爬楼梯(Climbing Stairs)

2. 杨辉三角(Pascal's Triangle)

3. 最大子数组和(Maximum Subarray)

4. 不同路径(Unique Paths)

5. 最小路径和(Minimum Path Sum)

6. 最长递增子序列(Longest Increasing Subsequence)

七、回溯 & DFS

1. 括号生成(Generate Parentheses)

2. 全排列(Permutations)

3. 子集(Subsets)

4. 单词搜索(Word Search)

八、设计题

1. LRU 缓存(LRU Cache)

九、排序 & 贪心

1. 合并区间(Merge Intervals)

2. 颜色分类(Sort Colors)

十、位运算

1. 只出现一次的数字(Single Number)


本文记录LeetCode Hot100中简单和中等难度的题目,按类型分类整理,包含C++代码实现,后面有js实现的代码。


一、数组 & 字符串

1. 两数之和(简单)

题目描述
给定一个整数数组 nums 和一个整数目标值 target,在数组中找出和为目标值 target 的两个整数,返回它们的数组下标。
示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解题思路
使用哈希表存储已遍历的值及其下标,遍历时检查 target - nums[i] 是否在哈希表中。
C++代码

#include <vector>
#include <unordered_map>
using namespace std;vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> map;for (int i = 0; i < nums.size(); i++) {int complement = target - nums[i];if (map.count(complement)) {return {map[complement], i};}map[nums[i]] = i;}return {};
}

2. 删除有序数组中的重复项(简单)

题目描述
给定一个升序排列的数组 nums,原地删除重复元素,使每个元素只出现一次,返回新数组的长度。
示例
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5(修改后的数组为 [0,1,2,3,4]
解题思路
双指针法:慢指针标记唯一元素位置,快指针遍历数组。
C++代码

int removeDuplicates(vector<int>& nums) {if (nums.empty()) return 0;int slow = 0;for (int fast = 1; fast < nums.size(); fast++) {if (nums[fast] != nums[slow]) {slow++;nums[slow] = nums[fast];}}return slow + 1;
}

3. 移除元素(简单)

题目描述
给定一个数组 nums 和一个值 val,原地移除所有数值等于 val 的元素,返回新数组的长度。
示例
输入:nums = [3,2,2,3], val = 3
输出:2(修改后的数组为 [2,2]
解题思路
双指针法:慢指针标记非目标元素的位置,快指针遍历数组。
C++代码

int removeElement(vector<int>& nums, int val) {int slow = 0;for (int fast = 0; fast < nums.size(); fast++) {if (nums[fast] != val) {nums[slow++] = nums[fast];}}return slow;
}

4. 合并两个有序数组(简单)

题目描述
给定两个非递减顺序排列的整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使合并后的数组同样按非递减顺序排列。
示例
输入:nums1 = [1,2,3,0,0,0], m = 3nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解题思路
从后向前合并,避免覆盖 nums1 中的元素。
C++代码

void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {int p1 = m - 1, p2 = n - 1, p = m + n - 1;while (p2 >= 0) {if (p1 >= 0 && nums1[p1] > nums2[p2]) {nums1[p--] = nums1[p1--];} else {nums1[p--] = nums2[p2--];}}
}

5. 买卖股票的最佳时机(简单)

题目描述
给定数组 prices,其中 prices[i] 表示股票第 i 天的价格,返回你能获取的最大利润(只能买卖一次)。
示例
输入:prices = [7,1,5,3,6,4]
输出:5(第2天买入,第5天卖出)
解题思路
遍历数组,记录历史最低价,并计算当前最大利润。
C++代码

int maxProfit(vector<int>& prices) {int minPrice = INT_MAX, maxProfit = 0;for (int price : prices) {minPrice = min(minPrice, price);maxProfit = max(maxProfit, price - minPrice);}return maxProfit;
}

6. 多数元素(简单)

题目描述
找出数组中出现次数超过 ⌊n/2⌋ 次的元素。
示例
输入:nums = [3,2,3]
输出:3
解题思路
Boyer-Moore投票算法:遇到相同元素计数+1,否则-1,计数为0时更换候选元素。
C++代码

int majorityElement(vector<int>& nums) {int candidate = nums[0], count = 0;for (int num : nums) {if (count == 0) candidate = num;count += (num == candidate) ? 1 : -1;}return candidate;
}

7. 移动零(简单)

题目描述
将数组中的所有零移动到末尾,同时保持非零元素的相对顺序。
示例
输入:nums = [0,1,0,3,12]
输出:[1,3,12,0,0]
解题思路
双指针法:将非零元素依次移到前面,最后填充零。
C++代码

void moveZeroes(vector<int>& nums) {int slow = 0;for (int fast = 0; fast < nums.size(); fast++) {if (nums[fast] != 0) {nums[slow++] = nums[fast];}}while (slow < nums.size()) {nums[slow++] = 0;}
}

8. 三数之和(中等)

题目描述
在数组 nums 中找到所有不重复的三元组 [nums[i], nums[j], nums[k]],使得 i != j != k 且 nums[i] + nums[j] + nums[k] = 0
示例
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2], [-1,0,1]]
解题思路
排序后固定一个数,用双指针在剩余区间寻找两数之和为负数。注意去重。
C++代码

vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(), nums.end());vector<vector<int>> res;for (int i = 0; i < nums.size(); i++) {if (i > 0 && nums[i] == nums[i-1]) continue; // 去重int left = i + 1, right = nums.size() - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum < 0) left++;else if (sum > 0) right--;else {res.push_back({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--;}}}return res;
}

9. 无重复字符的最长子串(中等)

题目描述
给定一个字符串 s,找出其中不含有重复字符的 最长子串 的长度。
示例
输入:s = "abcabcbb"
输出:3(最长子串是 "abc"
解题思路
滑动窗口:用哈希表记录字符的最新位置,右指针扩展窗口,左指针跳过重复位置。
C++代码

int lengthOfLongestSubstring(string s) {unordered_map<char, int> map;int maxLen = 0, left = 0;for (int right = 0; right < s.size(); right++) {char c = s[right];if (map.count(c) && map[c] >= left) {left = map[c] + 1; // 移动左指针跳过重复}map[c] = right;maxLen = max(maxLen, right - left + 1);}return maxLen;
}

10. 最长回文子串(中等)

题目描述
给定字符串 s,找到 s 中最长的回文子串。
示例
输入:s = "babad"
输出:"bab" 或 "aba"
解题思路
中心扩展法:遍历每个字符,尝试以该字符为中心向两边扩展,处理奇偶长度两种情况。
C++代码

string longestPalindrome(string s) {int start = 0, maxLen = 0;for (int i = 0; i < s.size(); i++) {int len1 = expand(s, i, i);     // 奇长度int len2 = expand(s, i, i+1);   // 偶长度int len = max(len1, len2);if (len > maxLen) {maxLen = len;start = i - (len - 1) / 2;}}return s.substr(start, maxLen);
}int expand(string s, int left, int right) {while (left >= 0 && right < s.size() && s[left] == s[right]) {left--;right++;}return right - left - 1;
}

二、链表

1. 合并两个有序链表(简单)

题目描述
将两个升序链表合并为一个新的 升序 链表并返回。
示例
输入:l1 = [1,2,4]l2 = [1,3,4]
输出:[1,1,2,3,4,4]
解题思路
使用虚拟头节点简化边界处理,依次比较两个链表的节点值,按升序连接。
C++代码

struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {}
};ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {ListNode dummy(0);      // 虚拟头节点ListNode *tail = &dummy;while (l1 && l2) {if (l1->val < l2->val) {tail->next = l1;l1 = l1->next;} else {tail->next = l2;l2 = l2->next;}tail = tail->next;}tail->next = l1 ? l1 : l2; // 连接剩余部分return dummy.next;
}

2. 环形链表(简单)

题目描述
判断链表中是否有环。
示例
输入:head = [3,2,0,-4](尾部节点指向索引1的节点)
输出:true
解题思路
快慢指针法:快指针每次走两步,慢指针走一步,若相遇则有环。
C++代码

bool hasCycle(ListNode *head) {if (!head) return false;ListNode *slow = head, *fast = head;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;if (slow == fast) return true;}return false;
}

3. 相交链表(简单)

题目描述
找到两个单链表相交的起始节点,若不相交返回 nullptr
示例
输入:listA = [4,1,8,4,5]listB = [5,6,1,8,4,5](相交节点为8)
输出:相交节点值为8的节点
解题思路
双指针法:指针A遍历完链表A后转向链表B,指针B同理。两指针会在相交点相遇。
C++代码

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode *pA = headA, *pB = headB;while (pA != pB) {pA = pA ? pA->next : headB;pB = pB ? pB->next : headA;}return pA; // 若无相交,最终pA和pB均为nullptr
}

4. 反转链表(简单)

题目描述
反转单链表并返回新的头节点。
示例
输入:1->2->3->4->5
输出:5->4->3->2->1
解题思路
迭代法:维护前驱节点 prev、当前节点 curr,逐个反转指针方向。
C++代码

ListNode* reverseList(ListNode* head) {ListNode *prev = nullptr, *curr = head;while (curr) {ListNode *next = curr->next;curr->next = prev;prev = curr;curr = next;}return prev;
}

5. 两数相加(中等)

题目描述
给定两个非空链表,表示两个非负整数(每位数字逆序存储),返回两数之和的链表。
示例
输入:l1 = [2,4,3]l2 = [5,6,4]
输出:[7,0,8](即342 + 465 = 807)
解题思路
模拟加法过程,维护进位值 carry,逐位相加生成新链表。
C++代码

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode dummy(0);ListNode *tail = &dummy;int carry = 0;while (l1 || l2 || carry) {int sum = carry;if (l1) {sum += l1->val;l1 = l1->next;}if (l2) {sum += l2->val;l2 = l2->next;}carry = sum / 10;tail->next = new ListNode(sum % 10);tail = tail->next;}return dummy.next;
}

6. 删除链表的倒数第N个结点(中等)

题目描述
删除链表的倒数第 n 个结点,并返回头节点。
示例
输入:head = [1,2,3,4,5]n = 2
输出:[1,2,3,5]
解题思路
双指针法:快指针先走 n 步,然后快慢指针同步移动,快指针到末尾时慢指针指向待删除节点的前驱。
C++代码

ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode dummy(0);dummy.next = head;ListNode *fast = &dummy, *slow = &dummy;for (int i = 0; i < n; i++) fast = fast->next; // 快指针先走n步while (fast->next) {fast = fast->next;slow = slow->next;}ListNode *toDelete = slow->next;slow->next = slow->next->next;delete toDelete; // 释放内存(实际LeetCode可能不需要)return dummy.next;
}

7. 环形链表 II(中等)

题目描述
返回链表开始入环的第一个节点,若链表无环则返回 nullptr
示例
输入:head = [3,2,0,-4](尾部节点指向索引1的节点)
输出:值为2的节点
解题思路

  1. 快慢指针判断是否有环,并找到相遇点。

  2. 将快指针重置到链表头,快慢指针同步移动,再次相遇点即为环入口。

C++代码

ListNode *detectCycle(ListNode *head) {ListNode *slow = head, *fast = head;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;if (slow == fast) { // 找到相遇点fast = head;    // 重置快指针到头部while (slow != fast) {slow = slow->next;fast = fast->next;}return slow;}}return nullptr;
}

总结

  1. 双指针技巧:链表的多数问题可以通过双指针(快慢指针、前后指针)高效解决。

  2. 虚拟头节点:简化边界条件处理(如删除头节点或空链表)。

  3. 环形链表问题:快慢指针相遇后,数学推导可定位环入口。

  4. 注意内存管理:实际面试中可能需要手动释放删除的节点(如删除倒数第N个节点)。


三、二叉树

1. 对称二叉树(简单)

题目描述
给定二叉树的根节点 root,检查它是否轴对称(镜像对称)。
示例
输入:root = [1,2,2,3,4,4,3]
输出:true
解题思路
递归比较左右子树是否对称:左子树的左节点与右子树的右节点、左子树的右节点与右子树的左节点均相等。
C++代码

struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};bool isSymmetric(TreeNode* root) {if (!root) return true;return compare(root->left, root->right);
}bool compare(TreeNode* left, TreeNode* right) {if (!left && !right) return true;if (!left || !right) return false;return (left->val == right->val) && compare(left->left, right->right) && compare(left->right, right->left);
}

2. 二叉树的最大深度(简单)

题目描述
给定二叉树的根节点 root,返回其最大深度(从根节点到最远叶子节点的最长路径的节点数)。
示例
输入:root = [3,9,20,null,null,15,7]
输出:3
解题思路
递归计算左右子树的最大深度,取较大者加1。
C++代码

int maxDepth(TreeNode* root) {if (!root) return 0;return 1 + max(maxDepth(root->left), maxDepth(root->right));
}

3. 二叉树的中序遍历(中等)

题目描述
给定二叉树的根节点 root,返回它的 中序 遍历结果。
示例
输入:root = [1,null,2,3]
输出:[1,3,2]
解题思路
迭代法:使用栈模拟递归,左链入栈到底,出栈访问节点后转向右子树。
C++代码

vector<int> inorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;TreeNode* curr = root;while (curr || !st.empty()) {while (curr) {      // 左链入栈到底st.push(curr);curr = curr->left;}curr = st.top();st.pop();res.push_back(curr->val);curr = curr->right; // 转向右子树}return res;
}

4. 二叉树的层序遍历(中等)

题目描述
给定二叉树的根节点 root,返回其节点值的层序遍历结果(逐层从左到右访问)。
示例
输入:root = [3,9,20,null,null,15,7]
输出:[[3], [9,20], [15,7]]
解题思路
BFS:使用队列逐层遍历,记录每层节点数。
C++代码

vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> res;if (!root) return res;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int levelSize = q.size();vector<int> level;for (int i = 0; i < levelSize; i++) {TreeNode* node = q.front();q.pop();level.push_back(node->val);if (node->left) q.push(node->left);if (node->right) q.push(node->right);}res.push_back(level);}return res;
}

5. 从前序与中序遍历序列构造二叉树(中等)

题目描述
给定两个整数数组 preorder 和 inorder,构造并返回二叉树。
示例
输入:preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出:[3,9,20,null,null,15,7]
解题思路

  1. 前序数组首元素为根节点。

  2. 在中序数组中找到根节点位置,分割左右子树。

  3. 递归构建左右子树。

C++代码

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {unordered_map<int, int> map;for (int i = 0; i < inorder.size(); i++) {map[inorder[i]] = i; // 记录中序元素索引}return build(preorder, 0, preorder.size()-1, 0, map);
}TreeNode* build(vector<int>& preorder, int preStart, int preEnd, int inStart, unordered_map<int, int>& map) {if (preStart > preEnd) return nullptr;int rootVal = preorder[preStart];TreeNode* root = new TreeNode(rootVal);int rootIdx = map[rootVal]; // 中序根节点位置int leftSize = rootIdx - inStart;root->left = build(preorder, preStart+1, preStart+leftSize, inStart, map);root->right = build(preorder, preStart+leftSize+1, preEnd, rootIdx+1, map);return root;
}

6. 二叉树展开为链表(中等)

题目描述
将二叉树按前序遍历顺序展开为一个单链表(右子树连接,左子树置空)。
示例
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]
解题思路
递归法

  1. 递归展开左右子树。

  2. 将左子树插入到右子树的位置,并将原右子树接到左子树的最右节点。

C++代码

void flatten(TreeNode* root) {if (!root) return;flatten(root->left);flatten(root->right);TreeNode* left = root->left;TreeNode* right = root->right;root->left = nullptr;root->right = left;// 找到左子树的最右节点,连接原右子树TreeNode* curr = root;while (curr->right) {curr = curr->right;}curr->right = right;
}

总结

  1. 递归与分治:二叉树问题大多可通过递归分解为子树问题(如构造二叉树)。

  2. 遍历模板:层序遍历使用队列(BFS),中序迭代使用栈。

  3. 空间优化:展开链表时无需额外空间,直接修改指针。

  4. 边界处理:注意空节点和单子树的情况(如对称二叉树判断)。


四、栈和队列

1. 有效的括号(简单)

题目描述
给定一个只包含 '('')''{''}''['']' 的字符串 s,判断字符串是否有效(括号正确闭合)。
示例
输入:s = "()[]{}"
输出:true
解题思路
使用栈结构,遇到左括号入栈,遇到右括号检查栈顶是否匹配。
C++代码

#include <stack>
using namespace std;bool isValid(string s) {stack<char> st;for (char c : s) {if (c == '(' || c == '{' || c == '[') {st.push(c);} else {if (st.empty()) return false;char top = st.top();if ((c == ')' && top != '(') || (c == '}' && top != '{') || (c == ']' && top != '[')) {return false;}st.pop();}}return st.empty();
}

2. 最小栈(中等)

题目描述
设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。
示例
输入:
push(-2) → push(0) → push(-3) → getMin() → 返回 -3
pop() → top() → 返回 0 → getMin() → 返回 -2
解题思路
使用辅助栈同步记录当前最小值,或每个节点保存当前值和当前最小值。
C++代码

class MinStack {
private:struct Node {int val;int minVal;Node* next;Node(int v, int m, Node* n) : val(v), minVal(m), next(n) {}};Node* head;
public:MinStack() : head(nullptr) {}void push(int val) {if (!head) {head = new Node(val, val, nullptr);} else {head = new Node(val, min(val, head->minVal), head);}}void pop() {Node* temp = head;head = head->next;delete temp;}int top() {return head->val;}int getMin() {return head->minVal;}
};

3. 字符串解码(中等)

题目描述
给定一个编码字符串(例如 3[a2[c]]),解码为原始字符串(accaccacc)。
示例
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
解题思路
使用栈处理嵌套结构,分别记录数字和字符串的临时结果。
C++代码

string decodeString(string s) {stack<pair<int, string>> st;int num = 0;string res = "";for (char c : s) {if (isdigit(c)) {num = num * 10 + (c - '0');} else if (c == '[') {st.push({num, res});num = 0;res = "";} else if (c == ']') {auto [repeat, prev] = st.top();st.pop();string temp = res;for (int i = 1; i < repeat; i++) {res += temp;}res = prev + res;} else {res += c;}}return res;
}

五、双指针与滑动窗口

1. 验证回文串(简单)

题目描述
给定一个字符串,验证它是否是回文串(只考虑字母和数字,忽略大小写)。
示例
输入:"A man, a plan, a canal: Panama"
输出:true
解题思路
双指针从两端向中间移动,跳过非字母数字字符并比较。
C++代码

bool isPalindrome(string s) {int left = 0, right = s.size() - 1;while (left < right) {while (left < right && !isalnum(s[left])) left++;while (left < right && !isalnum(s[right])) right--;if (tolower(s[left]) != tolower(s[right])) return false;left++;right--;}return true;
}

2. 盛最多水的容器(中等)

题目描述
给定 n 个非负整数表示容器高度,选择两个边使得容器容纳的水最多。
示例
输入:height = [1,8,6,2,5,4,8,3,7]
输出:49(由第2和第9条边形成)
解题思路
双指针从两端向中间移动,每次移动较矮的一边以寻求更高高度。
C++代码

int maxArea(vector<int>& height) {int left = 0, right = height.size() - 1;int maxArea = 0;while (left < right) {int h = min(height[left], height[right]);maxArea = max(maxArea, h * (right - left));if (height[left] < height[right]) {left++;} else {right--;}}return maxArea;
}

3. 替换后的最长重复字符(中等)

题目描述
给定字符串 s 和整数 k,允许替换任意字符 k 次,找到替换后最长重复字符的子串长度。
示例
输入:s = "AABABBA", k = 1
输出:4(将中间B替换为A后得到AAAABBA
解题思路
滑动窗口维护窗口内最大重复字符数,窗口大小受 窗口长度 - 最大重复数 ≤ k 限制。
C++代码

int characterReplacement(string s, int k) {vector<int> count(26, 0);int maxCount = 0, maxLen = 0, left = 0;for (int right = 0; right < s.size(); right++) {maxCount = max(maxCount, ++count[s[right] - 'A']);while (right - left + 1 - maxCount > k) { // 窗口不合法时收缩左边界count[s[left] - 'A']--;left++;}maxLen = max(maxLen, right - left + 1);}return maxLen;
}

4. 字符串的排列(中等)

题目描述
判断字符串 s2 是否包含 s1 的排列作为子串。
示例
输入:s1 = "ab", s2 = "eidbaooo"
输出:trues2包含"ba"
解题思路
滑动窗口统计字符频率,窗口长度固定为 s1 的长度。
C++代码

bool checkInclusion(string s1, string s2) {vector<int> target(26, 0), window(26, 0);for (char c : s1) target[c - 'a']++;int n = s1.size(), m = s2.size();if (n > m) return false;for (int i = 0; i < n; i++) {window[s2[i] - 'a']++;}if (window == target) return true;for (int i = n; i < m; i++) {window[s2[i - n] - 'a']--; // 移除左边界字符window[s2[i] - 'a']++;      // 添加右边界字符if (window == target) return true;}return false;
}

总结

  1. 栈的核心应用:括号匹配、嵌套结构解析(如字符串解码)。

  2. 双指针方向:相向移动(盛水容器)、同向移动(滑动窗口)。

  3. 滑动窗口关键:维护窗口合法性条件(如替换次数限制、固定窗口长度)。

  4. 空间优化:频率统计替代暴力匹配(如字符串排列问题)。


六、动态规划

1. 爬楼梯(简单)

题目描述
假设你正在爬楼梯,需要 n 阶才能到达楼顶。每次可以爬 1 或 2 个台阶。求有多少种不同的方法可以爬到楼顶。
示例
输入:n = 3
输出:3(方法:1+1+1, 1+2, 2+1)
解题思路
动态规划:状态转移方程 dp[i] = dp[i-1] + dp[i-2],优化空间复杂度为 O(1)
C++代码

int climbStairs(int n) {if (n <= 2) return n;int a = 1, b = 2, c;for (int i = 3; i <= n; i++) {c = a + b;a = b;b = c;}return b;
}

2. 杨辉三角(简单)

题目描述
给定非负整数 numRows,生成前 numRows 行的杨辉三角。
示例
输入:numRows = 5
输出:
[[1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1]]
解题思路
动态规划:每一行的第 j 个元素等于上一行的 j-1 和 j 元素之和。
C++代码

vector<vector<int>> generate(int numRows) {vector<vector<int>> res;for (int i = 0; i < numRows; i++) {vector<int> row(i + 1, 1);for (int j = 1; j < i; j++) {row[j] = res[i-1][j-1] + res[i-1][j];}res.push_back(row);}return res;
}

3. 最大子数组和(中等)

题目描述
给定整数数组 nums,找到具有最大和的连续子数组,返回其最大和。
示例
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6(子数组 [4,-1,2,1]
解题思路
Kadane算法:维护当前子数组和 curSum 和全局最大和 maxSum
C++代码

int maxSubArray(vector<int>& nums) {int maxSum = nums[0], curSum = nums[0];for (int i = 1; i < nums.size(); i++) {curSum = max(nums[i], curSum + nums[i]);maxSum = max(maxSum, curSum);}return maxSum;
}

4. 不同路径(中等)

题目描述
机器人从 m x n 网格的左上角移动到右下角,每次只能向右或向下移动,求总共有多少条不同的路径。
示例
输入:m = 3, n = 7
输出:28
解题思路
动态规划:状态转移方程 dp[i][j] = dp[i-1][j] + dp[i][j-1],空间优化为滚动数组。
C++代码

int uniquePaths(int m, int n) {vector<int> dp(n, 1);for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[j] += dp[j-1];}}return dp[n-1];
}

5. 最小路径和(中等)

题目描述
给定 m x n 网格,每个格子填非负数,找出一条从左上到右下的路径,使得路径上的数字总和最小。
示例
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7(路径:1→3→1→1→1)
解题思路
动态规划:初始化第一行和第一列,状态转移方程为 dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
C++代码

int minPathSum(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();for (int i = 1; i < m; i++) grid[i][0] += grid[i-1][0];for (int j = 1; j < n; j++) grid[0][j] += grid[0][j-1];for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {grid[i][j] += min(grid[i-1][j], grid[i][j-1]);}}return grid[m-1][n-1];
}

6. 最长递增子序列(中等)

题目描述
给定整数数组 nums,返回最长严格递增子序列的长度。
示例
输入:nums = [10,9,2,5,3,7,101,18]
输出:4(子序列 [2,5,7,101]
解题思路
动态规划:dp[i] 表示以 nums[i] 结尾的最长递增子序列长度,时间复杂度 O(n^2)
C++代码

int lengthOfLIS(vector<int>& nums) {int n = nums.size(), maxLen = 1;vector<int> dp(n, 1);for (int i = 1; i < n; i++) {for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {dp[i] = max(dp[i], dp[j] + 1);}}maxLen = max(maxLen, dp[i]);}return maxLen;
}

总结

  1. 状态定义:明确 dp[i] 或 dp[i][j] 的含义(如以 nums[i] 结尾的最长递增子序列长度)。

  2. 状态转移:找到子问题之间的关系(如爬楼梯的 dp[i] = dp[i-1] + dp[i-2])。

  3. 空间优化:用滚动数组降低维度(如不同路径问题)。

  4. 初始化与边界:处理第一行、第一列或空输入的情况(如最小路径和)。


七、回溯 & DFS

1. 括号生成(中等)

题目描述
给定整数 n,生成所有包含 n 对有效括号的组合。
示例
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
解题思路
回溯法:控制左括号和右括号的数量,左括号数不能超过 n,右括号数不能超过左括号数。
C++代码

vector<string> generateParenthesis(int n) {vector<string> res;backtrack(res, "", 0, 0, n);return res;
}void backtrack(vector<string>& res, string cur, int left, int right, int n) {if (cur.size() == 2 * n) {res.push_back(cur);return;}if (left < n) backtrack(res, cur + "(", left + 1, right, n);if (right < left) backtrack(res, cur + ")", left, right + 1, n);
}

2. 全排列(中等)

题目描述
给定不含重复数字的数组 nums,返回其所有可能的全排列。
示例
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
解题思路
回溯法:通过交换元素实现排列,递归结束后恢复原数组。
C++代码

vector<vector<int>> permute(vector<int>& nums) {vector<vector<int>> res;backtrack(nums, 0, res);return res;
}void backtrack(vector<int>& nums, int start, vector<vector<int>>& res) {if (start == nums.size()) {res.push_back(nums);return;}for (int i = start; i < nums.size(); i++) {swap(nums[start], nums[i]);backtrack(nums, start + 1, res);swap(nums[start], nums[i]); // 恢复数组}
}

3. 子集(中等)

题目描述
给定整数数组 nums(元素互不相同),返回所有可能的子集(幂集)。
示例
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
解题思路
迭代法:逐步将新元素添加到已有的子集中生成新子集。
C++代码

vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>> res = {{}};for (int num : nums) {int size = res.size();for (int i = 0; i < size; i++) {vector<int> subset = res[i];subset.push_back(num);res.push_back(subset);}}return res;
}

4. 单词搜索(中等)

题目描述
给定 m x n 二维字符网格 board 和字符串 word,判断 word 是否存在于网格中。
示例
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
解题思路
DFS 回溯:遍历每个起点,递归搜索四个方向,标记已访问的位置。
C++代码

bool exist(vector<vector<char>>& board, string word) {for (int i = 0; i < board.size(); i++) {for (int j = 0; j < board[0].size(); j++) {if (dfs(board, word, i, j, 0)) return true;}}return false;
}bool dfs(vector<vector<char>>& board, string& word, int i, int j, int idx) {if (idx == word.size()) return true;if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] != word[idx]) return false;char temp = board[i][j];board[i][j] = '#'; // 标记已访问bool found = dfs(board, word, i+1, j, idx+1) ||dfs(board, word, i-1, j, idx+1) ||dfs(board, word, i, j+1, idx+1) ||dfs(board, word, i, j-1, idx+1);board[i][j] = temp; // 恢复return found;
}

八、设计题

1. LRU缓存(中等)

题目描述
设计并实现一个 LRU(最近最少使用)缓存机制,支持 get 和 put 操作。
示例
输入:
capacity = 2
put(1,1); put(2,2); get(1); put(3,3);
输出:get(1)=1 → put(3) 后缓存为 {1=1,3=3}
解题思路
哈希表 + 双向链表:哈希表快速定位节点,双向链表维护访问顺序。
C++代码

class LRUCache {
private:struct Node {int key, val;Node *prev, *next;Node(int k, int v) : key(k), val(v), prev(nullptr), next(nullptr) {}};Node *head, *tail;unordered_map<int, Node*> map;int cap;void remove(Node* node) {node->prev->next = node->next;node->next->prev = node->prev;}void addToHead(Node* node) {node->next = head->next;node->prev = head;head->next->prev = node;head->next = node;}public:LRUCache(int capacity) : cap(capacity) {head = new Node(-1, -1);tail = new Node(-1, -1);head->next = tail;tail->prev = head;}int get(int key) {if (!map.count(key)) return -1;Node* node = map[key];remove(node);addToHead(node);return node->val;}void put(int key, int value) {if (map.count(key)) {Node* node = map[key];node->val = value;remove(node);addToHead(node);} else {if (map.size() == cap) {Node* last = tail->prev;remove(last);map.erase(last->key);delete last;}Node* newNode = new Node(key, value);map[key] = newNode;addToHead(newNode);}}
};

九、排序 & 贪心

1. 合并区间(中等)

题目描述
给定多个区间,合并所有重叠的区间。
示例
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解题思路
排序后贪心:按区间起点排序,遍历合并重叠区间。
C++代码

vector<vector<int>> merge(vector<vector<int>>& intervals) {if (intervals.empty()) return {};sort(intervals.begin(), intervals.end());vector<vector<int>> res = {intervals[0]};for (auto& interval : intervals) {if (interval[0] <= res.back()[1]) {res.back()[1] = max(res.back()[1], interval[1]);} else {res.push_back(interval);}}return res;
}

2. 颜色分类(中等)

题目描述
给定包含 0, 1, 2 的数组,原地排序使相同颜色相邻(荷兰国旗问题)。
示例
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
解题思路
三指针分区:left 标记 0 的右边界,right 标记 2 的左边界,curr 遍历数组。
C++代码

void sortColors(vector<int>& nums) {int left = 0, right = nums.size() - 1, curr = 0;while (curr <= right) {if (nums[curr] == 0) {swap(nums[curr++], nums[left++]);} else if (nums[curr] == 2) {swap(nums[curr], nums[right--]);} else {curr++;}}
}

十、位运算

1. 只出现一次的数字(简单)

题目描述
给定非空数组,其中某个元素只出现一次,其余均出现两次,找出该元素。
示例
输入:nums = [4,1,2,1,2]
输出:4
解题思路
异或运算:a ^ a = 0a ^ 0 = a,所有元素异或后结果为唯一数。
C++代码

int singleNumber(vector<int>& nums) {int res = 0;for (int num : nums) res ^= num;return res;
}

总结

  1. 回溯核心:通过递归探索所有可能路径,必要时剪枝(如括号生成中的合法性判断)。

  2. 设计题重点:数据结构的选择(如 LRU 缓存的双向链表 + 哈希表)。

  3. 排序预处理:合并区间问题需先排序以简化贪心逻辑。

  4. 位运算技巧:异或操作消除重复项,三指针原地分区(颜色分类)。


  

JavaScript实现代码


一、数组 & 字符串

1. 两数之和(Two Sum)
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. 删除有序数组中的重复项(Remove Duplicates from Sorted Array)
function removeDuplicates(nums) {if (nums.length === 0) return 0;let slow = 0;for (let fast = 1; fast < nums.length; fast++) {if (nums[fast] !== nums[slow]) {slow++;nums[slow] = nums[fast];}}return slow + 1;
}
3. 移除元素(Remove Element)
function removeElement(nums, val) {let slow = 0;for (let fast = 0; fast < nums.length; fast++) {if (nums[fast] !== val) {nums[slow++] = nums[fast];}}return slow;
}
4. 合并两个有序数组(Merge Sorted Array)
function merge(nums1, m, nums2, n) {let p1 = m - 1, p2 = n - 1, p = m + n - 1;while (p2 >= 0) {if (p1 >= 0 && nums1[p1] > nums2[p2]) {nums1[p--] = nums1[p1--];} else {nums1[p--] = nums2[p2--];}}
}
5. 买卖股票的最佳时机(Best Time to Buy and Sell Stock)
function maxProfit(prices) {let minPrice = Infinity, maxProfit = 0;for (const price of prices) {minPrice = Math.min(minPrice, price);maxProfit = Math.max(maxProfit, price - minPrice);}return maxProfit;
}
6. 多数元素(Majority Element)
function majorityElement(nums) {let count = 0, candidate = null;for (const num of nums) {if (count === 0) candidate = num;count += (num === candidate) ? 1 : -1;}return candidate;
}
7. 移动零(Move Zeroes)
function moveZeroes(nums) {let slow = 0;for (let fast = 0; fast < nums.length; fast++) {if (nums[fast] !== 0) {nums[slow++] = nums[fast];}}while (slow < nums.length) {nums[slow++] = 0;}
}
8. 三数之和(3Sum)
function threeSum(nums) {nums.sort((a, b) => a - b);const res = [];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) left++;else if (sum > 0) right--;else {res.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--;}}}return res;
}
9. 无重复字符的最长子串(Longest Substring Without Repeating Characters)
function lengthOfLongestSubstring(s) {const map = new Map();let max = 0, left = 0;for (let right = 0; right < s.length; right++) {const c = s[right];if (map.has(c) && map.get(c) >= left) {left = map.get(c) + 1;}map.set(c, right);max = Math.max(max, right - left + 1);}return max;
}
10. 最长回文子串(Longest Palindromic Substring)
function longestPalindrome(s) {let max = '';for (let i = 0; i < s.length; i++) {const len1 = expand(s, i, i);const len2 = expand(s, i, i + 1);const longer = len1.length > len2.length ? len1 : len2;if (longer.length > max.length) max = longer;}return max;
}function expand(s, left, right) {while (left >= 0 && right < s.length && s[left] === s[right]) {left--;right++;}return s.slice(left + 1, right);
}


二、链表

1. 合并两个有序链表(Merge Two Sorted Lists)
function mergeTwoLists(l1, l2) {const dummy = new ListNode(-1);let current = dummy;while (l1 && l2) {if (l1.val < l2.val) {current.next = l1;l1 = l1.next;} else {current.next = l2;l2 = l2.next;}current = current.next;}current.next = l1 || l2;return dummy.next;
}class ListNode {constructor(val, next = null) {this.val = val;this.next = next;}
}
2. 环形链表(Linked List Cycle)
function hasCycle(head) {let slow = head, fast = head;while (fast && fast.next) {slow = slow.next;fast = fast.next.next;if (slow === fast) return true;}return false;
}
3. 相交链表(Intersection of Two Linked Lists)
function getIntersectionNode(headA, headB) {let pA = headA, pB = headB;while (pA !== pB) {pA = pA ? pA.next : headB;pB = pB ? pB.next : headA;}return pA;
}
4. 反转链表(Reverse Linked List)
function reverseList(head) {let prev = null, curr = head;while (curr) {const next = curr.next;curr.next = prev;prev = curr;curr = next;}return prev;
}
5. 两数相加(Add Two Numbers)
function addTwoNumbers(l1, l2) {const dummy = new ListNode(0);let curr = dummy, carry = 0;while (l1 || l2 || carry) {const sum = (l1?.val || 0) + (l2?.val || 0) + carry;carry = Math.floor(sum / 10);curr.next = new ListNode(sum % 10);curr = curr.next;l1 = l1?.next;l2 = l2?.next;}return dummy.next;
}
6. 删除链表的倒数第N个结点(Remove Nth Node From End of List)
function removeNthFromEnd(head, n) {const dummy = new ListNode(0, head);let fast = dummy, slow = dummy;for (let i = 0; i < n; i++) fast = fast.next;while (fast.next) {fast = fast.next;slow = slow.next;}slow.next = slow.next.next;return dummy.next;
}
7. 环形链表 II(Linked List Cycle II)
function detectCycle(head) {let slow = head, fast = head;while (fast && fast.next) {slow = slow.next;fast = fast.next.next;if (slow === fast) {fast = head;while (slow !== fast) {slow = slow.next;fast = fast.next;}return slow;}}return null;
}

三、二叉树

1. 对称二叉树(Symmetric Tree)
function isSymmetric(root) {if (!root) return true;return compare(root.left, root.right);
}function compare(left, right) {if (!left && !right) return true;if (!left || !right || left.val !== right.val) return false;return compare(left.left, right.right) && compare(left.right, right.left);
}
2. 二叉树的最大深度(Maximum Depth of Binary Tree)
function maxDepth(root) {if (!root) return 0;return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
3. 二叉树的中序遍历(Binary Tree Inorder Traversal)
function inorderTraversal(root) {const res = [];const stack = [];let curr = root;while (curr || stack.length) {while (curr) {stack.push(curr);curr = curr.left;}curr = stack.pop();res.push(curr.val);curr = curr.right;}return res;
}
4. 二叉树的层序遍历(Binary Tree Level Order Traversal)
function levelOrder(root) {const res = [];if (!root) return res;const queue = [root];while (queue.length) {const levelSize = queue.length;const level = [];for (let i = 0; i < levelSize; i++) {const node = queue.shift();level.push(node.val);if (node.left) queue.push(node.left);if (node.right) queue.push(node.right);}res.push(level);}return res;
}
5. 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal)
function buildTree(preorder, inorder) {const map = new Map();for (let i = 0; i < inorder.length; i++) map.set(inorder[i], i);return build(0, preorder.length - 1, 0, inorder.length - 1);function build(preStart, preEnd, inStart, inEnd) {if (preStart > preEnd) return null;const rootVal = preorder[preStart];const root = new TreeNode(rootVal);const rootIdx = map.get(rootVal);const leftSize = rootIdx - inStart;root.left = build(preStart + 1, preStart + leftSize, inStart, rootIdx - 1);root.right = build(preStart + leftSize + 1, preEnd, rootIdx + 1, inEnd);return root;}
}class TreeNode {constructor(val, left = null, right = null) {this.val = val;this.left = left;this.right = right;}
}
6. 二叉树展开为链表(Flatten Binary Tree to Linked List)
function flatten(root) {let curr = root;while (curr) {if (curr.left) {const predecessor = findRightmost(curr.left);predecessor.right = curr.right;curr.right = curr.left;curr.left = null;}curr = curr.right;}
}function findRightmost(node) {while (node.right) node = node.right;return node;
}

四、栈 & 队列

1. 有效的括号(Valid Parentheses)
function isValid(s) {const stack = [];const map = { '(': ')', '{': '}', '[': ']' };for (const c of s) {if (c in map) {stack.push(c);} else {if (!stack.length || map[stack.pop()] !== c) return false;}}return !stack.length;
}
2. 最小栈(Min Stack)
class MinStack {constructor() {this.stack = [];this.minStack = [];}push(val) {this.stack.push(val);if (this.minStack.length === 0 || val <= this.minStack[this.minStack.length - 1]) {this.minStack.push(val);}}pop() {const val = this.stack.pop();if (val === this.minStack[this.minStack.length - 1]) {this.minStack.pop();}}top() {return this.stack[this.stack.length - 1];}getMin() {return this.minStack[this.minStack.length - 1];}
}
3. 字符串解码(Decode String)
function decodeString(s) {const stack = [];let num = 0, str = '';for (const c of s) {if (/\d/.test(c)) {num = num * 10 + parseInt(c);} else if (c === '[') {stack.push(str);stack.push(num);str = '';num = 0;} else if (c === ']') {const repeat = stack.pop();const prevStr = stack.pop();str = prevStr + str.repeat(repeat);} else {str += c;}}return str;
}

五、双指针 & 滑动窗口

1. 验证回文串(Valid Palindrome)
function isPalindrome(s) {s = s.replace(/[^a-z0-9]/gi, '').toLowerCase();let left = 0, right = s.length - 1;while (left < right) {if (s[left++] !== s[right--]) return false;}return true;
}
2. 盛最多水的容器(Container With Most Water)
function maxArea(height) {let left = 0, right = height.length - 1, max = 0;while (left < right) {const area = Math.min(height[left], height[right]) * (right - left);max = Math.max(max, area);height[left] < height[right] ? left++ : right--;}return max;
}
3. 替换后的最长重复字符(Longest Repeating Character Replacement)
function characterReplacement(s, k) {const count = new Array(26).fill(0);let left = 0, maxCount = 0, maxLen = 0;for (let right = 0; right < s.length; right++) {const idx = s.charCodeAt(right) - 'A'.charCodeAt(0);maxCount = Math.max(maxCount, ++count[idx]);while (right - left + 1 - maxCount > k) {count[s.charCodeAt(left) - 'A'.charCodeAt(0)]--;left++;}maxLen = Math.max(maxLen, right - left + 1);}return maxLen;
}
4. 字符串的排列(Permutation in String)
function checkInclusion(s1, s2) {const target = new Array(26).fill(0);const window = new Array(26).fill(0);for (const c of s1) target[c.charCodeAt() - 97]++;let left = 0;for (let right = 0; right < s2.length; right++) {const c = s2[right].charCodeAt() - 97;window[c]++;while (window[c] > target[c]) {window[s2[left++].charCodeAt() - 97]--;}if (right - left + 1 === s1.length) return true;}return false;
}

六、动态规划

1. 爬楼梯(Climbing Stairs)
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;
}
2. 杨辉三角(Pascal's Triangle)
function generate(numRows) {const res = [];for (let i = 0; i < numRows; i++) {const row = new Array(i + 1).fill(1);for (let j = 1; j < i; j++) {row[j] = res[i - 1][j - 1] + res[i - 1][j];}res.push(row);}return res;
}
3. 最大子数组和(Maximum Subarray)
function maxSubArray(nums) {let max = nums[0], curr = nums[0];for (let i = 1; i < nums.length; i++) {curr = Math.max(nums[i], curr + nums[i]);max = Math.max(max, curr);}return max;
}
4. 不同路径(Unique Paths)
function uniquePaths(m, n) {const dp = new Array(n).fill(1);for (let i = 1; i < m; i++) {for (let j = 1; j < n; j++) {dp[j] += dp[j - 1];}}return dp[n - 1];
}
5. 最小路径和(Minimum Path Sum)
function minPathSum(grid) {const m = grid.length, n = grid[0].length;for (let i = 1; i < m; i++) grid[i][0] += grid[i - 1][0];for (let j = 1; j < n; j++) grid[0][j] += grid[0][j - 1];for (let i = 1; i < m; i++) {for (let j = 1; j < n; j++) {grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]);}}return grid[m - 1][n - 1];
}
6. 最长递增子序列(Longest Increasing Subsequence)
function lengthOfLIS(nums) {const dp = new Array(nums.length).fill(1);let max = 1;for (let i = 1; i < nums.length; i++) {for (let j = 0; j < i; j++) {if (nums[i] > nums[j]) dp[i] = Math.max(dp[i], dp[j] + 1);}max = Math.max(max, dp[i]);}return max;
}

七、回溯 & DFS

1. 括号生成(Generate Parentheses)
function generateParenthesis(n) {const res = [];backtrack("", 0, 0);return res;function backtrack(s, left, right) {if (s.length === 2 * n) {res.push(s);return;}if (left < n) backtrack(s + "(", left + 1, right);if (right < left) backtrack(s + ")", left, right + 1);}
}
2. 全排列(Permutations)
function permute(nums) {const res = [];backtrack(0);return res;function backtrack(start) {if (start === nums.length) {res.push([...nums]);return;}for (let i = start; i < nums.length; i++) {[nums[start], nums[i]] = [nums[i], nums[start]];backtrack(start + 1);[nums[start], nums[i]] = [nums[i], nums[start]];}}
}
3. 子集(Subsets)
function subsets(nums) {const res = [[]];for (const num of nums) {const size = res.length;for (let i = 0; i < size; i++) {res.push([...res[i], num]);}}return res;
}
4. 单词搜索(Word Search)
function exist(board, word) {const m = board.length, n = board[0].length;for (let i = 0; i < m; i++) {for (let j = 0; j < n; j++) {if (dfs(i, j, 0)) return true;}}return false;function dfs(i, j, idx) {if (idx === word.length) return true;if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] !== word[idx]) return false;const temp = board[i][j];board[i][j] = "#";const found = dfs(i + 1, j, idx + 1) || dfs(i - 1, j, idx + 1) ||dfs(i, j + 1, idx + 1) || dfs(i, j - 1, idx + 1);board[i][j] = temp;return found;}
}

八、设计题

1. LRU 缓存(LRU Cache)
class LRUCache {constructor(capacity) {this.capacity = capacity;this.cache = new Map();}get(key) {if (!this.cache.has(key)) return -1;const value = this.cache.get(key);this.cache.delete(key);this.cache.set(key, value);return value;}put(key, value) {if (this.cache.has(key)) this.cache.delete(key);this.cache.set(key, value);if (this.cache.size > this.capacity) {this.cache.delete(this.cache.keys().next().value);}}
}

九、排序 & 贪心

1. 合并区间(Merge Intervals)
function merge(intervals) {intervals.sort((a, b) => a[0] - b[0]);const res = [intervals[0]];for (let i = 1; i < intervals.length; i++) {const last = res[res.length - 1];if (intervals[i][0] <= last[1]) {last[1] = Math.max(last[1], intervals[i][1]);} else {res.push(intervals[i]);}}return res;
}
2. 颜色分类(Sort Colors)
function sortColors(nums) {let left = 0, right = nums.length - 1, curr = 0;while (curr <= right) {if (nums[curr] === 0) {[nums[curr], nums[left]] = [nums[left], nums[curr]];left++;curr++;} else if (nums[curr] === 2) {[nums[curr], nums[right]] = [nums[right], nums[curr]];right--;} else {curr++;}}
}

十、位运算

1. 只出现一次的数字(Single Number)
function singleNumber(nums) {return nums.reduce((acc, num) => acc ^ num, 0);
}

相关文章:

LeetCode Hot100题解

目录 一、数组 & 字符串 1. 两数之和&#xff08;简单&#xff09; 2. 删除有序数组中的重复项&#xff08;简单&#xff09; 3. 移除元素&#xff08;简单&#xff09; 4. 合并两个有序数组&#xff08;简单&#xff09; 5. 买卖股票的最佳时机&#xff08;简单&…...

基于Jenkins的DevOps工程实践之Jenkins共享库

文章目录 前言Jenkins共享库结构1、共享库演示2、知识点补充3、实践使用共享库格式化输出日志4、groovy基础语法4.1、 什么是 Groovy&#xff1f;4.2、groovy特点4.3、运行方法4.4、标识符4.5、基本数据类型4.5.1、string类型4.5.2、list类型 4.6、函数使用4.7、正则表达式 5、…...

【安装指南】Docker 安装最新版 Nginx 并进行项目的编排

目录 一、Nginx 的介绍 1.1 开源版 Nginx​ ① 访问路由​ ② 反向代理​ ③ 负载均衡​ ④ 内容缓存​ ⑤ 可编程​ 1.2 商业版 Nginx Plus​ ① 负载均衡​ ② 动态管理​ ③ 安全控制​ ④ 状态监控​ ⑤ Kubernetes Ingress Controller​ ⑥ 流媒体​ 1.3 扩…...

MFC自定义控件开发与使用指南

MFC自定义控件开发与使用指南 1. 概述 MFC(Microsoft Foundation Classes)框架提供了丰富的内置控件,但在实际开发中,我们常常需要创建自定义控件来满足特定的界面需求。本文将详细介绍如何在MFC中开发自定义控件,并以CCustomTextControl为例,展示自定义控件的实现和使…...

Learning vtkjs之PolyDataNormals

法线可视化 介绍 polydata法线可视化 效果 核心代码 主要流程 const fullScreenRenderer vtkFullScreenRenderWindow.newInstance({background: [0, 0, 0],rootContainer: vtkContainerRef.current,});const renderer fullScreenRenderer.getRenderer();const renderWind…...

DeepSeek辅助学术写作之提交和出版以及评审过程分析提示词分享祝你顺利毕业~

目录 1.提交和出版 2.评审过程 大家好这里是AIWritePaper官方账号&#xff0c;官网&#x1f449;AIWritePaper~ 宝子们可以使用小编精选的“ChatGPT研究论文提示词”集合来创建研究论文。利用DeepSeek的智能回应生成详尽有效的内容&#xff0c;这样可以加快研究论文的策划、创…...

基于机器学习的心脏病数据分析与可视化(百度智能云千帆AI+DeepSeek人工智能+机器学习)健康预测、风险评估与数据可视化 健康管理平台 数据分析与处理

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

Kubernetes(k8s)学习笔记(四)--入门基本操作

本文通过kubernetes部署tomcat集群&#xff0c;来学习和掌握kubernetes的一些入门基本操作 前提条件 1.各个节点处于Ready状态&#xff1b; 2.配置好docker镜像库(否则会出现ImagePullBackOff等一些问题)&#xff1b; 3.网络配置正常(否则即使应用发布没问题&#xff0c;浏…...

在Java项目中实现本地语音识别与热点检测,并集成阿里云智能语音服务

引言 随着语音交互技术的发展&#xff0c;如何高效地处理用户的语音输入成为许多应用的重要课题。本文将详细介绍如何在一个Java项目中同时实现&#xff1a; 基于Vosk的本地语音识别&#xff1a;无需调用云端API即可完成语音到文本的转换。本地热点语音内容识别&#xff1a;对…...

C++八股--5--设计模式--适配器模式,代理模式,观察者模式

3. 观察者模式&#xff08;也叫做观察者-监听者模式&#xff0c;发布-订阅模式&#xff09; 主要关注对象的一对多关系&#xff0c;也就是多个对象都依赖于一个对象&#xff0c;当该对象状态改变时&#xff0c;其余对象都能得到对应的通知 如&#xff1a;一组数据&#xff08;数…...

Ubuntu下安装Node.js

一、引言 Ubuntu下安装Node.js主要有两种方式&#xff1a;通过apt安装和通过源码安装。本文主要讲解通过apt安装Node.js的方法。 二、通过apt安装Node.js 安装Node.js&#xff1a; apt install nodejs 我之前已经安装过了&#xff0c;所以提示&#xff1a;“nodejs 已经是最…...

用单目相机和apriltag二维码aruco实现单目定位

目录 一、核心流程与代码框架 1. ‌环境准备‌ 2. ‌ArUco定位实现 3. ‌AprilTag定位实现&#xff08;需额外安装Apriltag库&#xff09; 二、关键优化点 1‌.亚像素角点优化 2‌ 多标签联合定位 三、性能指标&#xff08;实测&#xff09; 四、常见问题 ‌检测失败…...

AIGC算力消耗白皮书:Stable Diffusion vs Midjourney的架构成本差异

引言&#xff1a;文生图模型的算力经济学悖论 当Midjourney单日处理超过4000万张图像请求时&#xff0c;其云服务算力成本却低于Stable Diffusion开源方案的37%。这揭示了一个核心矛盾&#xff1a;开源模型的架构自由度与闭源系统的商业优化之间存在根本性博弈。本文基于H800 …...

介绍 PHP-FPM 和 Python WSGI

我来详细介绍 PHP-FPM 和 Python WSGI&#xff0c;它们是现代Web开发中替代传统CGI的高性能解决方案&#xff0c;分别针对PHP和Python优化。 1. PHP-FPM&#xff08;FastCGI Process Manager&#xff09; 是什么&#xff1f; PHP-FPM 是PHP的 FastCGI 进程管理器&#xff0c;…...

赛季7靶场 -- Checker --User flag

本系列仅说明靶场的攻击思路&#xff0c;不会给出任何的详细代码执行步骤&#xff0c;因为个人觉得找到合适的工具以实现攻击思路的能力也非常重要。root要逆向&#xff0c;没做了&#xff0c;但是user flag也有借鉴意义&#xff0c;关于2FA的绕过我们有必要了解 1.首先Nmap扫描…...

【c语言】数据在内存中的存储

一、 大小端字节序 大端字节序&#xff1a;数据的低字节内容存放在内存的高地址处&#xff0c;数据的高字节内容存放在内存的低地址处&#xff0c;对于0x11223344 小端字节序&#xff1a;数据的低字节内容存放在内存的低地址处&#xff0c;数据的高字节内容存放在内存的高地…...

【Unity】XLua访问C#文件

创建NPC.cs&#xff1a; public class NPC { public string name; public int age; public void Say() { Debug.Log("Say:我是未被修改的"); } public static void Say() { Debug.Log("Static Say:我是未被修改的"); } public void Say2(int a) { Debug.Lo…...

Python实例题:Python获取房天下数据

目录 Python实例题 题目 实现思路 代码实现 代码解释 get_fangtianxia_data 函数&#xff1a; 主程序&#xff1a; 运行思路 注意事项 Python实例题 题目 Python获取房天下数据 实现思路 请求网页&#xff1a;使用 requests 库向房天下二手房页面发送请求&#xf…...

Milvus(12):分析器

1 分析器概述 在文本处理中&#xff0c;分析器是将原始文本转换为结构化可搜索格式的关键组件。每个分析器通常由两个核心部件组成&#xff1a;标记器和过滤器。它们共同将输入文本转换为标记&#xff0c;完善这些标记&#xff0c;并为高效索引和检索做好准备。 在 Milvus 中&a…...

小程序滚动条隐藏(uniapp版本)

单独指定页面隐藏&#xff08;找到对应的scroll-view&#xff09; <style> /* 全局隐藏滚动条样式 */ ::-webkit-scrollbar { display: none; width: 0; height: 0; color: transparent; background: transparent; } /* 确保scroll-view组件也隐藏滚动条 */ …...

在 Trae CN IDE 中配置 Python 3.11的指南

在 Trae CN IDE 中配置 Python 3.11的指南 下载 python 3.11 安装 Python 3.11 首先&#xff0c;我们需要确保安装了 Python 3.11。可以从Python 官方网站下载适合你操作系统的版本。 链接 如果你已经安装了 Python 3.11&#xff0c;可以通过以下命令确认&#xff1a; 文…...

AI 大模型常见面试题(及内容解析)

大模型领域包含许多专业术语&#xff0c;以下是一些关键术语的解释&#xff1a; 人工智能&#xff08;AI&#xff09;&#xff1a;是指使计算机系统能够模拟人类智能行为&#xff0c;以执行任务、解决问题和学习的科学和技术。 大型语言模型&#xff08;LLM&#xff09;&#…...

QT —— QWidget(1)

QT —— QWidget&#xff08;1&#xff09; QWidget是啥通俗解释&#xff1a;QWidget 是什么&#xff1f;1. QWidget 能干什么&#xff1f;2. 举个栗子 &#x1f330;3. QWidget 的特点4. 和“控件”是什么关系&#xff1f;5. 什么时候用 QWidget&#xff1f;6. 总结 QWidget 核…...

with的用法

Python SQLite 操作详解 本文档详细解释了使用 Python 操作 SQLite 数据库时涉及的关键概念和代码实践&#xff0c;包括 with 语句、事务处理、批量插入以及相关的优化建议。 一、with 语句的作用&#xff08;自动关门的保险库&#xff09; with sqlite3.connect(city_1301.d…...

Go反射-通过反射调用结构体的方法(带入参)

使用反射前&#xff0c;我们需要提前做好映射配置 papckage_struct_relationship.go package reflectcommonimport (api "template/api" )// 包名到包对象的映射 var structMap map[string]func() interface{}{"template/api": func() interface{} { re…...

C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录 二…...

使用 Selenium 爬取动态网页数据 —— 实战与坑点详解

本文记录了笔者在爬取网页数据过程中遇到的各种技术挑战&#xff0c;包括页面动态渲染、JavaScript 注入等问题&#xff0c;并最终给出一个可运行的完整方案。 文章目录 网页获取不到数据&#x1f680; 尝试用 Selenium 渲染页面 网页获取不到数据 某网页数据依赖大量 JavaSc…...

强化学习--2.数学

强化学习--数学 1、概率统计知识1.1 随机变量与观测值1.2 概率密度函数&#xff08;PDF&#xff09;1.3 期望1.4 随机抽样 2、数据期望E3、正态分布4、条件概率1. **与多个条件相关**&#xff08;依赖所有前置条件&#xff09;2. **仅与上一个条件相关**&#xff08;马尔可夫性…...

rails 8 CSS不起效问题解决

很久没用rails了&#xff0c;最近打算重新复习一下。在配置好环境后&#xff0c;创建了项目&#xff0c;通过脚手架创建了数据库表&#xff0c;和相关的文件。但我发现却没有生成相应的CSS文件&#xff0c;可能是rails8 取消了吧。于是自己手动创建了相应的css文件。但是刷新页…...

双指针算法详解(含力扣和蓝桥杯例题)

目录 一、双指针算法核心概念 二、常用的双指针类型&#xff1a; 2.1 对撞指针 例题1&#xff1a;盛最多水的容器 例题2&#xff1a;神奇的数组 2.2 快慢指针&#xff1a; 例题1&#xff1a;移动零 例题2&#xff1a;美丽的区间&#xff08;蓝桥OJ1372&#xff09; 3.总…...

C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱 你好!在 C 语言编程中,与用户进行交互最基本的方式就是通过标准输入和标准输出。我们之前探讨了如何使用 ​​printf​​ 和 ​​putchar​​ 进行…...

算法笔记。质数筛算法

题目&#xff1a; 给定一个正整数 n&#xff0c;请你求出 1∼n 中质数的个数。 输入格式 共一行&#xff0c;包含整数 n。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示 1∼n 中质数的个数。 数据范围 1≤n≤106 输入样例&#xff1a; 8输出样例&#xf…...

C语言中memmove和memcpy

1、memmove()函数 void *memmove(void *str1, const void *str2, size_t n); 将str2所指向的存储区的前n个字节复制到str1所指向的存储区。 memmove()允许“str1和str2所指向的存储区重叠”。通过检查地址关系&#xff0c;自动选择复制方向&#xff08;从前往后或从后往前&a…...

GESP2024年6月认证C++八级( 第三部分编程题(2)空间跳跃)

参考程序&#xff1a; #include <cstdio> #include <vector> #include <queue> #include <utility> #include <cstring> using namespace std;// 定义一个结构体&#xff0c;用于 Dijkstra 优先队列中的节点 struct Node {int v, w; // v 表示图…...

使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例

前言 本来想再发几个小游戏后在整理一下流程的&#xff0c;但是今天试了一下这个俄罗斯方块的游戏结果发现本来修改的好好的的&#xff0c;结果后面越改越乱&#xff0c;前面的版本也没保存&#xff0c;根据AI修改他是在几个版本改来改去&#xff0c;想着要求还是不能这么高。…...

Linux中安装mysql8,转载及注意事项

一、先前往官网下载mysql8 下载地址&#xff1a; https://dev.mysql.com/downloads/选择Linux 二、删除Linux中的mysql&#xff08;如果有的话&#xff09;&#xff0c;上传安装包 1、先查看mysql是否存在&#xff0c;命令如下&#xff1a; rpm -qa|grep -i mysql如果使用这…...

网站即时备份,网站即时备份的方法有哪些

网站数据的安全性与业务连续性直接关系到企业的核心竞争力。无论是因硬件故障、人为误操作、网络攻击还是自然灾害&#xff0c;数据丢失或服务中断都可能带来难以估量的损失。因此&#xff0c;网站即时备份成为保障业务稳定性的关键技术手段。 一、核心即时备份技术方案 云服…...

LVM扩容小计

文章目录 [toc]当前磁盘使用问题分析关键问题定位推荐解决方案方案一&#xff1a;扩展根分区&#xff08;LVM 动态扩容&#xff09;方案二&#xff1a;清理磁盘空间&#xff08;紧急临时处理&#xff09; 当前磁盘使用问题分析 根据你的磁盘信息&#xff0c;根文件系统 (/) 已…...

【2025软考高级架构师】——案例分析总结(13)

摘要 本文对2025年软考高级架构师的考纲及案例分析进行了总结。内容涵盖系统规划、架构设计、系统建模、安全架构、可靠性分析、大数据架构等多方面知识点&#xff0c;还涉及软件质量特性、系统流程图与数据流图、嵌入式系统架构、分布式系统设计等考查内容&#xff0c;详细列…...

Redis ⑨-Jedis | Spring Redis

Jedis 通过 Jedis 可以连接 Redis 服务器。 通过 Maven 引入 Jedis 依赖。 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><versi…...

aidermacs开源程序使用 Aider 在 Emacs 中进行 AI 配对编程

一、软件介绍 文末提供程序和源码下载 Aidermacs 通过集成 Aider&#xff08;最强大的开源 AI 配对编程工具之一&#xff09;为 Emacs 带来了 AI 驱动的开发。如果您缺少 Cursor&#xff0c;但更喜欢生活在 Emacs 中&#xff0c;Aidermacs 提供了类似的 AI 功能&#xff0c;同…...

HarmonyOS NEXT——DevEco Studio的使用(还没写完)

一、IDE环境的搭建 Windows环境 运行环境要求 为保证DevEco Studio正常运行&#xff0c;建议电脑配置满足如下要求&#xff1a; 操作系统&#xff1a;Windows10 64位、Windows11 64位 内存&#xff1a;16GB及以上 硬盘&#xff1a;100GB及以上 分辨率&#xff1a;1280*8…...

使用PageHelper实现分页查询(详细)

一&#xff1a;需求分析与设计 1.1 产品原型 &#xff08;1&#xff09;分页展示&#xff0c;每页展示10条数据&#xff0c;根据员工姓名进行搜索 &#xff08;2&#xff09;业务规则 1.2 接口设计 &#xff08;1&#xff09;操作&#xff1a;查询&#xff0c;请求方式&#xf…...

神经网络基础-从零开始搭建一个神经网络

一、什么是神经网络 人工神经网络&#xff08;Articial Neural Network&#xff0c;简写为ANN&#xff09;也称为神经网络&#xff08;NN),是一种模仿生物神经网络和功能的计算模型&#xff0c;人脑可以看做是一个生物神经网络&#xff0c;由众多的神经元连接而成&#xff0c;…...

数据库原理与应用实验二 题目七

利用sql建立教材数据库,并定义以下基本表: 学生(学号,年龄,性别,系名) 教材(编号,书名,出版社编号,价格) 订购(学号,书号,数量) 出版社(编号,名称,地址) 1定义主码、外码、和价格、数量的取值范围。 2 在三个表中输入若干记录,注意如果输入违反完整…...

如何在 CentOS 7 命令行连接 Wi-Fi?如何在 Linux 命令行连接 Wi-Fi?

如何在 CentOS 7 命令行连接 Wi-Fi&#xff1f;如何在 Linux 命令行连接 Wi-Fi&#xff1f; 摘要 本教程覆盖如何在多种 Linux 发行版下通过命令行连接 Wi-Fi&#xff0c;包括&#xff1a; CentOS 7、Ubuntu、Debian、Arch Linux、Fedora、Alpine Linux、Kali Linux、OpenSU…...

【学习笔记】 强化学习:实用方法论

作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程&#xff0c;深度学习领域研究生必读教材),开始深度学习领域学习&#xff0c;深入全面的理解深度学习的理论知识。 之前的文章参考下面的链接&#xf…...

ElasticSearch深入解析(十):字段膨胀(Mapping 爆炸)问题的解决思路

文章目录 一、核心原理&#xff1a;动态映射的双刃剑1. 动态映射的工作机制2. 映射爆炸的触发条件3. 底层性能损耗 二、典型场景与案例分析1. 日志系统&#xff1a;动态标签引发的灾难2. 物联网数据&#xff1a;设备属性的无序扩展 三、系统性解决方案1. 架构层优化2. 配置层控…...

react18基础速成

1、项目搭建 npx create-react-app my-react-app&#xff08;项目名&#xff09; cd 项目名进入项目目录 终端输入 npm start 启动项目 浏览器查看 项目搭建成功 2、JSX JavaScript语法和HTML语法写在一起就是JSX语法 jsx只能返回一个根元素&#xff0c;即最外层的div&a…...

18、状态库:中央魔法仓库——React 19 Zustand集成

一、量子熔炉的诞生 "Zustand是记忆水晶的量子纠缠体&#xff0c;让状态流无需魔杖驱动即可自洽&#xff01;"霍格沃茨炼金术研究院的工程师挥动魔杖&#xff0c;Zustand 的原子化状态流在空中交织成星轨矩阵。 ——基于《魔法国会》第2025号协议&#xff0c;Zustan…...