力扣第2390题 从字符串中移除星号 c++ stack容器?超内存 用双指针 巧解

题目

力扣第2390. 从字符串中移除星号

中等

给你一个包含若干星号 * 的字符串 s 。

在一步操作中,你可以:

  • 选中 s 中的一个星号。
  • 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。

返回移除 所有 星号之后的字符串

注意:

  • 生成的输入保证总是可以执行题面中描述的操作。
  • 可以证明结果字符串是唯一的。

示例 1:

输入:s = "leet**cod*e"
输出:"lecoe"
解释:从左到右执行移除操作:
- 距离第 1 个星号最近的字符是 "leet**cod*e" 中的 't' ,s 变为 "lee*cod*e" 。
- 距离第 2 个星号最近的字符是 "lee*cod*e" 中的 'e' ,s 变为 "lecod*e" 。
- 距离第 3 个星号最近的字符是 "lecod*e" 中的 'd' ,s 变为 "lecoe" 。
不存在其他星号,返回 "lecoe" 。

示例 2:

输入:s = "erase*****"
输出:""
解释:整个字符串都会被移除,所以返回空字符串。

提示:

  • 1 <= s.length <= 105
  • s 由小写英文字母和星号 * 组成
  • s 可以执行上述操作

思路和解题方法一(不行超内存)

  • 首先创建一个栈st,用于存储非星号字符。
  • 然后遍历字符串s中的每个字符:
    • 如果当前字符是星号('*')并且栈st不为空,则将栈顶的元素弹出,表示移除星号左侧最近的非星号字符。
    • 如果当前字符不是星号,则将其入栈st。
  • 创建一个空字符串result,用于存储最终结果。
  • 最后,从栈底到栈顶依次弹出字符,将每个字符拼接到result的前面。
  • 返回result作为最终的结果字符串。

这段代码使用了栈的特性,通过判断当前字符是否是星号以及栈是否为空,来实现移除星号左侧最近的非星号字符的操作。最后,将栈中剩余的字符拼接成结果字符串返回。

复杂度

        时间复杂度:

                O(n)

        其中n是字符串的长度。在遍历过程中,每个字符最多入栈和出栈一次,因此栈的操作总体上可以看作是线性时间复杂度的。所以总的时间复杂度为O(n)。

        空间复杂度

                O(n)

        算法使用了一个栈来存储非星号字符,栈的大小最坏情况下可能与输入字符串的长度相同。

c++ 代码

 
  
class Solution {
public:
    std::string removeStars(string s) {
        stack st; // 创建一个栈,用于存储非星号字符
        for (char c : s) { // 遍历字符串s中的每个字符
            if (c == '*' && !st.empty()) { // 如果当前字符是星号且栈不为空,则将栈顶元素弹出,表示移除星号左侧最近的非星号字符
                st.pop();
            } else if (c != '*') { // 如果当前字符不是星号,则将其入栈
                st.push(c);
            }
        }
        
       string result; // 创建一个空字符串,用于存储最终结果
        while (!st.empty()) { // 从栈底到栈顶依次弹出字符,将每个字符拼接到result的前面
            result = st.top() + result;
            st.pop();
        }
        return result; // 返回最终结果字符串
    }
};

 思路和解题方法二

首先,我们定义了两个指针i和j。i是慢指针,指向当前要处理的字符,j是快指针,用于遍历字符串。同时,我们也记录了字符串的长度n:

int n = s.length(); int i = 0; 
// 慢指针,指向当前要处理的字符 int j = 0; // 快指针,用于遍历字符串

接下来,我们开始遍历字符串。对于每一个字符,如果它是星号,我们需要移除星号左侧最近的非星号字符。我们可以通过将慢指针i往前移动来找到最近的非星号字符,直到遇到一个非星号字符或者到达字符串开头。注意,我们需要判断i是否大于0,以避免数组越界错误。然后,我们将慢指针i再往前移动一位,即移除了最近的非星号字符:

if (s[j] == '*') {
    // 找到星号时,移除星号左侧最近的非星号字符
    while (i > 0 && s[i-1] == '*') {
        i--;
    }
    if (i > 0) {
        i--; // 移除非星号字符
    }
}

如果当前字符不是星号,我们将其放到当前慢指针i的位置,并同时移动慢指针i和快指针j:

else {
    // 非星号字符,将其放到当前慢指针的位置
    s[i] = s[j];
    i++;
}
j++;

最后,我们返回从字符串开头到慢指针i的子串,即移除了所有星号之后的字符串。注意,这里需要使用substr函数获取子串,其第一个参数是子串的起始位置,第二个参数是子串的长度:

return s.substr(0, i);

复杂度

        时间复杂度:

                O(n)

        时间复杂度是O(n),其中n是输入字符串的长度。因为我们需要遍历整个字符串一次来处理每个字符。

        空间复杂度

                O(1)

        空间复杂度是O(1),因为我们只使用了常数个变量来保存指针和临时变量,没有使用额外的数据结构。

c++ 双指针 代码

 
  
class Solution {
public:
    std::string removeStars(string s) {
        stack st; // 创建一个栈,用于存储非星号字符
        for (char c : s) { // 遍历字符串s中的每个字符
            if (c == '*' && !st.empty()) { // 如果当前字符是星号且栈不为空,则将栈顶元素弹出,表示移除星号左侧最近的非星号字符
                st.pop();
            } else if (c != '*') { // 如果当前字符不是星号,则将其入栈
                st.push(c);
            }
        }
        
       string result; // 创建一个空字符串,用于存储最终结果
        while (!st.empty()) { // 从栈底到栈顶依次弹出字符,将每个字符拼接到result的前面
            result = st.top() + result;
            st.pop();
        }
        return result; // 返回最终结果字符串
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

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