Leetcode--字符串

第344题 反转字符串

解题思路:双指针法,定义两个指针,一个位于首端,一个在尾端,互相交换元素即可,注意循环终止条件。

class Solution {
public:
    void reverseString(vector<char>& s) {
        //求字符串的长度
        int len = s.size();
        //双指针,一个指首端,一个指尾端
        int left = 0,right = len-1;
        while(left<right)
        {
            //开始反转
            int temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            //移动首尾指针
            left++;
            right--;
        }
    }
};

第541题 反转字符串

解题思路:题目整体不难,主要都是细节问题,主要思想是将整个字符串以2*k大小进行分组,然后在每个分组内反转前k个,主要分为以下三种情况:

  • 字符串长度小于k,则将整个链表进行反转

  • 字符串长度大于k,则开始第一组【0~2*k】内前k个进行反转

  • 当执行到最后一个分组的时候,判断当前剩余长度是否大于k若是,继续进行前k个反转,否则,将剩余部分全部反转。

class Solution {
public:
    void reverseString(string& s,int begin,int end) {
        //双指针,一个指首端,一个指尾端
        int left = begin,right = end-1;
        while(left<right)
        {
            //开始反转
            int temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            //移动首尾指针
            left++;
            right--;
        }
    }
    string reverseStr(string s, int k) {
        int len = s.size();
        //当字符串长度小于k,全部反转
        if (len < k)
        {
            reverseString(s, 0, len);
            return s;
        }
        else
        {
            int i = 0;
            while (i < len)
            {
                int r_len = len - i;//右边剩余长度
                //当剩余字符不足2*k个,即最后一个分组
                //也分两种情况,第一种情况是剩余长度小于k,第二种情况是剩余长度大于k但是小于2*k;
                if (r_len < k)
                {
                    reverseString(s, i, len);
                    return s;
                }
                else
                    reverseString(s, i, i + k);
                i += k * 2;
            }
            return s;
        }
    }
};

剑指offer 05 替换空格

解题思路:首先要明确"%20"不能一下子直接替换空格,因此原字符串需要扩容。采用双指针思想,从后往前开始遍历。为什么要从后向前填充,从前向后填充不行么?从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素向后移动。很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。这么做有两个好处:

  • 不用申请新数组。

  • 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

class Solution {
public:
    string replaceSpace(string s) {
        int len = s.size();
        //统计空格个数
        int count = 0;
        for (int i = 0; i < len; i++)
            if (s[i] == ' ')
                count++;
        //给s扩充空间,原来的''可以被%取代,但是字符2和0还需要重新给分配空间
        s.resize(len + count * 2);
        int newlen = s.size();
        //从后向前遍历,并且使用双指针,一个指原字符串尾,一个指新字符串尾(事实上物理空间是同一块)
        for (int i = newlen - 1, j = len - 1; j < i; i--, j--)
        {
            //没遍历到空格时,一个一个向后挪
            if (s[j] != ' ')
                s[i] = s[j];
            else
            {
                s[i] = '0';
                s[i - 1] = '2';
                s[i - 2] = '%';
                i -= 2;//填充完要向前挪两步
            }
        }
        return s;
    }
};

第151题 反转字符串中的单词

解题思路:先移除多余空格,再将整个字符串反转,最后将每个单词反转。

class Solution {
public:
    void reverse(string& s, int start, int end) 
        { //翻转,区间写法:左闭右闭 []
            for (int i = start, j = end; i < j; i++, j--) 
                swap(s[i], s[j]);
        } 
    string reverseWords(string s) {
        //三步走:先删除字符串中多余的空格;再直接交换字符(交换完单词是反的);对单词进行反转
        //第一步:移除多余空格(双指针法)
        int slow = 0;
        for (int first = 0; first < s.size(); ++first) 
        { 
            if (s[first] != ' ')
            { //遇到非空格就处理,即删除所有空格。
                if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
                while (first < s.size() && s[first] != ' ') { //补上该单词,遇到空格说明单词结束。
                    s[slow++] = s[first++];
                }
            }
        }
        s.resize(slow); //slow的大小即为去除多余空格后的大小。
        int len = s.size();
        //第二步:将整个字符串逆转
        reverse(s, 0, len - 1);
        //第三步:将逆序的单词正过来
        int start = 0;
        for (int i = 0; i <= len; i++)
        {
            if (i == len || s[i] == ' ')//到达一个单词的尾部,则开始反转
            {
                reverse(s, start, i - 1);
                //重新移动start
                start = i + 1;
            }
        }
        return s;
    }
};

剑指offer58-Ⅱ 左旋转字符串

解题思路:更上面的题类似,先部分反转,再整体反转。

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        //该函数传的是地址
        //前k个反转
        reverse(s.begin(), s.begin() + n);
        //后n-k个反转
        reverse(s.begin() + n, s.end());
        //整体反转
        reverse(s.begin(), s.end());
        return s;
    }
};

第28题 找出字符串中第一个匹配项的下标

解题思路:滑动窗口,每次在haystack 上截取needle 长度的子串,比较是否相等,若找到相等的,直接返回下标,若遍历结束,返回-1。

class Solution {
public:
    bool isequal(string haystack, int start, int end, string needle)
{
    for (int i=start,j=0;i<end;i++,j++)
    {
        if (haystack[i] != needle[j])
            return false;
    }
    return true;
}
    int strStr(string haystack, string needle) {
        //滑动窗口,窗口大小为needle.size()
        int len = needle.size();
        for (int i = 0,j = i+len;j<=haystack.size(); i++,j++)
        {
            //判断当前窗口和needle是否相等
            if (isequal(haystack, i, j, needle))
                return i;
        }
        return -1;
    }
};

还有一个KMP算法专用来,之后单独写一篇文章来学习一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值