LeetCode-316-mid-去除重复数字(单调栈)

本博客介绍了LeetCode第316题的解题思路,使用单调栈解决去重并保持字典序最小的问题。分析了如何利用单调栈的性质来确保字典序最小,并提供了算法、数据结构的选择及复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键字:“单调栈”

题目描述

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

LeetCode-316-mid-去除重复字母

分析

题目要求:

  1. 去重且每个字母出现一次:则返回结果的长度固定
  2. 返回结果的排列保持原有相对位置
  3. 返回结果的字典序最小

设s中每个字母出现次数为 [ c a , c b , . . . , c z ] [c_a, c_b,..., c_z] [ca,cb,...,cz],则满足条件1和2的排列顺序总共有: c a × c b × . . . × c z c_a\times c_b \times ... \times c_z ca×cb×...×cz 种,由于输入规模较大,暴力枚举的方法不可行。

解题思路

条件2和尽量字典序的条件3:-> 单调栈(有相对位置+一定顺序)

目前还没有理清之间的关系。单调栈的性质和与这道题的联系。

目标是条件3:尽量把字典序小的字符(‘a’,‘b’,‘c’,…,‘z’)排在前边。所以可以尽量按照字典序升序的单调栈来排列。如果遇到原打算删除的字符在剩余字符串中不存在,则保留该字符。


设已有字符串pre,当前字符c,剩余字符串post。

如果c没有出现在pre中,则将c放入pre中(并将pre中最邻近结尾且大于c的在post中仍然存在的字符删除)// 这里是c字符所在位置要尽可能放在满足其字典序的位置,操作后所能形成的字典序更小。要求可删除的字符要在post字符串中出现,这样才能在剩余字符串中将该删除的字符附在最终形成的字符串的末尾。

如果c已经出现在pre中,则查看下一字符。(如果将pre中的c去掉,则使得字典序变大)


算法
INPUT: s
OUTPUT: ans
INIT:
visit[26], count[26]
for c in s :
	count[c-'a'] ++ 

//循环不变量:visit, count, stack
stack
for c in s :
	// 现有stack中没有c
	if visit[c] == false :
		while !stack.empty() && stack.top() > c && count[stack.top()-'a'] > 0 )
			visit[ stack.top() ] = false
			stack.pop()
		stack.push( c )
		visit[c-'a'] = true 
	count[c-'a'] -- 

ans = string(stack)
return ans
数据结构

记录访问信息:数组、vector

模拟单调栈:string、stack

复杂度分析

空间复杂度 O ( n ) O(n) O(n)

时间复杂度 O ( n ) O(n) O(n),不考虑stack.pop()

代码实现

class Solution {
public:
    string removeDuplicateLetters(string s) {

        vector<int> visit(26), count(26) ;
        for ( char c : s ){
            ++ count[c-'a'] ;
        }

        string stk = "" ;
        for ( char c : s ){
            if ( visit[c-'a'] == 0 ){
                while ( !stk.empty() && stk.back() > c && count[stk.back()-'a'] > 0 ){
                    visit[ stk.back()-'a' ] = 0 ;
                    stk.pop_back() ;
                }
                stk.push_back( c ) ;
                visit[c-'a'] = 1 ;
            }
            -- count[c-'a'] ;

        }
        return stk ;
    }
};

  • 使用vector或数组来存储对字符信息的访问,时间复杂度更低
  • 单调栈访问中,每个元素至少入栈一次

相关问题


PS.

  1. 相比较于其他已有的leetcode刷题笔记,我希望能够提供相关的解题分析和部分相关问题的链接,使得大家能获得一个较好的分析与相关问题的比较。

  2. 偶尔会进行类似题目的总结工作,有需要的读者可以对这份工作进行关注。

  3. 如果你发现有相关的错误或者表述不当不清晰的地方,请进行评论,我会尽快进行核对勘正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值