今天开始刷字符串方面的算法题了。当然有些题目太简单了我就不拿出来了。
还是老规矩,一篇三题。前两三篇好像忘记把题目名字放出来了,这次记住了。
第一题:字符串中第一个单身字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = “leetcode”
返回 0.
s = “loveleetcode”,
返回 2.
注意事项:您可以假定该字符串只包含小写字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第二题:有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:
输入: s = “rat”, t = “car”
输出: false
说明:
你可以假设字符串只包含小写字母。
进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-anagram
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第三题:验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
示例 2:
输入: “race a car”
输出: false
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-palindrome
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的题解(1)
看到这题呢,我又想巩固一下我的映射表方面的知识,所以我一开始是这样打算的:
看,本来是多好的思路啊,但是做的过程中发现map会根据键值大小自动排序。。。
我也不记得之前是谁跟我说map不提供自动排序的。。。
那就很尴尬了,于是我就决定暴力破解了。
但是也不是纯粹的暴力破解,还是有点技巧性的。
看一下代码:
int firstUniqChar(string s)
{
//如果是空的
if (s.size() == 0)
return -1;
vector<char> temp;
string::iterator it1, it2;
vector<char>::iterator vit;
int flag;
int count = 0;
for (it1 = s.begin(); it1 != s.end(); it1++)
{
flag = 1;
for (vit = temp.begin(); vit != temp.end(); vit++)
{
if (*it1 == *vit)
{
flag = 0;
count++;
break;
}
}
if (flag == 0)
continue;
it2 = it1;
it2++;
for (; it2 != s.end(); it2++)
{
//如果中间截胡了
if (*it1 == *it2)
{
temp.push_back(*it1);
flag = 0;
break;
}
}
if (flag == 0) //如果截胡了
{
count++;
continue;
}
//如果没有截胡
return count;
}
//如果一个都没
return -1;
}
我的题解(2)
这个简单的要死,只要不涉及位序,映射表就好了。图我就不画了。
bool isAnagram(string s, string t)
{
map<char, int> s_str,t_str;
int count = 0;
if(s.size() != t.size())
return false;
if (s.size() == 0)
return true;
for (int i = 0; i < s.size(); i++)
{
s_str[s[i]] += 1;
t_str[t[i]] += 1;
}
if (s_str.size() != t_str.size())
return false;
map<char, int>::iterator s_it = s_str.begin();
map<char, int>::iterator t_it = t_str.begin();
while (s_it != s_str.end())
{
if (s_it->first != t_it->first || s_it->second != t_it->second)
return false;
s_it++;
t_it++;
}
return true;
}
我的题解(3)
这个第三题倒是好好的给我上了一课,倒不是说它很难,相反,还挺简单的。不过我发现迭代器好像没办法获取当前指向位置的下标吧!!!那就比较尴尬了,因为这题是不用遍历到尾的,只需要遍历到中间。
思路就是这么简单以至于官方都不给答案了。
那就看一下我的吧。
bool isPalindrome(string s)
{
string t;
int a=0,b=0;
int sz = s.size();
//将字符串重组
for (;a<sz; a++)
{
b = s[a];
if ((97 <= b && 122 >= b) || (65 <= b && 90 >= b) || (48<=b && 57>=b))
t.push_back(s[a]);
}
//头尾比对
sz = t.size();
for (a = 0,b = sz-1;a<b;a++,b--)
{
if (t[a] != t[b])
{
//要排掉数字
if (57 >= t[a] || 57 >= t[b])
return false;
if (((t[a] - 32) != t[b]) && ((t[a] + 32) != t[b]))
return false;
}
}
return true;
}
官方题解(1)
方法一: 线性时间复杂度解法
这道题最优的解法就是线性复杂度了,为了保证每个元素是唯一的,至少得把每个字符都遍历一遍。
算法的思路就是遍历一遍字符串,然后把字符串中每个字符出现的次数保存在一个散列表中。这个过程的时间复杂度为 O(N)O(N),其中 NN 为字符串的长度。
接下来需要再遍历一次字符串,这一次利用散列表来检查遍历的每个字符是不是唯一的。如果当前字符唯一,直接返回当前下标就可以了。第二次遍历的时间复杂度也是 O(N)O(N)。
作者:LeetCode
链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string/solution/zi-fu-chuan-zhong-de-di-yi-ge-wei-yi-zi-fu-by-leet/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
说多了都是泪,散列表果然比映射表好用,进化了就是不一样。看来这次说什么也得会用哈希表!!!
class Solution {
public int firstUniqChar(String s) {
HashMap<Character, Integer> count = new HashMap<Character, Integer>();
int n = s.length();
// build hash map : character and how often it appears
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
count.put(c, count.getOrDefault(c, 0) + 1);
}
// find the index
for (int i = 0; i < n; i++) {
if (count.get(s.charAt(i)) == 1)
return i;
}
return -1;
}
}
> 作者:LeetCode
> 链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string/solution/zi-fu-chuan-zhong-de-di-yi-ge-wei-yi-zi-fu-by-leet/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
官方题解(2)
方法一:排序
算法:
通过将 ss 的字母重新排列成 tt 来生成变位词。因此,如果 TT 是 SS 的变位词,对两个字符串进行排序将产生两个相同的字符串。此外,如果 ss 和 tt 的长度不同,tt 不能是 ss 的变位词,我们可以提前返回。
作者:LeetCode
链接:https://leetcode-cn.com/problems/valid-anagram/solution/you-xiao-de-zi-mu-yi-wei-ci-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法二:哈希表
算法:
为了检查 tt 是否是 ss 的重新排列,我们可以计算两个字符串中每个字母的出现次数并进行比较。因为 SS 和 TT 都只包含 A-ZA−Z 的字母,所以一个简单的 26 位计数器表就足够了。
我们需要两个计数器数表进行比较吗?实际上不是,因为我们可以用一个计数器表计算 ss 字母的频率,用 tt 减少计数器表中的每个字母的计数器,然后检查计数器是否回到零。
作者:LeetCode
链接:https://leetcode-cn.com/problems/valid-anagram/solution/you-xiao-de-zi-mu-yi-wei-ci-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我不觉得这题哈希表会比映射表要有优势。
官方题解(3)
应该是太简单而没有题解。
总结
做完这些题呢,应该明白以下几点:
- string串也是STL容器的一种。
- map容器会根据键值自动排序。
- 哈希表无论如何要掌握,尽快,希望明天就能马上学以致用。