今天開始刷字符串方面的算法題了。當然有些題目太簡單了我就不拿出來了。
還是老規矩,一篇三題。前兩三篇好像忘記把題目名字放出來了,這次記住了。
第一題:字符串中第一個單身字符
給定一個字符串,找到它的第一個不重複的字符,並返回它的索引。如果不存在,則返回 -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容器會根據鍵值自動排序。
- 哈希表無論如何要掌握,儘快,希望明天就能馬上學以致用。