还在为算法面试发愁?别怕!本文精选10道C++高频算法题,手把手教你解题思路+代码实现,助你轻松上岸!🚀
文章目录
-
-
- [1. 字母异位词判断 🔤](#1. 字母异位词判断 🔤)
- [2. 两数之和 🎯](#2. 两数之和 🎯)
- [3. 快乐数 😄](#3. 快乐数 😄)
- [4. 赎金信 ✉️](#4. 赎金信 ✉️)
- [5. 三数之和 🌟](#5. 三数之和 🌟)
- [6. 四数之和 🔢](#6. 四数之和 🔢)
- [7. 四数相加II 🧮](#7. 四数相加II 🧮)
- [8. 有效的数独 ✅](#8. 有效的数独 ✅)
- [9. LRU缓存机制 ⚙️](#9. LRU缓存机制 ⚙️)
- [总结 🎉](#总结 🎉)
-
1. 字母异位词判断 🔤
题目 :判断字符串 t
是否是 s
的字母异位词(字母相同但顺序不同)。
示例:
输入:
s = "anagram"
,t = "nagaram"
→ 输出:true
解法:
- 核心:统计字符频次是否一致。
- 步骤 :
- 若长度不等,直接返回
false
; - 用数组
freq[26]
统计s
的字符频次; - 遍历
t
,减少频次,若出现负数则无效。
- 若长度不等,直接返回
C++代码:
cpp
bool isAnagram(string s, string t) {
if (s.size() != t.size()) return false;
int freq[26] = {0};
for (char c : s) freq[c - 'a']++;
for (char c : t) if (--freq[c - 'a'] < 0) return false;
return true;
}
时间复杂度 : O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)(固定大小数组)
2. 两数之和 🎯
题目 :在数组 nums
中找出和为 target
的两个数,返回其下标。
要求:每种输入只对应一个答案,且元素不重复使用。
解法:
- 核心:哈希表记录遍历过的值及其下标。
- 步骤 :
- 遍历数组,计算补数
complement = target - nums[i]
; - 若补数在哈希表中,返回下标;否则记录当前值。
- 遍历数组,计算补数
C++代码:
cpp
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); i++) {
int comp = target - nums[i];
if (map.count(comp)) return {map[comp], i};
map[nums[i]] = i;
}
return {};
}
时间复杂度 : O ( n ) O(n) O(n),空间复杂度: O ( n ) O(n) O(n)
3. 快乐数 😄
题目 :判断一个数 n
是否为快乐数(最终通过平方和变为1)。
关键点:若陷入循环则不是快乐数。
解法:
- 核心:用哈希集合检测循环。
- 步骤 :
- 计算
n
的各位平方和; - 若和为
1
,返回true
; - 若和已存在于集合,返回
false
;否则加入集合并继续。
- 计算
C++代码:
cpp
bool isHappy(int n) {
unordered_set<int> seen;
while (n != 1) {
int sum = 0;
while (n) {
int digit = n % 10;
sum += digit * digit;
n /= 10;
}
if (seen.count(sum)) return false;
seen.insert(sum);
n = sum;
}
return true;
}
时间复杂度 : O ( log n ) O(\log n) O(logn)(收敛速度快),空间复杂度: O ( log n ) O(\log n) O(logn)
4. 赎金信 ✉️
题目 :判断 ransom
能否由 magazine
中的字符构成(每个字符仅用一次)。
解法:
- 核心 :统计
magazine
的字符频次,检查是否覆盖ransom
。 - 步骤 :
- 用数组统计
magazine
的字符频次; - 遍历
ransom
,减少频次,若出现负数则无效。
- 用数组统计
C++代码:
cpp
bool canConstruct(string ransom, string magazine) {
int freq[26] = {0};
for (char c : magazine) freq[c - 'a']++;
for (char c : ransom) if (--freq[c - 'a'] < 0) return false;
return true;
}
时间复杂度 : O ( m + n ) O(m+n) O(m+n),空间复杂度: O ( 1 ) O(1) O(1)
5. 三数之和 🌟
题目 :找出数组 nums
中所有和为 0
的不重复三元组。
解法:
- 核心:排序 + 双指针。
- 步骤 :
- 排序数组;
- 遍历数组,对每个元素
nums[i]
,用双指针在右侧找-nums[i]
; - 跳过重复元素避免重复解。
C++代码:
cpp
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) {
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--;
}
else if (sum < 0) left++;
else right--;
}
}
return res;
}
时间复杂度 : O ( n 2 ) O(n^2) O(n2),空间复杂度: O ( 1 ) O(1) O(1)(忽略输出存储)
6. 四数之和 🔢
题目 :找出数组 nums
中所有和为 target
的不重复四元组。
解法:
- 核心:排序 + 双层循环 + 双指针(类似三数之和)。
- 步骤 :
- 排序数组;
- 两层循环确定前两个数,双指针确定后两个数;
- 跳过重复元素。
C++代码:
cpp
vector<vector<int>> fourSum(vector<int>& nums, int target) {
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;
for (int j = i + 1; j < nums.size(); j++) {
if (j > i+1 && nums[j] == nums[j-1]) continue;
int left = j + 1, right = nums.size() - 1;
while (left < right) {
long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
res.push_back({nums[i], nums[j], 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 res;
}
时间复杂度 : O ( n 3 ) O(n^3) O(n3)
7. 四数相加II 🧮
题目 :计算四个等长数组 A, B, C, D
中,有多少元组满足 A [ i ] + B [ j ] + C [ k ] + D [ l ] = 0 A[i] + B[j] + C[k] + D[l] = 0 A[i]+B[j]+C[k]+D[l]=0。
解法:
- 核心:分组 + 哈希表。
- 步骤 :
- 计算
A
和B
所有元素和,存入哈希表(和→频次); - 计算
C
和D
所有元素和,查找哈希表中是否存在相反数。
- 计算
C++代码:
cpp
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int, int> map;
for (int a : A) for (int b : B) map[a + b]++;
int count = 0;
for (int c : C) for (int d : D) count += map[-(c + d)];
return count;
}
时间复杂度 : O ( n 2 ) O(n^2) O(n2),空间复杂度: O ( n 2 ) O(n^2) O(n2)
8. 有效的数独 ✅
题目:判断 9×9 数独是否有效(行、列、3×3宫内无重复数字)。
解法:
- 核心:用三个二维数组分别记录行、列、宫内的数字出现情况。
- 关键 :宫索引计算:
box_index = (i / 3) * 3 + j / 3
。
C++代码:
cpp
bool isValidSudoku(vector<vector<char>>& board) {
int rows[9][9] = {0}, cols[9][9] = {0}, boxes[9][9] = {0};
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') continue;
int num = board[i][j] - '1';
int box_idx = (i / 3) * 3 + j / 3;
if (rows[i][num] || cols[j][num] || boxes[box_idx][num])
return false;
rows[i][num] = cols[j][num] = boxes[box_idx][num] = 1;
}
}
return true;
}
时间复杂度 : O ( 1 ) O(1) O(1)(固定81次循环),空间复杂度: O ( 1 ) O(1) O(1)
9. LRU缓存机制 ⚙️
题目 :设计 LRU 缓存,支持 get
和 put
操作(时间复杂度 O ( 1 ) O(1) O(1))。
解法:
- 核心:双向链表(维护使用顺序) + 哈希表(快速定位节点)。
- 关键操作 :
get
:将节点移到链表头部;put
:若存在则更新值并移到头部;若不存在则插入新节点,若超容则删除尾部节点。
C++代码:
cpp
class LRUCache {
private:
struct Node {
int key, val;
Node *prev, *next;
Node(int k, int v) : key(k), val(v) {}
};
unordered_map<int, Node*> map;
Node *head, *tail;
int capacity;
void removeNode(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;
}
void moveToHead(Node* node) {
removeNode(node);
addToHead(node);
}
Node* popTail() {
Node* node = tail->prev;
removeNode(node);
return node;
}
public:
LRUCache(int cap) : capacity(cap) {
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];
moveToHead(node);
return node->val;
}
void put(int key, int value) {
if (map.count(key)) {
Node* node = map[key];
node->val = value;
moveToHead(node);
} else {
Node* node = new Node(key, value);
map[key] = node;
addToHead(node);
if (map.size() > capacity) {
Node* tail = popTail();
map.erase(tail->key);
delete tail;
}
}
}
};
时间复杂度 : O ( 1 ) O(1) O(1) 所有操作
总结 🎉
掌握这10道题,算法面试不再慌!重点在于:
- 哈希表用于快速查找(两数之和、字母异位词等);
- 双指针用于有序数组的搜索(三数之和等);
- 链表+哈希实现 O ( 1 ) O(1) O(1) 复杂度的 LRU。
快去刷题吧,offer在等你!💪
如果本文对你有帮助,欢迎点赞收藏🌟
需要完整代码模板的评论区留言~👇