代码随想录(四):字符串

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:

输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

提示

  • 1 <= s.length <= 105
  • s[i] 都是 ASCII 码表中的可打印字符

C++代码

//方法一:
class Solution {
public:
    void reverseString(vector<char>& s) {
        int i = 0, j = s.size() - 1;
        while (i < j) {
            swap(s[i++], s[j--]);
        }
    }
};
//方法二
class Solution {
public:
    void reverseString(vector<char>& s) {
        reverse(s.begin(),s.end());
    }
};

541. 反转字符串 II

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:

输入:s = "abcdefg", k = 2
输出:"bacdfeg"

示例 2:

输入:s = "abcd", k = 2
输出:"bacd"

提示

1 <= s.length <= 104
s 仅由小写英文组成
1 <= k <= 104

C++代码

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.end());
            else reverse(s.begin() + i, s.begin() + i + k);
        }
        return s;
    }
};

剑指 Offer 05. 替换空格

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

示例 1:

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

限制

0 <= s 的长度 <= 10000

C++代码

public:
    string replaceSpace(string s) {
        string res;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] != ' ') res += s[i];
            else res += "%20";
        }
        return res;
    }
};

151.翻转字符串里的单词

力扣题目链接

给定一个字符串s,逐个翻转字符串中的每个单词

示例 1:

输入: "the sky is blue"
输出: "blue is sky the"

示例 2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

解题思路:可以运用双指针先把每个单词进行反转,最后再将整个字符串进行反转。同时要消除多余的空格。

C++代码

class Solution {
public:
    string reverseWords(string s) {
        int k = 0; //用k来记录反转后到串的下标用到了什么位置
        for (int i = 0, j = 0; i < s.size();) {
            while (j < s.size() && s[j] == ' ') j++;
            if (j == s.size()) break;
            i = j;
            while (j < s.size() && s[j] != ' ') j++;
            reverse(s.begin() + i, s.begin() + j);
            if (k) s[k++] = ' ';
            while (i < j) s[k++] = s[i++]; 
        } 
        s.erase(s.begin() + k, s.end());
        reverse(s.begin(), s.end());
        return s;
    }
};
// 方法二
class Solution {
public:
    string reverseWords(string s) {
        string res;
        for (int i = 0, j = 0; i < s.size();) {
            if (s[i] == ' ') {
                i++;
                continue;
            }
            j = i;
            while (i < s.size() && s[i] != ' ') i++;
            reverse(s.begin() + j, s.begin() + i);
            res.append(s.begin() + j, s.begin() + i);
            res.push_back(' ');
        }
        res.pop_back();
        reverse(res.begin(), res.end());
        return res;
    }
};

剑指 Offer 58 - II. 左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

输入: s = "abcdefg", k = 2
输出: "cdefgab"

示例 2:

输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"

限制

1 <= k < s.length <= 10000

解题思路:通过定义发现规律

C++代码

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.end());
        reverse(s.begin(), s.end() - n);
        reverse(s.end() - n, s.end());
        return s;
    }
};

// 方法二
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        string res;
        res.append(s.begin() + n, s.end());
        res.append(s.begin(), s.begin() + n);
        return res;
    }
};

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

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

提示

  • 1 <= haystack.length, needle.length <= 104
  • haystackneedle 仅由小写英文字符组成

解题思路

这道题题意是要求从字符串中找到一个子串与模式串相匹配,并返回第一个匹配项的下标。从长字符串中寻找特定模式串的问题可使用kmp算法。首先求得模式串的next数组,然后在将模式串和长字符串进行匹配。

C++代码

class Solution {
public:
    int strStr(string s, string p) {
        if (p.empty()) return 0;
        int n = s.size(), m = p.size();
        s = ' ' + s; //kmp算法中字符串下标通常从1开始
        p = ' ' + p;
        vector <int> ne(m + 1); 
        for (int i = 2, j = 0; i <= m; i++) {
            while (j && p[i] != p[j + 1]) j = ne[j]; //当以i结尾的字符串p的第i个位置和p串前缀的j+1的位置值不相等
            										 //此时失配,需要移动j的位置重新进行匹配
            if (p[i] == p[j + 1]) j++;
            ne[i] = j;
        }
        for (int i = 1, j = 0; i <= n; i++) {
            while (j && s[i] != p[j + 1]) j = ne[j];
            if (s[i] == p[j + 1]) j++;
            if (j == m) 
                return i - m; //这里的取值和字符串下标相关,注意下标的取值
        }
        return -1;
    }
};

459. 重复的子字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

提示

1 <= s.length <= 104
s 由小写英文字母组成

解题思路

这道题题意是检查字符串是否由一个子串重复多次构成,那么也就是说我们需要寻找到一个周期,并判断这个周期的子串能不能构成原字符串。这里我首先提出两条性质

  1. 如果非空字符串s的长度为n,字符串s的最长公共前后缀长度为next[n],则t = n - next[n]为字符串s的最小周期,此时字符串s的最后一个周期的子串并不一定完整。
  2. 如果最小周期t可以整除n,则最小周期t一定是其他所有周期的约数。

C++代码

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        s = ' ' + s;
        vector<int> next(n + 1);
        for (int i = 2, j = 0; i <= n; i++) {
            while (j && s[i] != s[j + 1]) j = next[j];
            if (s[i] == s[j + 1]) j ++;
            next[i] = j;
        }
        int t = n - next[n]; //t是字符串s的最小周期,并且字符串s中的最后一个周期t可以不完整。
        return t < n && n % t == 0; //如果最小周期可以整除n,则最小周期一定是其他所有周期的约数。
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员小浩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值