LeetCode初级算法学习——字符串(一)

鸽了好久,终于再次开始刷题,以后不能这么懒惰了!
话不多说直接开始
这次题有点多,分两篇文章写

①反转字符串

题目大意

给定一个字符序数组,要求原地将其所有字符反转过来,并返回该数组

思路讲解

没啥好解释的,简单的双指针,两个指针一起向中间靠近

源代码
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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mac-lengs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值