代码随想录训练营Day08|344.反转字符串、541.反转字符串2、剑指offer 05.替换空格、151.反转字符串里的单词、剑指offer58:左旋转字符串

C++字符串的常见函数:

C++ 字符串 (string)

函数 返回值 描述
size() size_t 返回字符串的长度。
length() size_t size(),返回字符串的长度。
empty() 布尔值 (truefalse) 如果字符串为空,则返回 true;否则返回 false
clear() 清空字符串内容。
at(pos) 字符的引用 返回位置 pos 的字符。
operator[] 字符的引用 返回指定位置的字符。
substr(start, len) string 返回一个子字符串,从位置 start 开始,长度为 len
append(str) string& str 追加到当前字符串的末尾。
push_back(ch) 将字符 ch 添加到字符串末尾。
pop_back() 删除字符串的最后一个字符。
erase(pos, len) string& 从位置 pos 开始删除 len 个字符。
replace(pos, len, str) string& str 替换从位置 pos 开始的 len 个字符。
find(str, pos) size_t 从位置 pos 开始查找子字符串 str 的首次出现。如果找到,返回起始位置;否则返回 string::npos
rfind(str, pos) size_t 从位置 pos 开始向前查找子字符串 str 的最后一次出现。如果找到,返回起始位置;否则返回 string::npos
c_str() const char* 返回C风格的字符串。
begin() 迭代器 返回指向字符串首字符的迭代器。
end() 迭代器 返回指向字符串末尾字符之后的迭代器。
compare(str) 整数 比较当前字符串和 str。返回值为0表示相等;小于0表示当前字符串小于 str;大于0表示当前字符串大于 str

当然,下面我会为您列举和解释这些操作:

1. 创建字符串

  • 使用构造函数:
    std::string str1;                    // 默认构造,空字符串
    std::string str2("Hello");           // 从C风格字符串构造
    std::string str3 = "World";          // 使用=运算符从C风格字符串赋值
    std::string str4(5, 'a');            // 用5个字符'a'构造,结果:"aaaaa"
    

2. 字符串的拼接

  • 使用 ++= 运算符:
    std::string str1 = "Hello";
    std::string str2 = "World";
    std::string str3 = str1 + " " + str2;    // 结果:"Hello World"
    str1 += " World";                        // str1现在是"Hello World"
    
  • 使用 append() 方法:
    std::string str1 = "Hello";
    str1.append(" World");                   // str1现在是"Hello World"
    

    3. 字符串的遍历

  • 使用范围for循环:
    std::string str = "Hello";
    for (char c : str) {
        std::cout << c << std::endl;
    }
    
  • 使用传统的for循环和下标操作:
    std::string str = "Hello";
    for (size_t i = 0; i < str.size(); i++) {
        std::cout << str[i] << std::endl;
    }
    
  • 使用迭代器:
    std::string str = "Hello";
    for (auto it = str.begin(); it != str.end(); ++it) {
        std::cout << *it << std::endl;
    }
    

    4. 字符串的反转

  • 使用 std::reverse() 函数:
    #include 
    
    std::string str = "Hello";
    std::reverse(str.begin(), str.end());    // str现在是"olleH"
    
  • 手动实现:
    std::string reverseString(const std::string& input) {
        std::string result;
        for (int i = input.size() - 1; i >= 0; i--) {
            result.push_back(input[i]);
        }
        return result;
    }
    

LeetCode344:反转字符串

思路:双指针,首部和尾部交换,方向向内。

class Solution {
    public void reverseString(char[] s) {
        // 第一反应:双指针。
        int size = s.length;
        int left = 0;
        int right = size-1;
        while(right > left){
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
}
class Solution {
public:
    void reverseString(vector<char>& s) {
        // 双指针,头部和尾部位置交换,方向向内
        int left = 0;
        int right = s.size() - 1;
        while(left<right){
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
};

LeetCode542:反转字符串2

思路:双指针。找到交换位置的起始和结束位置,依次交换即可。
通过for循环里面的i += 2*k,就可以找到每次交换的起始位置,因为i是从0开始的(如果从i=-1开始就是2k的位置,也就是交换起始位置的前一位)。
下面就是判断结束位置,但是结束位置要分情况,就是最有一个2k结束之后剩下的部分。
>k 则slow ,slow+k-1的部分进入交换;
slow, size-1的部分进入交换。
关键点:如何找到一种很好的方式确定这些位置,还有特殊情况的判定比较关键。

class Solution {
    public String reverseStr(String s, int k) {
        // 双指针
        // 在for循环的时候就将2k找到 不用一步步遍历去找
        // 清楚需要几个变量: k, 2k; 交换的first,end,需要知道四个变量的位置
        /* 其中k和2k可以通过for确定;first的位置也可以通过佛如确定,
        可以理解为当前i的位置就是交换的起始位置,而end的位置由于情况不同要分类,
        所以通过Math.min(size-1, slow+k-1),表示当前s(i或者上一个2k后一位)到末尾还剩多少,
        小于k就是size-1 ,大于k就是slow+k-1(-1 是因为for是从i开始的,实际上i的位置
        可以理解为2k的后一个位置。例如,k=2 (0, 4, 8)都是交换的起始位置。)
        */
        int size = s.length();
        char[] ch = s.toCharArray();
        for(int i=0;i<size;i += 2*k){
            int slow = i;
            int last = Math.min(size-1, slow+k-1);
            while(slow<last){
                ch[slow] ^= ch[last];
                ch[last] ^= ch[slow];
                ch[slow] ^= ch[last];
                slow++;
                last--;
            }
        }
        return new String(ch);
    }
}

C++:注意函数的使用
reverse(start, end)

class Solution {
public:
    string reverseStr(string s, int k) {
        for(int i=0;i<s.size();i+= (2*k)){ // i增加2k
            // 如果总长度到当前i起点位置长度大于K,表示需要将前k个翻转
            if(s.size() - i >=k){
                reverse(s.begin()+i, s.begin()+i+k);
            }
            else{//如果总长度到当前i起点位置小于k,表示直接将i起点到结尾的翻转
                reverse(s.begin()+i, s.end());
            }
        }
        return s;
    }
};

LeetCode剑指offer05.替换空格

原题描述:

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1: 输入:s = “We are happy.”
输出:“We%20are%20happy.”

#思路
对于一些常用的java函数不够熟练。
思路:找到空格直接通过StringBuilder填充。

class Solution {
    public String replaceSpace(String s) {
        // StringBuilder 类似于python的列表 可以appen,可以修改里面的值

        char[] ch = s.toCharArray(); // 
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<ch.length;i++){
            if(ch[i]==' '){
                sb.append("%20");
            }
            else{
                sb.append(ch[i]);
            }
        }
        return sb.toString();
    }
}

思路:双指针,先按照空格多少扩充。然后从后往前一个个将原来的s添加到char[] 中。

class Solution {
    public String replaceSpace(String s) {
        // 双指针,好好了解一下扩充法。
        // 先将原string扩充,然后从后向前填充,避免从前到后要把空格之后的往后移动
        // 这里的替换%20 是三个字符
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i) == ' '){ // 如果找到空格就在sb最后在添加两个空格
                sb.append("  ");
            }
        }
        int first = s.length() -1; // 原s的长度
        s = s + sb.toString(); // 不知道这个用法,s的拼接。s的扩充
        int end = s.length() -1; // 扩充之后的长度,与first的差就是要填充的长度
        char[] ch = s.toCharArray();
        while(end>first){
            if(ch[first] == ' '){
                ch[end] ='0';
                end--;
                ch[end]='2';
                end--;
                ch[end] = '%';
            }
            else{
                ch[end] = ch[first];
            }
            first--;
            end--;
        }
        return new String(ch); // java字符串的常用函数要学
    }
}

新题描述:

假定一段路径记作字符串 path,其中以 “.” 作为分隔符。现需将路径加密,加密方法为将 path 中的分隔符替换为空格 " ",请返回加密后的字符串。
示例 1:
输入:path = “a.aef.qerf.bb”
输出:“a aef qerf bb”

class Solution {
public:
    string pathEncryption(string path) {
        for(int i=0;i<path.size();i++){
            if(path[i] == '.'){
                path[i] = ' ';
            }
        }
        return path;
    }
};

LeetCode151★:反转字符串中的单词

需要三刷

class Solution {
    public String reverseWords(String s) {
    	// 去除字符串中的多余空格
        StringBuilder sb = trimSpaces(s);

        // 翻转字符串
        reverse(sb, 0, sb.length() - 1);

        // 翻转每个单词
        reverseEachWord(sb);

        return sb.toString();
    }

    public StringBuilder trimSpaces(String s) {
        int left = 0, right = s.length() - 1;
        // 去掉字符串开头的空白字符
        while (left <= right && s.charAt(left) == ' ') {
            ++left;
        }

        // 去掉字符串末尾的空白字符
        while (left <= right && s.charAt(right) == ' ') {
            --right;
        }

        // 将字符串间多余的空白字符去除
        // 这里多用了一个空间 来装去除多余空格之后的字符串
        StringBuilder sb = new StringBuilder(); 
        while (left <= right) {
            char c = s.charAt(left);

            if (c != ' ') {
                sb.append(c);
            } else if (sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }

            ++left;
        }
        return sb;
    }

    public void reverse(StringBuilder sb, int left, int right) {
        while (left < right) {
            char tmp = sb.charAt(left);
            sb.setCharAt(left++, sb.charAt(right));
            sb.setCharAt(right--, tmp);
        }
    }

    public void reverseEachWord(StringBuilder sb) {
        int n = sb.length();
        int start = 0, end = 0;

        while (start < n) {
            // 循环至单词的末尾
            while (end < n && sb.charAt(end) != ' ') {
                ++end;
            }
            // 翻转单词
            reverse(sb, start, end - 1);
            // 更新start,去找下一个单词
            start = end + 1;
            ++end;
        }
    }
}

必须掌握

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]);
        }
    }

    
    // 这一步的逻辑想不出来,我只会最基础的分情况删除。
    void removeblank(string& s){ // 
        int slow = 0;
        for(int fast=0;fast<s.size();++fast){
        // 和27题的区别是:多了一个添加空格的处理
            if(s[fast] != ' '){ // 遇到一个新的单词,在操作。不然fast一直往后走。
                if(slow != 0){ // 第一个单词的时候跳过,后面就是在遇到一个新单词之后,现在这个单词的前面加一个空格
                    s[slow++] = ' ';
                }
                
                while(fast < s.size() && s[fast] != ' '){ //在遇到空格之前,将单词往前移动
                    s[slow++] = s[fast++]; 
                }
                
            }
        }
        s.resize(slow);
    }
    string reverseWords(string s) {
        removeblank(s); //去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。
        reverse(s, 0, s.size() - 1);
        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
        for (int i = 0; i <= s.size(); ++i) {
            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
                reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
                start = i + 1; //更新下一个单词的开始下标start
            }
        }
        return s;
        }   
};

LeetCode剑指offer58-2左旋转字符串

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<n;i++){
            sb.append(s.charAt(i));
        }
        int fast = n;
        int slow = 0;
        char[] ch = s.toCharArray();
        while(s.length()>fast){
            ch[slow] = ch[fast];
            slow++;
            fast++;
        }
        
        StringBuilder sb_1 = new  StringBuilder();
        for(int i=0;i<s.length()-n;i++){
            sb_1.append(ch[i]);
        }
        sb_1.append(sb);
        return sb_1.toString();
    }
}

解法二:也可以翻转局部、然后在翻转整体。

class Solution {
    public String reverseLeftWords(String s, int n) {
        // 依据代码随想录的提示,先翻转局部,再反转整体。
        String s1 = reverseSub(s, 0, n-1);
        String s2 = reverseSub(s1, n, s.length()-1);
        String s3 = reverseSub(s2,0,s.length()-1);
        return s3;
    }
    public  String reverseSub(String s, int start, int end){
        char[] ch = s.toCharArray();
        while(end>start){
            ch[start] ^= ch[end];
            ch[end] ^= ch[start];
            ch[start] ^= ch[end];
            end--;
            start++;
        }
        return new String(ch);
    }
}

你可能感兴趣的:(LeetCode刷题,算法,leetcode)