【棧】B015_LC_刪除字符串中的所有相鄰重複項 II(暴力刪除 / 棧 + 對每種字符計數)

一、Problem

Given a string s, a k duplicate removal consists of choosing k adjacent and equal letters from s and removing them causing the left and the right side of the deleted substring to concatenate together.

We repeatedly make k duplicate removals on s until we no longer can.

Return the final string after all such duplicate removals have been made.

It is guaranteed that the answer is unique.

Input: s = "deeedbbcccbdaa", k = 3
Output: "aa"
Explanation: 
First delete "eee" and "ccc", get "ddbbbdaa"
Then delete "bbb", get "dddaa"
Finally delete "ddd", get "aa"

Constraints:

1 <= s.length <= 10^5
2 <= k <= 10^4
s only contains lower case English letters.

二、Solution

方法一:暴力刪除

  • 對於實時 StringBuilder,每一次都去找 k 個相鄰且相同的字符,找到之後使用 delete 刪除。
  • 刪除完畢之後更新當前 sb 的長度,到 cur 中,並存儲 cur 到 pre 中
  • 如果發現 cur == pre 證明找不到相同的 k 個相鄰字符,返回即可最大長度 max。
class Solution {
    public String removeDuplicates(String s, int k) {
        StringBuilder sb = new StringBuilder(s);
        int cur = -1, pre = 0;
        
        while (cur != pre) {
            int cnt = 1;
            for (int i = 1; i < sb.length(); i++) {
                if (sb.charAt(i-1) != sb.charAt(i))
                    cnt = 1;
                else if (++cnt == k)
                    sb.delete(i-k+1, i+1);
            }
            pre = cur;
            cur = sb.length();
        }
        return sb.toString();
    }
}

複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()

方法二:棧

比賽的時候想用棧來着,賽後寫了下,發現我的棧思路很難對:

  • 將字符 c 壓棧前,對比棧頂元素是否和 c 相同,如果是相同的話,那麼計數器 + 1
  • 如果計數器到達 k,將棧頂的 k 個元素彈出棧,並將 cnt 設置爲 1

WA:這樣是錯的,這是因爲只用了一個全局的計數器 cnt 導致的。

"deeedbbcccbdaa"
3
預期:"aa"
輸出:"dedbcbda"
class Solution {
    public String removeDuplicates(String s, int k) {
        Stack<Character> st = new Stack<>();
        int cnt = 0;

        for (char c : s.toCharArray()) {
            if (st.isEmpty() || c != st.peek())
                st.push(c);
            else  {
                if (++cnt == k) {
                    while (cnt-- > 0)
                        st.pop();
                }
                cnt = 0;
            }
        }
        StringBuilder sb = new StringBuilder();
        while (!st.isEmpty()) {
            sb.insert(0, st.pop());
        }
        return sb.toString();
    }
}

正確的棧思路應該對每一個字符進行計數。

class Solution {
    public String removeDuplicates(String s, int k) {
        Stack<P> st = new Stack<>();

        for (char c : s.toCharArray()) {
            if (st.isEmpty() || c != st.peek().c)
                st.push(new P(c, 1));
            else if (++st.peek().cnt == k)
                st.pop();
        }
        StringBuilder sb = new StringBuilder();
        while (!st.isEmpty()) {
            while (st.peek().cnt-- > 0)
                sb.insert(0, st.peek().c);
            st.pop();
        }
        return sb.toString();
    }
    class P {
        char c;
        int cnt;
        P(char c, int cnt) {this.c = c; this.cnt = cnt;}
    }
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章