leetcode242——有效的字母异位词
题目描述:
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
算法思想:
计算两个字符串中所有出现字母的频率,若完全相等即为字母异位词。
算法实现:
bool isAnagram(string s, string t) {
//若两个字符串长度不等一定不为字母异位词
int n = s.size(), m = t.size();
if(n != m) return false;
int hash[26];
//计算字符串s的字母频率
for(int i=0;i<n;i++) hash[s[i]-'a']++;
//计算两个字符串的字母频率差
for(int i=0;i<m;i++) hash[t[i]-'a']--;
//若有字母频率差不为0,即不是字母异位词
for(int i=0;i<26;i++){
if(hash[i]!=0) return false;
}
return true;
}
leetcode438——找到字符串中所有字母异位词
题目描述:
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab" 输出: [0,1,2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
算法思想:
若字符串s的长度小于p一定不存在。先从头开始遍历字符串s与字符串p等长的部分的字母频率,若完全相等即为一个字母异位词,然后后移一位比较下一个等长字符串与字符串的字母频率,直至比较到s的末尾等长字符串。
算法实现:
vector<int> findAnagrams(string s, string p) {
int slen = s.size(), plen = p.size();
if(slen<plen) return vector<int>();
vector<int> nums;
vector<int> sfreq(26,0);
vector<int> pfreq(26,0);
//记录下s从头开始的与p等长的字符串的字母频率与p的字母频率
for(int i=0;i<plen;i++){
sfreq[s[i]-'a']++;
pfreq[p[i]-'a']++;
}
//从开头第一个等长字符串比较到末尾的等长字符串
for (int i = 0; i <= slen - plen; i++) {
if (sfreq == pfreq) nums.emplace_back(i);
if(i<slen-plen){
/*下一个等长字符串为去头字母加尾字母,频率数组只需头字母的频率-1,
加入新的尾字母频率+1*/
sfreq[s[i]-'a']--;
sfreq[s[i+plen]-'a']++;
}
}
return nums;
}
leetcode454——四数相加
题目描述:
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 输出:1
算法思想:
将四个数组进行分组,2个一组,分别将每组的和与凑成该和有几种搭配存放在map的key与value中。最后检查和为0的个数。
算法实现:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
//分别存放每组的和
unordered_map<int,int> map1,map2;
int count=0;
for(int num1:nums1){
for(int num2:nums2){
map1[num1+num2]++;
}
}
for(int num3:nums3){
for(int num4:nums4){
map2[num3+num4]++;
}
}
int target;
for(auto &it:map1){
//在第二组找与第一组和为0的组合(first存放和,second存放构成这种和有多少种搭配)
target=0-it.first;
if(map2.find(target)!=map2.end()) count=count+it.second*map2[target];
}
return count;
}