第一题:242. 有效的字母异位词
解法1:数组计数法(最优)
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length()) return false;
int[] alpha = new int[26];
for(int i=0;i<s.length();i++){
alpha[s.charAt(i)-'a']++;
alpha[t.charAt(i)-'a']--;
}
for(int i=0;i<26;i++){
if(alpha[i]!=0) return false;
}
return true;
}
}
特点:
- 时间复杂度:O(n)
- 空间复杂度:O(1)
- 只适用于小写字母场景
解法2:排序比较法
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length()!=t.length()) return false;
sort(s.begin(),s.end());
sort(t.begin(),t.end());
return s==t;
}
};
特点:
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1) 或 O(n)(取决于排序算法)
- 通用性强,但效率较低
解法3:哈希表法
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length() != t.length()) return false;
unordered_map<char, int> map;
for(char c : s) map[c]++;
for(char c : t) map[c]--;
for(auto val : map) {
if(val.second != 0) return false;
}
return true;
}
};
特点:
- 时间复杂度:O(n)
- 空间复杂度:O(k),k为字符集大小
- 适用于Unicode字符
第二题:202. 快乐数
解法1:快慢指针法(Floyd判圈)
class Solution {
public:
int bitSqureSum(int n) {
int sum = 0;
while(n > 0) {
int bit = n % 10;
sum += bit * bit;
n = n / 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n, fast = n;
while(true) {
fast = bitSqureSum(fast);
fast = bitSqureSum(fast); // 快指针走两步
slow = bitSqureSum(slow); // 慢指针走一步
if(fast == 1) return true; // 找到快乐数
if(fast == slow) return false; // 进入循环
}
}
};
特点:
- 时间复杂度:O(logn)
- 空间复杂度:O(1)
- 数学证明:非快乐数最终会进入循环
解法2:哈希表记录法
class Solution {
public:
int bitSqureSum(int n) {
int sum = 0;
while(n > 0) {
int bit = n % 10;
sum += bit * bit;
n = n / 10;
}
return sum;
}
bool isHappy(int n) {
unordered_map<int,int> map;
map[n] = 1;
while(n != 1) {
n = bitSqureSum(n);
if(map[n] == 1) return false; // 出现重复,进入循环
map[n] = 1;
}
return true;
}
};
特点:
- 时间复杂度:O(logn)
- 空间复杂度:O(logn)
- 思路直观,容易理解
第三题:349. 两个数组的交集
解法1:数组哈希法
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[10000] = {0};
vector<int> ans;
for(int i=0;i<nums1.size();i++) {
hash[nums1[i]] = 1;
}
for(int i=0;i<nums2.size();i++) {
if(hash[nums2[i]] == 1) {
ans.push_back(nums2[i]);
hash[nums2[i]] = 2; // 标记为已添加,避免重复
}
}
return ans;
}
};
特点:
- 时间复杂度:O(m+n)
- 空间复杂度:O(10000)
- 适用于数值范围已知的情况
解法2:双哈希表法
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> map, quchong;
vector<int> ans;
for(int a : nums1) {
map[a] = 1;
}
for(int a : nums2) {
if(map[a] && quchong[a] != 1) {
quchong[a] = 1;
ans.push_back(a);
}
}
return ans;
}
};
特点:
- 时间复杂度:O(m+n)
- 空间复杂度:O(m)
- 通用性强,适用于任意整数
第四题:1. 两数之和
解法1:哈希表一次遍历(最优)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for(int i=0;i<nums.size();i++) {
if(map.count(target - nums[i]))
return {i, map[target - nums[i]]};
map[nums[i]] = i;
}
return {};
}
};
特点:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 一次遍历,边查边存
解法2:暴力枚举法
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
for(int i=0;i<numsSize;i++){
for(int j=i+1;j<numsSize;j++){
if(nums[i]+nums[j]==target){
*returnSize=2;
int *ans=(int*)malloc(sizeof(int)*2);
ans[0]=i;ans[1]=j;
return ans;
}
}
}
*returnSize=0;
return NULL;
}
特点:
- 时间复杂度:O(n²)
- 空间复杂度:O(1)
- 思路简单,但效率低
核心技巧总结
| 技巧 | 适用场景 | 代表题目 |
|---|---|---|
| 数组计数 | 字符统计、数值范围固定 | 有效的字母异位词 |
| 快慢指针 | 循环检测、链表问题 | 快乐数、环形链表 |
| 哈希表记录 | 查找、去重、计数 | 两数之和、交集 |
| 排序+双指针 | 需要有序处理的场景 | 三数之和等 |
选择建议
- 字符/小范围数值 → 数组计数法
- 循环检测问题 → 快慢指针法
- 通用查找问题 → 哈希表法
- 简单场景 → 暴力法(小数据量)