二、字符串
1.反转字符串
(1)双指针
一个指向首元素,另一个指向为元素
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
int left = 0, right = len - 1;
while (left < right)
{
auto temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
};
2.整数反转
这题的难点在反转之后的数字会越界。
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0)
{
if (rev < INT_MIN / 10 || rev > INT_MAX / 10)return 0;
int digit = x % 10;
rev = rev * 10 + digit;
x /= 10;
}
return rev;
}
};
3.字符串中的第一个唯一字符
(1)使用find和rfind函数
string的find函数返回第一个对应字符的索引
class Solution {
public:
int firstUniqChar(string s) {
for (auto c : s)
{
if (s.find(c) != s.rfind(c))
{
return s.find(c);
}
}
return -1;
}
};
(2)使用哈希表
分两次遍历,第一次记录次数,第二次查找次数为1的元素索引
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<int, int>temp;
for (auto c : s)
{
temp[c]++;
}
for (int i = 0; i < s.size(); ++i)
{
if (temp[s[i]] == 1)
return i;
}
return -1;
}
};
4.有效字母的异位词
(1)先排序在比较
class Solution {
public:
bool isAnagram(string s, string t) {
sort(s.begin(), s.end());
sort(t.begin(), t.end());
if (s == t)return true;
else return false;
}
};
(2)使用哈希表
class Solution {
public:
bool isAnagram(string s, string t) {
if (s.length() != t.length())return false;
vector<int>htable(26, 0);
for (auto c : s)
{
htable[c - 'a']++;
}
for (auto cc : t)
{
if (htable[cc - 'a'] == 0)return false;
htable[cc - 'a']--;
}
return true;
}
};
5.验证回文串
(1)双指针
class Solution {
public:
bool isPalindrome(string s) {
int left = 0;
int right = s.size() - 1;
while (left < right)
{
while (left < right && !isalnum(s[left]))
{
left++;
}
while (left < right && !isalnum(s[right]))
{
right--;
}
if (tolower(s[left]) != tolower(s[right]))return false;
left++;
right--;
}
return true;
}
};
(2)先筛选,再翻转,最后比较
class Solution {
public:
bool isPalindrome(string s) {
string temp;
for (auto c : s)
{
if (isalnum(c))
{
temp += tolower(c);
}
}
string other(temp.rbegin(), temp.rend());
if (temp == other)return true;
return false;
}
};
6.字符串转换整数(atoi)
(1)自动机
看了一眼官方题解,有点难理解,自己跟着手打了一遍QAQ
首先创建一个状态表,根据读入的字符进行状态转换。
class Automaton
{
string state = "start";
unordered_map<string, vector<string>> table = {
{"start",{"start","signed","in_number","end"}},
{"signed", {"end", "end", "in_number", "end"}},
{"in_number", {"end", "end", "in_number", "end"}},
{"end", {"end", "end", "end", "end"}}
};
int get_col(char c)
{
if (isspace(c))return 0;
if (c == '+' || c == '-')return 1;
if (isdigit(c))return 2;
return 3;
}
public:
int sign = 1;
long long ans = 0;
void get(char c)
{
state = table[state][get_col(c)];
if (state == "in_number")
{
ans = ans * 10 + c - '0';
ans = sign == 1 ? min(ans, (long long)INT_MAX) : min(ans, -(long long)INT_MIN);
}
else if (state == "signed")
{
sign = c == '+' ? 1 : -1;
}
}
};
class Solution {
public:
int myAtoi(string s) {
Automaton automaton;
for (auto c : s)
{
automaton.get(c);
}
return automaton.ans * automaton.sign;
}
};
(2)遍历判断
class Solution {
public:
int myAtoi(string s) {
int sign = 1;//正负号
int i = 0;
int len = s.length();
while (s[i] == ' ')
i++;
if (len == i || (!isdigit(s[i])&&s[i] != '+' && s[i] != '-'))
{
return 0;
}
if (s[i] == '+'|| s[i]== '-')
{
if (s[i] == '-') sign = -1;
i++;
}
long num = 0;
while (i < len && isdigit(s[i]))
{
num = num * 10 + s[i] - '0';
i++;
if (num > INT_MAX && sign == 1)return INT_MAX;
if (num > INT_MAX && sign == -1)return INT_MIN;
}
return num * sign;
}
};
7.实现strStr()
(1)双指针
如果不相等应该回退 i-j-1哦
同样的最后应该返回 i - j。
class Solution {
public:
int strStr(string haystack, string needle) {
if (needle.empty())return 0;
int i = 0, j = 0;
while (i < haystack.size() && j < needle.size())
{
if (haystack[i] != needle[j])
{
i = i - j + 1;
j = 0;
}
else
{
i++;
j++;
}
}
if (j == needle.size())return i - j;
return -1;
}
};
(2)kmp算法
class Solution {
public:
int strStr(string haystack, string needle) {
int n = haystack.size(), m = needle.size();
if (m == 0) {
return 0;
}
vector<int> pi(m);
for (int i = 1, j = 0; i < m; i++) {
while (j > 0 && needle[i] != needle[j]) {
j = pi[j - 1];
}
if (needle[i] == needle[j]) {
j++;
}
pi[i] = j;
}
for (int i = 0, j = 0; i < n; i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = pi[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == m) {
return i - m + 1;
}
}
return -1;
}
};
8.外观数列
pos - start 是重复次数。
class Solution {
public:
string countAndSay(int n) {
string prev = "1";
for (int i = 2; i <= n; ++i)
{
int start = 0;
int pos = 0;
string curr = "";
while (pos < prev.size())
{
while (pos < prev.size() && prev[start] == prev[pos])
{
pos++;
}
curr += to_string(pos - start) + prev[start];
start = pos;
}
prev = curr;
}
return prev;
}
};
9.最长公共前缀
(1)横向比较
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (!strs.size())return "";
string prefix = strs[0];
int len = strs.size();
for (int i = 1; i < len; ++i)
{
prefix = longest(prefix, strs[i]);
if (prefix.empty())break;
}
return prefix;
}
string longest(const string& s1, const string& s2)
{
int len = min(s1.size(), s2.size());
int i = 0;
while (i < len && s1[i] == s2[i])
{
++i;
}
return s1.substr(0, i);
}
};
(2)纵向比较
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty())return "";
int len = strs[0].size();
int Len = strs.size();
for (int i = 0; i < len; ++i)
{
char c = strs[0][i];
for (int j = 1; j < Len; ++j)
{
if (i == strs[j].size() || strs[j][i] != c)
{
return strs[0].substr(0, i);
}
}
}
return strs[0];
}
};