• leetcode 2030. 含特定字母的最小子序列


    特别恶心的一道题
    首先基础做法是单调栈,如果没有至少repetition个letter的限制,直接从左往右遍历,维护一个递增栈即可

    加上这个限制之后,会有两个改动:

    1. 判断是否当前出栈元素是letter,删除后会导致后面的letter不够凑到repetition,这里需要把原栈的所有元素进行归档(代码31行)
    2. 处理一直是递增字符串的特殊case

    代码如下

    class Solution {
    public:
        string smallestSubsequence(string s, int k, char letter, int repetition) {
            string result;
    
            int n = s.length();
            stack<char> st;
            int letter_count = 0;
    
            int need_delete = n - k;
            // int last_repetition = 0;
            
    
            vector<int> pre(n + 5, 0);
            for(int i = 0; i < n; ++i) {
                if (i == 0) pre[i] = s[i] == letter;
                else pre[i] = pre[i - 1] + (s[i] == letter);
            }
            
            int end_flag = n;
    
            for(int i = 0; i < n; ++i) {
                int still_have = pre[n - 1] - pre[i] + (s[i] == letter);
    
                // printf("%d\n", still_have);
    
                while(!st.empty()) {
                    char tt = st.top();
    
                    if (need_delete == 0) break;
                    if (tt == letter && letter_count - 1 + still_have < repetition) {
                        string tmp;
                         while(!st.empty()) {
                            tmp += st.top();
                            st.pop();
                        }
                        reverse(tmp.begin(), tmp.end());
                        result += tmp;
                        // printf("%s\n", result.c_str());
                        break;
                    }
    
                    if(tt > s[i]) {
                        st.pop();
                        need_delete --;
                        if(tt == letter) letter_count --;
                        // printf("pop %c %d %d\n", tt, need_delete, letter_count);
                    } else {
                        break;
                    }
                }
    
                st.push(s[i]);
                if(s[i] == letter) letter_count ++;
                // printf("push %c %d %d\n", s[i], need_delete, letter_count);
            }
    
    
            string tmp;
            while(!st.empty()) {
                tmp += st.top();
                st.pop();
            }
            reverse(tmp.begin(), tmp.end());
            result += tmp;
    
            // printf("%s\n", result.c_str());
    
            
            result = result.substr(0, k);
    
            // for special case
            int cnt = 0;
            for(int i = 0; i < k; ++i) {
                if(result[i] == letter) {
                    cnt ++;
                }
            }
            for(int i = k - 1; i >= 0; --i) {
                if(result[i] != letter && cnt < repetition) {
                    result[i] = letter;
                    cnt ++;
                }
            }
    
            return result;
        }
    };
    
  • 相关阅读:
    MongoDB性能优化五步走之读书笔记
    Effective java 第十章 并发 避免过度同步 读书笔记
    Effective java 第三章对于所有对象都通用的方法(一) 读书笔记
    mongodb设计模式策略之读书笔记
    Effective java 第十章 并发 同步访问共享的可变数据 读书笔记
    搬运工生涯开端
    Effective java 第二章创建和销毁对象 读书笔记
    Mongodb聚合操作之读书笔记
    ArcGIS Engine 的插件式开发
    从一个AE画点的例子来看C#QI机制
  • 原文地址:https://www.cnblogs.com/Basasuya/p/15730436.html
Copyright © 2020-2023  润新知