手撕练习之字符串

一、反转字符串中的每一个单词(leetcode 151、557)

在这里插入图片描述
思路:
1.利用string流输入将原字符串按空格分割,
2.然后去除尾部空格,
3.整体翻转字符串,
4.最后遍历字符串进行部分翻转。

class Solution {
public:
    string reverseWords(string s) {
    	stringstream ss(s);
	    string token, str;
        // 利用string流输入将原字符串按空格分割
    	while (ss >> token) {
	    	str = str + token + " ";
    	}
    	// 检查字符串是否为空
        if(str.empty())
            return str;
        // 去除尾部空格
        int sz = str.size() - 1;
        while (str[sz] == ' ') {
		    str.pop_back();
		    sz--;
	    }
        // 先整体翻转
        reverse(str.begin(), str.end());
        for (int i = 0, j = 0; i <= str.size(); ++i){
            // 部分翻转
            if (i == str.size() || str[i] == ' '){
                reverse(str.begin()+j, str.begin()+i);
                j = i + 1;
            }
        }
        return str;
    }
};

二、多个字符串的最长公共前缀(leetcode 14)

在这里插入图片描述
思路:对于多个字符串,顺序比较每个字符串的字符是否相等,如果相等比较下一个字符;如果不相等则输出之前已比较相等的字符。

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if (!strs.size()) {
            return "";
        }
        // 以第一个字符串为标杆
        int length = strs[0].size();
        int count = strs.size();
        // 控制遍历字符串的元素
        for (int i = 0; i < length; ++i) {
            char c = strs[0][i];
            // 控制遍历每个字符串
            for (int j = 1; j < count; ++j) {
            	// 若某个字符串已遍历完 或 字符不相同 则输出
                if (i == strs[j].size() || strs[j][i] != c) {
                    return strs[0].substr(0, i);
                }
            }
        }
        return strs[0];
    }
};

三、N位数字串删除K个数字,使剩下的数字串最小(leetcode 402)

在这里插入图片描述
在这里插入图片描述
思路:尽可能让最高位小,最高位相同的情况下尽可能让次高位小,所以应该维护一个非递减栈
1.构建一个非递减栈(单调栈思想):从左到右遍历数字num,依次进栈;每个数字进栈前检查是否比栈顶小,是的话弹掉栈顶,然后再循环跟栈顶比较,直到不比栈顶小或栈空了。出栈次数为K次。
2.如果K次(删数字)没用完,则依次弹出栈顶,删除剩下次数数字。
3.取出栈中数字,剔除前面的0.

class Solution {
public:
    string removeKdigits(string num, int k) {
        int len = num.size();
        if(k<=0)
            return num;
        if(k>=len)
            return "0";
        vector<char> vt;
        //构建一个非递减栈(单调栈思想):从左到右遍历数字num,依次进栈;每个数字进栈前检查是否
        //比栈顶小,是的话弹掉栈顶,然后再循环跟栈顶比较,直到不比栈顶小或栈空了。出栈次数为K次。
        for (auto x : num) {
            while (!vt.empty() && vt.back() > x && k) {
                vt.pop_back();
                k--;
            }
            vt.push_back(x);
        }
        //如果K次(删数字)没用完,则依次弹出栈顶,删除剩下次数数字。
        while(k>0){
            vt.pop_back();
            k--;
        }
        string res;
        int i = 0;
        //取出栈中数字,剔除前面的0.
        for(;i<vt.size() && vt[i]=='0';++i);
        for(;i<vt.size();++i){
            res += vt[i];
        }
        if (res.empty())
            return "0";
        return res;
    }
};

四、回文子串的个数(leetcode 647)

在这里插入图片描述
思路:分两种情况:

  • 1.奇数长子回文串。以字符串中的每一个字符都当作回文串中间的位置,然后向两边扩散,每当成功匹配两个左右两个字符,结果count自增1,然后再比较下一对。
  • 2.偶数长子回文串。如果是偶数长度的,那么i是最中间两个字符的左边那个,右边那个就是i+1,这样就能覆盖所有的情况。
class Solution {
public:
    int countSubstrings(string s) {
        int len = s.size();
        int count = 0;
        for(int i = 0;i<len;i++)
        {
            // 奇数长度的子回文串,中间元素相同后,左右分别向外扩一位再比较,
            //这依次比较是否相同,不相同终止
            int left = i,right = i;
            while(left >= 0 && right < len && s[left] == s[right])
            {
                count++;
                left--;
                right++;
            }
            // 偶数长度的子回文串,中间俩元素相同后,左右分别向外扩一位再比较,
            //i是最中间两个字符的左边那个,右边那个就是i+1
            left = i;
            right = i+1;            
            while(left >= 0 && right < len && s[left] == s[right])
            {
                count++;
                left--;
                right++;
            }
        }
        return count;
    }
};

五、最长无重复字符子串(leetcode 3)

在这里插入图片描述
思路:双指针加哈希,即每遍历一个元素就记录下它出现的次数,如果当前元素计数大于1,则向前找到与当前字符相同的字符,i记录的是这个相同字符的下一个字符,它们之间的区间长度就是无重复子串的长度,然后不断更新最大值。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> ump;
        int maxlen = 0;
        for (int i = 0, j = 0; j < s.size(); ++j){
        	// 每遍历一个元素就记录下它出现的次数
            ump[s[j]]++;
            // 向前找到与当前字符相同的字符,同时抹去相同字符前的字符计数
            // i记录的是这个相同字符的下一个字符
            while (ump[s[j]] > 1) 
                ump[s[i++]]--;
            maxlen = max(maxlen, j - i + 1);
        }
        return maxlen;
    }
};

六、最长回文子串(leetcode 5)

在这里插入图片描述
思路:以某一个字符为中心向两边扩散寻找回文子串,记录长度,最左端

  • 如果子串是奇数,则以当前位置为中心,
  • 如果子串是偶数,则以当前位置和下一个位置共同作为中心。
public:
    string longestPalindrome(string s) {
        int len = s.size();
        int maxl = 0, start = 0;
        for(int i = 0;i < len; i++)
        {
        	// 如果子串是奇数,则以当前位置为中心
            int l = i, r = i, lt = 0;
            while(l >= 0 && r < len && s[l] == s[r])
            {
                l--;
                r++;
            }
            lt = r-l-1;
            if(lt > maxl)
            {
                maxl = lt;
                start = l+1;
            }
            // 如果子串是偶数,则以当前位置和下一个位置共同作为中心
            l = i; r = i+1; lt = 0;
            while(l >= 0 && r < len && s[l] == s[r])
            {
                l--;
                r++;
            }
            lt = r-l-1;
            if(lt > maxl)
            {
                maxl = lt;
                start = l+1;
            }
        }
        return s.substr(start, maxl);
    }
};

七、查找子串的位置(实现strStr())(leetcode 28)

在这里插入图片描述

class Solution {
public:
    int strStr(string haystack, string needle) {
        int lenh = haystack.size();
        int lenn = needle.size();
        for(int i = 0; i <= (lenh-lenn); i++)
        {
            int j = 0, it = i;
            while(j < lenn && haystack[it] == needle[j])
            {
                j++;
                it++;
            }
            // 如果j遍历到头了则说明needle是haystack的子串
            if(j == lenn)
                return i;
        }
        return -1;
    }
};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值