字符串 leetcode 316. 去除重复字母 (栈 单调栈)

#题目内容
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

注意:该题与 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同

示例 1:

输入:s = “bcabc”
输出:“abc”

示例 2:

输入:s = “cbacdcbc”
输出:“acdb”

提示:

1 <= s.length <= 104
s 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicate-letters

java语言解答,代码贴子leetcode圈友分享非常推荐,代码来源链接,讲解真是由浅入深

/**
大佬讲解链接在上面
题解大佬解答答案,我只是搬运工,加了些注释*/
class Solution {
    public String removeDuplicateLetters(String s) {
        //申请一个栈
        Stack<Character> stk = new Stack<>();
        // 维护一个计数器记录字符串中字符的数量
        // 因为输入为 ASCII 字符,大小 256 够用了
        int[] count = new int[256];
        for (int i = 0; i < s.length(); i++) {
            count[s.charAt(i)]++;
        }
        //inStack用来保存是否在栈中的状态
        boolean[] inStack = new boolean[256];
        for (char c : s.toCharArray()) {
            // 每遍历过一个字符,都将对应的计数减一
            count[c]--;

            //如果这个字符在栈中,则下一个字符继续判断,因为和前面和这个字符相等的字符不需要被替换,
            //即使被替换也会让这个符先出栈中,然后再加入栈中..
            if (inStack[c]) continue;

            //只要栈不为孔,,且当前栈顶元素大于当前字符
            while (!stk.isEmpty() && stk.peek() > c) {
                // 若之后不存在该栈顶元素了,则停止 pop
                //stk.peek()知识返回栈顶对象,并不弹出该元素
                if (count[stk.peek()] == 0) {
                    break;
                }
                // 若之后还有,则可以 pop
                inStack[stk.pop()] = false;
            }
            stk.push(c);
            inStack[c] = true;
        }
        //用来进行接收内容
        StringBuilder sb = new StringBuilder();
        while (!stk.empty()) {
            sb.append(stk.pop());
        }
        //顺序翻转下即是答案,应为栈是后进先出的
        return sb.reverse().toString();
    }
}

c语言解答(现学现用,思路同java)

/*
发现了千万不能申请数组用来存放结果,因为这个空间会被释放,导致一直打印null
*/
//字典序:相当于你查字典的时候用字母查的顺序
char * removeDuplicateLetters(char * s){
    //定义个栈,用数组来定义 栈的长度为len即可
    int len=strlen(s)+1;
     char *stack = (char *)malloc(sizeof(char) * 27);

    //错误做法,因为这样申请的数组会在局部函数返回后消除
    // char stack[len];
    //初始化栈
    // for(int i=0;i<len;i++){
    //     stack[i]='0';
    // }


    //count用来统计s中出现的次数
    int count[256];
    //初始化count
    for(int i=0;i<256;i++){
        count[i]=0;
    }
    for(int i=0;i<len-1;i++){
        count[s[i]]++;
    }

    //定义栈顶元素
    int stktop=-1;

    //定义一个数组记录该字母是否在栈中出现 先初始化
    int jilu[28];
    for(int i=0;i<28;i++){
        jilu[i]=0;
    }
    for(int i=0;i<len-1;i++){
        count[s[i]]--;

        //字母出现在栈中,直接继续
        if(jilu[s[i]-'a']==1){
            continue;
        }
        
        //如果栈不为空,且当前字符大于当前栈顶元素
        while(stktop>=0&&stack[stktop]>s[i]){
            if(count[stack[stktop]]==0){
                break;
            }
            jilu[stack[stktop]-'a']=0;
            stktop--;
        }
        stktop++;
        stack[stktop]=s[i];
        jilu[s[i]-'a']=1;
    }
    stktop++;
    stack[stktop]='\0';
    return stack;
}

总结,如果要返回个字符串,千万别用局部函数申请的数组用来返回,真的切记,要用malloc一、C语言中返回函数中局部变量值和指针

动态分配的内存 :在C语言中malloc, 申请的内存空间可以在主调函数中使用,直到被释放为止 free, delete/free

下面知识总结来源与该博客,只摘取了一部分

(1) 在C语言中,一个函数可以直接返回函数中定义的局部变量,其实在函数返回后,局部变量是被系统自动回收的,因为局部变量是分配在栈空间,那为什么还可以返回局部变量,其实这里返回的是局部变量的副本(拷贝)。

(2) 函数返回局部变量地址:局部变量内存分配在栈空间,因为函数返回后,系统自动回收了函数里定义的局部变量,所以运行时去访问一个被系统回收后的地址空间,一定就会发生段错误,这是C/C++语言的特点。内存空间分配在堆中即可。
————————————————
版权声明:本文为CSDN博主「li_101357」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/li_101357/article/details/80209413

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值