鸽了好久,终于再次开始刷题,以后不能这么懒惰了!
话不多说直接开始
这次题有点多,分两篇文章写
①反转字符串
题目大意
给定一个字符序数组,要求原地将其所有字符反转过来,并返回该数组
思路讲解
没啥好解释的,简单的双指针,两个指针一起向中间靠近
源代码
class Solution {
public:
void reverseString(vector<char>& s) {
int right = s.size() - 1;
int left = 0;
while(left<right)
{
int temp = s[left];
s[left] = s[right];
s[right] = temp;
--right;
++left;
}
}
};
②整数反转
题目大意
给一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
思路讲解
还是比较麻烦的,整体思路是将每一个数字都单独存到字符中,然后在反转时先记录符号,再判断是否溢出
麻烦的地方是,当该值的位数为十位(两边的最值也是十位),且最高位为2时,需要具体判断是否溢出。这里就要连减两次,防止在中间运算的时候出现溢出现象
源代码
class Solution {
public:
int reverse(int x) {
if(x == 0 || x == -2147483648)
{
return 0;
}
bool symbol = true;
if(x < 0)
{
symbol = false;
}
int num[15];
int cnt = 0;
x = abs(x);
while(x != 0)
{
++cnt;
num[cnt] = x % 10;
x = x / 10;
}
int res = 0;
int now = 1;
//总位数不足10位,一定不会溢出
if(cnt <= 9)
{
while(now <= cnt)
{
res = res * 10;
res += num[now];
++now;
}
if(symbol)
{
return res;
}
return (-1*res);
}
//一共十位数,可能会溢出
else
{
//最高位大于等于三,一定溢出
if(num[1] >= 3)
{
return 0;
}
//10位但不可能溢出
if(num[1] < 2)
{
while(now <= cnt)
{
res = res * 10;
res += num[now];
++now;
}
if(symbol)
{
return res;
}
return (-1*res);
}
//10位可能溢出
now = 2;
while(now <= cnt)
{
res = res * 10;
res += num[now];
++now;
}
//正数情况下
if(symbol)
{
int mx = 2147483647;
mx = mx - res;
mx = mx - num[1]*1000000000;
if(mx < 0)
{
return 0;
}
return (res+num[1]*1000000000);
}
else
{
int mx = 2147483647;
mx = mx - res;
mx = mx - num[1]*1000000000;
//因为负数绝对值的最大值大1
if(mx < -1)
{
return 0;
}
return (-1 * (res+num[1]*1000000000));
}
}
}
};
③字符串中的第一个唯一字符
题目大意
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1
思路讲解
这里利用数据库中的思想,利用一个主键,关联起三个不同的标记。
letter是记录字母出现的先后,under记录该字母第一次出现的下标,time记录该字母出现的次数
由letter来串联起来
源代码
class Solution {
public:
int firstUniqChar(string s) {
vector<int> letter(30);
vector<int> time(30);
vector<int> under(30);
int cnt = 0;
for(int i=0;i<s.size();++i)
{
if(time[s[i]-'a'] == 0)
{
letter[cnt] = (s[i]-'a');
under[letter[cnt]] = i;
++cnt;
}
++time[s[i]-'a'];
}
if(cnt == 0)
{
return -1;
}
--cnt;
for(int i=0;i<=cnt;++i)
{
if(time[letter[i]] == 1)
{
return under[letter[i]];
}
}
return -1;
}
};
④有效的字母异位词
题目大意
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
思路讲解
若为字母异位词,则一定字母数相同。则可以先一起遍历两个字符串,然后记录下每个字母出现的次数,最后再对比一下即可
源代码
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size())
{
return false;
}
vector<int> first(30);
vector<int> second(30);
int n = s.size();
for(int i=0;i<n;++i)
{
++first[s[i]-'a'];
++second[t[i]-'a'];
}
for(int i=0;i<26;++i)
{
if(first[i]!=second[i])
{
return false;
}
}
return true;
}
};
⑤验证回文串
题目大意
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写
思路讲解
回文字符串的升级版,这里需要额外判断空格和记录字母大小写
用到两个重要函数
isalnum(char c),判断c否是字母或数字
isalpha(char c),判断c是否是字母
这个地方有个有趣的小插曲,因为要忽略大小写,则需要通过±32(因为ascii码)来忽略,可能会出现数字和字母正好差32的特殊情况(有个样例卡了我一次),所以需要额外的进行判断和留心!
源代码
class Solution {
public:
bool isPalindrome(string s) {
int left = 0;
int right = s.size() - 1;
bool flag = false;
while(left < right)
{
flag = false;
if(!isalnum(s[left]))
{
++left;
flag = true;
}
if(!isalnum(s[right]))
{
--right;
flag = true;
}
if(!flag)
{
if(s[left] == s[right] || s[left] == s[right]+32 || s[left] == s[right]-32)
{
if(isalpha(s[left]) && !isalpha(s[right]))
{
return false;
}
if(!isalpha(s[left]) && isalpha(s[right]))
{
return false;
}
--right;
++left;
}
else
{
return false;
}
}
}
return true;
}
};