leetcode真题+牛客面试真题——字符串汇总:344. 反转字符串 541. 反转字符串 II 05. 替换空格 151. 颠倒字符串中的单词

344. 反转字符串

在这里插入图片描述
请添加图片描述

class Solution {
public:
    void reverseString(vector<char>& s) {
        int size = s.size();
        int last = size - 1;
        for(int i = 0; i < (size+1) / 2; i++){
            char tmp = s[i];
            s[i] = s[last-i];
            s[last-i] = tmp;
        }
    }
};

541. 反转字符串 II

https://leetcode-cn.com/problems/reverse-string-ii/
在这里插入图片描述
这里 i 更新的时候只需要 += 2k,可以节约中间的遍历。

class Solution {
public:
    string reverseStr(string s, int k) {
        for(int i = 0; i < s.size(); i += 2 * k){
            if(i + k < s.size()){
                reverse(s.begin() + i, s.begin() + i + k);
                continue;
            }
            reverse(s.begin() + i, s.end());
        }
        return s;
    }
};

05. 替换空格

https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."

由于字符串的存储类似于数组,都是在连续的区间内对数据进行存取,所以插入数据都要将元素后移对应位置空出来才能赋值,每插入一个元素就要将后面都移动一遍,但是这样的效率不高。所以可以考虑先计算所需的空间大小然后用双指针从后向前对新穿赋值。

把每个空格替换成%20,那么每多一个空格就需要增加两个位置,所以新数组的大小为 s.size() + 2 * count

class Solution {
public:
    string replaceSpace(string s) {
        // 计算当前的空格数 space
         int space = 0;
         for(int i = 0; i < s.size(); i++)
            if(s[i]==' ') space ++;
        int oldSize = s.size();
        // 初始化新数组
        s.resize(s.size() + space * 2);
        int newSize = s.size();
        for(int i = oldSize - 1, j = newSize - 1; i < j; i--){
            if(s[i]!=' '){
                s[j] = s[i];
                j--;
            }else{
                s[j] = '0';
                s[j-1] = '2';
                s[j-2] = '%';
                j -= 3;
            }
        }
        return s;

    }
};

151. 颠倒字符串中的单词

https://leetcode-cn.com/problems/reverse-words-in-a-string/在这里插入图片描述
在这里插入图片描述
这里的做法 空间复杂度为O(1)
请添加图片描述

class Solution {
public:
    // 反转特定区间的字符串
    void reverseArea(string &s,int start,int end){
        for(int i = start, j = end; i < j; i++, j--){
            swap(s[i],s[j]);
        } 
    }
    // 去除字符串中多余的空格
    void removeExtraSpace(string &s){
        int slow = 0, fast = 0;
        // 去除字符串前面的空格
        while(fast < s.size() && s[fast] == ' '){
            fast++;
        }
        // 去除字符串之间多余的空格
        for(; fast < s.size(); fast++){
            //出现重复的空格时(确保fast- 1>0否则出现空指针异常)
            if(fast - 1 > 0 && s[fast - 1] == s[fast] && s[fast] == ' '){
                continue;
            }else{
                s[slow] = s[fast];
                slow ++ ;
            }
        }
        // 去除字符串后面的空格
        if(slow - 1 > 0 && s[slow - 1] == ' '){
            s.resize(slow - 1);
        }else{
            s.resize(slow);
        }
    }

    string reverseWords(string s) {
        removeExtraSpace(s);
        reverseArea(s,0,s.size()-1);
        for(int i = 0; i < s.size(); i++){
            int j = i;
            while(j < s.size() && s[j] != ' ') j++;
            reverseArea(s,i,j-1);
            i = j;
        }
        return s;
    }
};

这道题做完可以做下牛客的 BM83 字符串变形
https://www.nowcoder.com/practice/c3120c1c1bc44ad986259c0cf0f0b80e只是多了一个大写所有单词字符的功能。

class Solution {
public:
    void reverseArea(string &s,int start,int end){
        for(int i = start, j = end; i < j; i++,j--){
            swap(s[i],s[j]);
        }
    }
//  这个函数的功能是在去除空格的同时将字母反转
//	void removeExtraSpace(string &s){
//         int slow = 0, fast = 0;
//         //移除前面的空格
//         while(fast < s.size() && s[fast] == ' ') fast++;
//         // 移除中间多余的空格
//         for(; fast < s.size(); fast ++){
//             if(fast-1 > 0 && s[fast - 1] == ' ' && s[fast]==' ') continue;
//             else {
//                 if(s[fast]>='a' && s[fast]<='z'){
//                     s[slow] = s[fast] - 'a' + 'A';
//                 }else if(s[fast]>='A' && s[fast]<='Z'){
//                     s[slow] = s[fast] - 'A' + 'a';
//                 }else s[slow] = s[fast];
//                 slow ++ ;
//             }
//         }
//         if(slow - 1 > 0 && s[slow - 1]==' ') s.resize(slow - 1);
//         else s.resize(slow);
//     }
    void transfer(string &s){
        for(int i = 0; i < s.size(); i++){
            if(s[i]>='a' && s[i]<='z'){
                    s[i] = s[i] - 'a' + 'A';
            }else if(s[i]>='A' && s[i]<='Z'){
                s[i] = s[i] - 'A' + 'a';
            }
        }
    }
    string trans(string s, int n) {
        // write code here
        //removeExtraSpace(s);
        transfer(s);
        reverseArea(s, 0, s.size()-1);

        for(int i=0;i<s.size();i++){
            int j = i;
            while(j < s.size() && s[j]!=' ') j++;
            reverseArea(s, i, j-1);
            i = j;
        }
        return s;
    }
};

58 - II. 左旋转字符串

https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/
在这里插入图片描述
简易版:先将即将被覆盖的前半段取出来到tmp,后半段前移,把tmp赋给后半段

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        string tmp(n,' ');
        for(int i = 0; i < n; i++) tmp[i] = s[i];
        for(int i = 0, j = n; j < s.size(); i++, j++) s[i] = s[j];
        for(int i = s.size() - n,j = 0; j < tmp.size(); i++,j++) s[i] = tmp[j];
        return s;
    }
};

在这里插入图片描述

KMP:28. 实现 strStr()

https://leetcode-cn.com/problems/implement-strstr/
在这里插入图片描述
在一个串中查找是否出现过另一个串,这是KMP的看家本领,我对KMP的理解可以见下图
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    void getNext(int *next,string &s){
        int i = 0; //初始化前缀的末尾(也表示最长相同前后缀的长度)
        next[0] = 0; 
        for(int j = 1; j < s.size(); j++){ //j表示后缀的末尾,j为next数组赋值
            while(i > 0 && s[j] != s[i]){
                i = next[i - 1];
            }
            if(s[j] == s[i]) i++; //前后缀末尾相同时,长度++
            next[j] = i; //更新next[j],j+1不匹配时回退到next[j]
        }
    }
    int strStr(string haystack, string needle) {
        if(needle.size() == 0) return 0;
        int next[needle.size()];
        getNext(next,needle);
        int j = 0;
        for(int i = 0; i < haystack.size(); i++){
            while(j > 0 && haystack[i] != needle[j]){
                j = next[j - 1];
            }
            if(haystack[i]==needle[j]) j++;
            if(j == needle.size()){
                return i - needle.size() + 1;
            }
        }
        return -1;
    }
};

459. 重复的子字符串

https://leetcode-cn.com/problems/repeated-substring-pattern/
在这里插入图片描述

class Solution {
public:
    void getNext(int *next,string &s){
        int i = 0;
        next[0]=0;
        for(int j = 1; j < s.size(); j++ ){
            while(i > 0 && s[j] != s[i]){
                i = next[i-1];
            }
            if(s[j] == s[i]) i++;
            next[j] = i;
        }
    }
    bool repeatedSubstringPattern(string s) {
        int len  = s.size();
        if(len == 0) return false;
        int next[s.size()];
        getNext(next,s);
        // for(int i = 0;i<len;i++) cout<<next[i]<<' ';
        // next[len-1] == 0 一定不是重复的串
        if(next[len-1] != 0 && len % (len - next[len - 1] ) == 0) 
            return true;
        return false;
    }
};

BM84 最长公共前缀

https://www.nowcoder.com/practice/28eb3175488f4434a4a6207f6f484f47
在这里插入图片描述

class Solution {
public:
    /**
     * 
     * @param strs string字符串vector 
     * @return string字符串
     */
    string getSamePrefix(string s1,string s2){
        int len = min(s1.length(),s2.length());
        int i = 0;
        while(i<len && s1[i] == s2[i]) i++;
        return s1.substr(0,i);
    }
    string longestCommonPrefix(vector<string>& strs) {
        // write code here
        if(strs.size() == 0) return "";
        string prefix = strs[0];
        for(int i = 1; i < strs.size(); i++){
            prefix = getSamePrefix(strs[i], prefix);
        }
        return prefix;
    }
};

BM86 大数加法

https://www.nowcoder.com/practice/11ae12e8c6fe48f883cad618c2e81475

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 计算两个数之和
     * @param s string字符串 表示第一个整数
     * @param t string字符串 表示第二个整数
     * @return string字符串
     */
    string solve(string s, string t) {
        // write code here
        if(s=="") return t;
        if(t=="") return s;
        if(t.size()>s.size()) return solve(t,s);
        reverse(s.begin(),s.end());
        reverse(t.begin(),t.end());
        string res;
        int r = 0;
        for(int i = 0; i < s.size(); i++){
            r += s[i] - '0';
            if(i < t.size()) r += t[i] - '0';
            res += r % 10 + '0';
            r /= 10;
        }
        if(r) res += r % 10 + '0';
        reverse(res.begin(),res.end());
        return res;
    }
};

BM85 验证IP地址(待做)

https://www.nowcoder.com/practice/55fb3c68d08d46119f76ae2df7566880
在这里插入图片描述
模拟题:根据要求依次判断各个条件是否满足

将IPv4、IPv6地址中各个分隔符中的数字取出来判断 是否满足条件

class Solution {
public:
    int i = 0; //全局变量,控制目前遍历到字符
    bool isIPv4(string s){
        int sum = 0;
        int count = 0; //记录位数
        bool preZero = true;//记录当前位之前有没有0
        while(i < s.size() && s[i] != '.' && isdigit(s[i])){
            int num = s[i] -'0';
            if(num == 0 && s[i+1] == '.' && preZero){ //处理"192.0.0.1"
                i += 2; 
                return true;
            }
            if(num == 0 && preZero) return false; //处理 "00.0.0.1"
            if(count > 3) return false; //处理 "111111111111111.0.0.1"
            if(num != 0 && preZero) preZero =  false;
            sum = sum * 10 + num; 
            i++;
            count++;
        }
        i++;
        return (sum > 0 && sum <= 255);
    } 
    
    bool isIPv6(string s){
        int count = 0;
        while(i < s.size() && s[i] != ':' &&
        (isdigit(s[i]) || s[i]>='a'&& s[i]<='f' || s[i]>='A'&& s[i]<='F')  ){
            //cout<<s[i];
            i++;
            count++;
        }
        i++; // 跳过当前的 :
        return (count > 0 && count <= 4); //只有此时十六进制数的位数 >0 && <=4 才返回 true
    }
    string validIPAddress(string queryIP) {
        int contains,choose;
        bool f = true;
        if(queryIP.find(':')!=std::string::npos){ //判断是不是ipv6
            choose = 6;
            contains = 8; //依次判断8个十六进制数
            while(contains--){
                bool tmp = isIPv6(queryIP);
                f = f & tmp;
            }
            
        }else if(queryIP.find('.')!=std::string::npos){
            choose = 4;
            contains = 4; //依次判断4个十进制数
            while(contains--){
                f = f & isIPv4(queryIP);
            }
        }
        if(i==queryIP.size() + 1){
            if(choose==6 && f) return "IPv6";
            if(choose==4 && f) return "IPv4";
        }
        return "Neither";
    }
};

NC116 把数字翻译成字符串

https://www.nowcoder.com/practice/046a55e6cd274cffb88fc32dba695668?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值