DAY8 字符串+Leetcode344反转字符串+Leetcode541反转字符串II+替换空格 +Leetcode151翻转字符串里的单词+II.左旋转字符串

题目链接/文章讲解/视频讲解: 代码随想录

344.反转字符串

题目要求:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

双指针法,两边的指针同时向中间移动,交换双指针指向的元素。

C++:

class Solution {
public:
    void swapchar(char& a, char& b){
        char tmp = a;
        a = b;
        b = tmp;
    }
    void reverseString(vector& s) {
        for (int left = 0, right = s.size()-1; left < s.size()/2; left++, right--){
            swapchar(s[left],s[right]);
        }
    }
};

Python:

class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        # 使用了一个堆栈来反转一个字符串或字符列表
        stack = []
        for char in s:
            stack.append(char)
        for i in range(len(s)):
            # (.pop() 方法会返回并删除列表末尾的元素)
            s[i] = stack.pop()

541. 反转字符串II

题目要求:给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

遍历时只需要让i每次前进2*k步,判断是否有需要反转的空间即可。

C++:

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]);
        }
    }
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += (2 * k)){
            if (i + k <= s.size()){
                reverse(s, i, i + k - 1);
                continue;
            }
            reverse(s, i, s.size() - 1);
        }
        return s;
    }
};

Python:

class Solution(object):
    def reverseStr(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: str
        """
        def reverse_substring(text):
            left, right = 0, len(text) - 1
            while left < right:
                text[left], text[right] = text[right], text[left]
                left += 1
                right -= 1
            return text
        res = list(s)
        for cur in range(0, len(s), 2*k):
            # 如果cur+k超过res长度则会返回至字符串最后一个值。
            res[cur: cur+k] = reverse_substring(res[cur: cur+k])
        return ''.join(res)

剑指Offer 05.替换空格

题目要求:把给定字符串中的'.',替换成空格 。

C++:

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

Python:

class Solution(object):
    def pathEncryption(self, path):
        """
        :type path: str
        :rtype: str
        """
        return path.replace('.', ' ')

151.翻转字符串里的单词 

题目要求:给定一个字符串,逐个翻转字符串中的每个单词。

不要使用辅助空间,空间复杂度要求为O(1)。

思路:

举个例子,源字符串为:"the sky is blue "

  • 移除多余空格 : "the sky is blue"
  • 字符串反转:"eulb si yks eht"
  • 单词反转:"blue is sky the"

C++:

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 removeExtraSpaces(string& s){
        int slow = 0;
        for (int i = 0; i < s.size(); i++){
            if (s[i] != ' '){
                if (slow!=0) s[slow++] = ' '; // 给单次之间加上空格
                while (i < s.size() && s[i] != ' '){
                    // 不上单次,遇到空格说明单次结束
                    s[slow++] = s[i++];
                }
            }
        }
        s.resize(slow);
    }

    string reverseWords(string s) {
        removeExtraSpaces(s);
        reverse(s, 0, s.size() - 1);
        int start = 0;
        for (int i = 0; i <= s.size(); ++i){
            // 翻转遇到的单词(此处的单次已经前后颠倒)
            if (i == s.size() || s[i] == ' '){
                // 如果到达结尾或遇到空格就翻转
                reverse(s, start, i - 1);
                start = i + 1;
            }
        }
        return s;
    }
};

Python:

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 删除空格
        s = s.strip()
        # 反转整个字符串
        s = s[::-1]
        # 将字符串拆分成单词,并反转每个单词
        return ' '.join(word[::-1] for word in s.split())

剑指Offer58-II.左旋转字符串 

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

不能申请额外空间,只能在本串上操作

可以通过局部反转+整体反转,达到左旋转的目的。

具体步骤为:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串

最后就可以达到左旋n的目的,而不用定义新的字符串,完全在本串上操作。

例如 :示例1中 输入:字符串abcdefg,n=2

DAY8 字符串+Leetcode344反转字符串+Leetcode541反转字符串II+替换空格 +Leetcode151翻转字符串里的单词+II.左旋转字符串_第1张图片

C++:

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

    string dynamicPassword(string password, int target) {
        reverse(password, 0, target-1);
        reverse(password, target, password.size()-1);
        reverse(password, 0, password.size()-1);
        return password;
    }
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

Python(使用切片):

class Solution(object):
    def dynamicPassword(self, password, target):
        """
        :type password: str
        :type target: int
        :rtype: str
        """
        return password[target:] + password[:target]

总结

学会双指针,局部反转+全局反转的方法。局部反转+局部反转+全局反转可以完成字符串旋转的操作。这种操作可以不申请额外的空间,在O(n)的时间复杂度和O(1)的空间复杂度下可以完成字符串旋转操作。

你可能感兴趣的:(算法,数据结构,c++,leetcode)