316. 去除重复字母
一、题目
给你一个字符串 s
,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
二、思路
/** 打印效果,一目了然 b压入栈中,成功啦 c压入栈中,成功啦 当前元素【a】比栈顶元素【c】小,而且栈顶元素再后面还存在,需要移除了栈顶元素 当前元素【a】比栈顶元素【b】小,而且栈顶元素再后面还存在,需要移除了栈顶元素 a压入栈中,成功啦 b压入栈中,成功啦 d压入栈中,成功啦 当前元素【c】比栈顶元素【d】小,而且栈顶元素再后面还存在,需要移除了栈顶元素 c压入栈中,成功啦 n压入栈中,成功啦 当前元素【d】比栈顶元素【n】小,而且栈顶元素再后面还存在,需要移除了栈顶元素 d压入栈中,成功啦 j压入栈中,成功啦 当前元素【h】比栈顶元素【j】小,而且栈顶元素再后面还存在,需要移除了栈顶元素 h压入栈中,成功啦 s压入栈中,成功啦 j压入栈中,成功啦 e压入栈中,成功啦 n压入栈中,成功啦 */
三、代码
class Solution { public String removeDuplicateLetters(String s) { // 遍历每个字符,得出每个字符最后出现的index // 用栈数据结构保存字符串,后进先出 // 记录某个字符是否已再栈中保存 // 获取字符串数组 char[] chars = s.toCharArray(); // 定义一个长度为26的数组,记录每个字符最后出现的index int[] num = new int[26]; for (int i=0; i<chars.length; i++) { num[chars[i] - 'a'] = i; } // 定义栈 Deque<Character> stack = new ArrayDeque<>(); // 定义某个字符是否保存在栈中 boolean[] visited = new boolean[26]; // 开始遍历字符 for (int i=0; i<chars.length; i++) { // 如果当前字符已经再栈中,则continue if (visited[chars[i] - 'a']) { continue; } // 取出栈顶字符和当前字符作比较,while循环 /** 【1】栈必须非空 【2】取出栈顶元素和当前元素比较,栈顶元素比当前大 【3】栈顶元素再当前字符后面,还存在,则移除栈顶元素 */ // 此处必须要用while,用if就会有遗漏,参考测试用例 "bcabdcacndjhcsdjabcddend" while (!stack.isEmpty() && stack.peekLast() > chars[i] && num[stack.peekLast() - 'a'] > i) { //移除栈顶元素 Character c = stack.removeLast(); //表示该字符没有在栈中出现 visited[c - 'a'] = false; System.out.println("当前元素【" + chars[i] + "】比栈顶元素【" + c + "】小" + ",而且栈顶元素再后面还存在" + ",需要移除了栈顶元素"); } // 否则将该字符加入栈中,并设置已经存在栈中 stack.addLast(chars[i]); System.out.println(chars[i] + "压入栈中,成功啦"); visited[chars[i] - 'a'] = true; } StringBuilder sb = new StringBuilder(); for(Character c : stack){ sb.append(c); } return sb.toString(); } }
四、分析
复杂度分析
时间复杂度:O(N),其中 N 为字符串长度。代码中虽然有双重循环,但是每个字符至多只会入栈、出栈各一次。
空间复杂度:O(∣Σ∣),其中 Σ 为字符集合,本题中字符均为小写字母,所以 ∣Σ∣=26。由于栈中的字符不能重复,因此栈中最多只能有 ∣Σ∣个字符,另外需要维护两个数组,分别记录每个字符是否出现在栈中以及每个字符的剩余数量。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了