一、知识点介绍
二、练习题目
(1) 1512. 好数对的数目
(2) 2006. 差的绝对值为 K 的数对数目
(3) 1347. 制造字母异位词的最小步骤数
(4) 面试题 10.02. 变位词组
三、算法思路
1. 好数对的数目
(1) 暴力遍历,符合条件的话,计数器加1
(2) 最后返回计数器
class Solution {
public:
int numIdenticalPairs(vector<int>& nums) {
int cnt = 0;
for(int i = 0; i < nums.size(); ++i) {
for(int j = i + 1; j < nums.size(); ++j) {
if(nums[i] == nums[j]) cnt++;
}
}
return cnt;
}
};
2. 差的绝对值为 K 的数对数目
(1) 跟第一道题一样,暴力法
class Solution {
public:
int countKDifference(vector<int>& nums, int k) {
int cnt = 0;
for(int i = 0; i < nums.size(); ++i) {
for(int j = i + 1; j < nums.size(); ++j) {
if(abs(nums[i] - nums[j]) == k) cnt++;
}
}
return cnt;
}
};
3. 制造字母异位词的最小步骤数
(1) 用两个哈希表分别存下每个字母出现的次数,再做差
(2) 因为是可以换成任意字母,所以最后结果要除以2。
class Solution {
public:
int minSteps(string s, string t) {
int hashs[26];
int hasht[26];
int ans = 0;
memset(hashs, 0, sizeof(hashs));
memset(hasht, 0, sizeof(hasht));
for(int i = 0; i < s.size(); ++i) {
hashs[s[i]-'a']++;
}
for(int i = 0; i < t.size(); ++i) {
hasht[t[i]-'a']++;
}
for(int i = 0; i < 26; ++i) {
ans = ans + abs(hashs[i] - hasht[i]);
}
return ans/2;
}
};
4. 变位词组
(1) 先用一个二维的哈希表存下每个单词中字母出现的次数
(2) 再遍历一边,如果两个单词的哈希表一样,说明他们互为变位词组。
(3) 考虑到会重复遍历,所以再定义一个数组,存下状态(该单词有没有被加入答案数组)。
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> ans;
int len = strs.size();
if(len <= 1) return {strs};
vector<vector<int>> hash(len, vector<int>(26, 0));
vector<int> visited(len, 0);
int cnt = 0;
//每个单词的哈希表
for(int i = 0; i < len; ++i) {
for(int j = 0; j < strs[i].size(); ++j) {
hash[i][strs[i][j] - 'a']++;
}
}
for(int i = 0; i < len; ++i) {
if(visited[i] == 0) {
ans.push_back({strs[i]});
visited[i] = 1;
}
for(int j = i + 1; j < len; ++j) {
if(check(hash[i], hash[j]) && visited[j] == 0) {
ans.back().push_back(strs[j]);
visited[j] = 1;
}
}
cnt++;
}
return ans;
}
bool check(vector<int>& str1, vector<int>& str2) {
for(int i = 0; i < 26; ++i) {
if(str1[i] != str2[i]) return false;
}
return true;
}
};