• [Leetcode]316.去除重复字母


    题目

    贪心方法

    用一个两个数组vector<int>cnt,vector<bool>in_right_place;

    string res:目前符合条件的字符串,到代码结束的时候,这个res才是正确的答案

    cnt数组 用于记录每个char未来会出现的次数,in_right_place数组判断这个char是否已经在正确的位置上

    什么叫做未来会出现呢?

    我们拿样例做为例子:

    输入: "bcabc"

    我们先遍历一遍所有字符串记录cnt

    结果是cnt['a']=1,cnt['b']=2,cnt['c']=2,其他都为0

    我们需要再遍历一遍寻找结果

    现在读到第一个字符b,未来会出现的'b'的次数就减去1(因为已经出现了一次了),所以未来b只会再出现(2-1)次,这就是未来出现的次数

    in_right_place判断正确位置比较好理解,我们每次读到一个未在正确位置上的字符,就可以将这个字符拿来和res比较字典序,

    如果能发现存在一个新字符串使得字典序更小,则代替

    如何判断字典序更小呢?

    通过这个:

    while(cnt[res.back()]>0&&读取的当前字符<res.back()){
    /*就能说明存在一个新序列使得字典序更小*/
    in_right_place[res.back()]=false;
    res.pop_back();
    /*撤销正确位置的标记并将其从结果字符串弹出*/
    }

    还是回到样例,假设当前读取的字符为s[2],即'a',此时的res="bc"

    =>‘a’比'c'字典序优先且'c'未来还会出现(即cnt['c']>0),说明存在'a'在'c'前面的搭配,所以弹出'c'并撤销'c'是正确位置的标记即in_right_place['c']=false;此时res="b"

    =>‘a’比'b'字典序优先且'b'未来还会出现(即cnt['b']>0),说明存在'a'在'b'前面的搭配,所以弹出'b'并撤销'b'是正确位置的标记即in_right_place['b']=false;此时res=""

    这一题的贪心在于,每次遍历会考虑后面的情况将res改变。具体实现代码如下:

     

    C++实现代码如下:

    class Solution {
    public:
        string removeDuplicateLetters(string s) {
            vector<int>cnt(256);
            vector<bool>in_right_place(256);
            for(char c:s){
                cnt[c]++;
            }
            string res="";
            /*返回的字符串初始化为空*/
            for(char c:s){
                cnt[c]--;
                if(in_right_place[c]){
                    /*如果已经在正确位置,则跳过*/
                    continue;
                }else{
                    while(cnt[res.back()]>0&&c<res.back()){
                        /*说明存在一个新序列使得字典序更小*/
                        in_right_place[res.back()]=false;
                        res.pop_back();
                        /*撤销正确位置的标记并将其从结果字符串弹出*/
                    }
                    res+=c;
                    in_right_place[c]=true;
                    /*此时c在“当前的”正确位置*/
                }
            }
            return res;
            
        }
    };

    也可以不用vector而用数组记录

    class Solution {
    public:
       string removeDuplicateLetters(string s) {
            int m[256] = {0}, visited[256] = {0};
            string res = "";
            for (auto a : s) m[a]++;
            for (auto a : s) {
                --m[a];
                if (visited[a]) continue;
                while (a < res.back() && m[res.back()]) {
                    visited[res.back()] = 0;
                    res.pop_back();
                }
                res += a;
                visited[a] = 1;
            }
            return res;
        }
    };
  • 相关阅读:
    React 官网列子学习
    阿里云图片裁剪
    Android list加载图片工具类
    Java 反射
    Android 调节图片工具类
    Android 设置资源字体,屏幕截图
    android 跨进程通讯 AIDL
    android sdk api结构解析
    android学习之activity
    驱动进阶1
  • 原文地址:https://www.cnblogs.com/adamwong/p/10219690.html
Copyright © 2020-2023  润新知