首页 > 其他分享 >手撕代码之字符串

手撕代码之字符串

时间:2023-08-29 11:34:49浏览次数:34  
标签:string int res 代码 ++ str 字符串 size



文章目录

  • 一、反转字符串中的每一个单词(leetcode 151、557)
  • 二、多个字符串的最长公共前缀(leetcode 14)
  • 三、字符串转整数(leetcode 8)
  • 四、N位数字串删除K个数字,使剩下的数字串最小(leetcode 402)
  • 五、回文子串的个数(Leetcode 647)
  • 六、最长无重复字符的子串(leetcode 3)
  • 七、最长回文子串(leetcode 5)
  • 八、查找子串的位置(leetcode 28)


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

手撕代码之字符串_回文子串


  思路:利用string流输入将原字符串按空格分割,然后去除尾部空格整体翻转字符串,最后遍历字符串进行部分翻转

class Solution {
public:
    string reverseWords(string s) {
    	stringstream ss(s);
	    string token, str;
        // 利用string流输入将原字符串按空格分割
    	while (ss >> token) {
	    	str = str + token + " ";
    	}
        // 去除尾部空格
        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)

手撕代码之字符串_子串_02


  思路:假设第一个字符串为最长前缀,比较当前最长前缀和下一个字符串的公共部分,不断更新公共前缀。

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string res = "";
        if (!strs.empty()){
            // 假设第一个为最长前缀,以后再不断更新公共前缀
            res = strs[0];
            for (int i = 1; i < strs.size(); ++i){
                // 比较当前最长前缀和下一个字符串的公共部分
                int len = 0;
                for (int j = 0; j < res.size() && j < strs[i].size(); ++j){
                    if (strs[i][j] == res[j])
                        len++;
                    else
                        break;
                }
                // 更新最长公共前缀
                res = res.substr(0, len);
            }
        }
        return res;
    }
};

三、字符串转整数(leetcode 8)

手撕代码之字符串_子串_03


  思路:先过滤前面的空格,然后判断正负号以及首字符是不是数字,最后判断越界

class Solution {
public:
    int myAtoi(string str) {
        int i = 0, flag = 1;
        // 过滤前面的空格
        while (str[i] == ' ')
            i++;
        // 判断正负号以及首字符是不是数字
        if (str[i] == '-'){
            i++;
            flag = -1;
        }
        else if (str[i] == '+'){
            i++;
        }
        else if (!isdigit(str[i]))
            return 0;
        long long int res = 0;
        for (; i < str.size(); ++i){
            if (isdigit(str[i])){
                res = res * 10 + (str[i] - '0');
                // 判断整数越界
                if (res > INT_MAX && flag == 1)
                    return INT_MAX;
                if (res > INT_MAX && flag == -1)
                    return INT_MIN;                
            }
            else
                break;
        }
        return res * flag;
    }
};

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

手撕代码之字符串_子串_04


手撕代码之字符串_回文子串_05

class Solution {
public:
    string removeKdigits(string num, int k) {
        // 构建一个非递减栈stkstk:从左往右遍历数字numnum,依次进栈;每个数字xx进栈前检查
        // 是否比栈顶,是的话弹掉栈顶;全部数字一共有k次机会弹栈顶(相当于,最多在这一步删掉k个数字)。
        stack<char> stk;
        for (auto x : num) {
            while (!stk.empty() && stk.top() > x && k) {
                stk.pop();
                k--;
            }
            stk.push(x);
        }
        // 如果k次(删数字的)机会没有用完,则弹出栈顶直到stkstk中剩余stk.size()−k个数字
        while (k--)
            stk.pop();
        string res;
        // 将stkstk倒出来再reverse,统计前导0的个数,并以此返回对应的值
        while (!stk.empty()) {
            res += stk.top();
            stk.pop();
        }
        reverse(res.begin(), res.end());
        int i = 0;
        while (i < res.size() && res[i] == '0')
            i++;
        if (i == res.size())
            return "0";
        else
            return string(res.begin()+i, res.end());
    }
};

五、回文子串的个数(Leetcode 647)

手撕代码之字符串_回文子串_06


  思路:以字符串中的每一个字符都当作回文串中间的位置,然后向两边扩散,每当成功匹配两个左右两个字符,结果res自增1,然后再比较下一对。注意回文字符串有奇数和偶数两种形式,如果是奇数长度,那么i位置就是中间那个字符的位置,所以我们左右两遍都从i开始遍历;如果是偶数长度的,那么i是最中间两个字符的左边那个,右边那个就是i+1,这样就能覆盖所有的情况。

class Solution {
public:
    int countSubstrings(string s) {
        if (s.empty()) return 0;
        int res = 0;
        // 分别考虑长度为奇数和偶数的情况
        for (int i = 0; i < s.size(); ++i) {
            countSubstringsCore(s, i, i, res);
            countSubstringsCore(s, i, i+1, res);
        }
        return res;
    }
    // 以字符串中的每一个字符都当作回文串中间的位置,然后向两边扩散,每当成功匹配两个左右两个字符,
    // 结果res自增1,然后再比较下一对
    void countSubstringsCore(string s, int i, int j, int &res) {
        while (i >= 0 && j < s.size() && s[i] == s[j]) {
            --i;
            ++j;
            ++res;
        }
    }
};

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

手撕代码之字符串_回文子串_07


  思路:滑动窗口加哈希,即每遍历一个元素就记录下它出现的次数,如果当前元素计数大于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)

手撕代码之字符串_子串_08


  思路:以某一个字符为中心向两边扩散寻找回文子串,用maxLen记录长度,如果子串是奇数,则以当前位置为中心,如果子串是偶数,则以当前位置和下一个位置共同作为中心

class Solution {
public:
    string longestPalindrome(string s) {
        int start = 0, maxLen = 0;
        // 以某一个字符为中心向两边扩散寻找回文子串
        for (int i = 0; i < s.size(); ++i){
            // 如果子串是奇数,则以当前位置为中心
            longestPalindromeCore(s, i, i, start, maxLen);
            // 如果子串是偶数,则以当前位置和下一个位置共同作为中心
            longestPalindromeCore(s, i, i+1, start, maxLen);
        }
        return s.substr(start, maxLen);
    }
    void longestPalindromeCore(string s, int left, int right, 
                               int &start, int &maxLen){
        while (left >= 0 && right < s.size() && s[left] == s[right]){
            --left;
            right++;
        }
        // start记录回文子串开始的地方,maxLen记录长度
        if (maxLen < right - left - 1){
            start = left + 1;
            maxLen = right - left - 1;
        }
    }
};

八、查找子串的位置(leetcode 28)

手撕代码之字符串_字符串_09

class Solution {
public:
    int strStr(string haystack, string needle) {
        if (needle == "")
            return 0;
        // i用于遍历haystack,j用于遍历needle,cnt用于计算相同字符的数量
        int j = 0, cnt = 0;
        for (int i = 0; i < haystack.size(); ++i){
            if (haystack[i] == needle[j]){
                cnt++;
                // 如果j遍历到头了则说明needle是haystack的子串
                if (j == needle.size() - 1)
                    return i-cnt+1;
                j++;
            }
            // 重置i,j,cnt
            else {
                i -= cnt;
                j = 0;
                cnt = 0;
            }
        }
        return -1;
    }
};


标签:string,int,res,代码,++,str,字符串,size
From: https://blog.51cto.com/u_6526235/7273892

相关文章

  • 手撕代码之栈和队列
    文章目录一、括号匹配(leetcode20)二、最小栈(leetcode155)三、两个栈实现一个队列(leetcode232)一、括号匹配(leetcode20)classSolution{public:boolisValid(strings){if(s.empty())returntrue;stack<char>stk;stk.push(s[0]......
  • 手撕代码之二叉树
    文章目录一、根据排序数组构造二叉搜索树(leetcode108)二、根据前序遍历和中序遍历构造二叉树(leetcode105)三、二叉树的非递归遍历(leetcode94、144、145)四、二叉树中和为某一值的路径(leetcode112)五、二叉树的最大深度(leetcode104)六、二叉树的层次遍历(leetcode102)七、判断两个二......
  • 一次html中展示xml字符串不显示问题记录
    现象在html中展示xml字符串时不显示原因展示xml字符串时代码为document.getElementById("demoPre").innerHTML=xml字符串,此时xml并不会作为文本显示,而是将xml节点嵌入html中,而浏览器又不能解析xml节点,最后就不显示解决办法修改代码为document.getElementById("demoPre")......
  • Java代码审计之目录穿越
    一、目录穿越漏洞1、什么是目录穿越所谓的目录穿越指利用操作系统中的文件系统对目录的表示。在文件系统路径中,".."表示上一级目录,当你使用"../"时,你正在引用当前目录的上一级目录。如果你使用"../../",你实际上在两次".."的基础上,再次引用上一级目录,从而返回到上两级目录。......
  • Oracle 字符串相似度查询
    Oracle函数: SYS.UTL_MATCH.EDIT_DISTANCE_SIMILARITY(str,patternStr)--Oracle查询字符串相似度函数SELECTDISTINCTe.EQP_GROUP,SYS.UTL_MATCH.EDIT_DISTANCE_SIMILARITY(e.EQP_GROUP,'LARF')xsdFROMIMP_AREA_EQPGROUP_MAPPINGeORDERBYXSDDESC查询结果: ......
  • r'\1'表示替换字符串中的第一个捕获组 将匹配到的字符串被替换为第一个捕获组的内容
    请解释pd.Series.str.replace(pat=r'(?i)(.*)-h.*',#(.*)表示一个捕获组repl=r'\1',#将匹配到的字符串被替换为捕获组的内容regex=True)中r'\1'的作用在pd.Series.str.replace()函数中,r'\1'表示替换字符串中的第一个捕获组......
  • Vscode如何如何显示vue代码提示
    Vscode使用版本 下载这个插件 ......
  • 5.1.29 远程代码执行漏洞
    ThinkPHP55.0.22/5.1.29远程代码执行漏洞漏洞描述Thinkphp是一个国内轻量级的开发框架。由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞。验证方式直接访问http://your-ip:8080/index.php?s=/Index/\thi......
  • Bash 字符串处理
    一、截取语法格式说明${string:start:length}从string字符串的左边第start个字符开始,向右截取length个字符。${string:start}从string字符串的左边第start个字符开始截取,直到最后。${string:0-start:length}从string字符串的右边第start个字......
  • python代码画爱心❤(海龟)
    importturtle#设置标题turtle.title("蜜蜂的程序")turtle.st()#显示海龟print(turtle.position())turtle.color("red","pink")turtle.begin_fill()#填充前turtle.left(90)turtle.penup()turtle.pendown()turtle.circle(60,180)turtle.circle(18......