316. Remove Duplicate Letters

26 篇文章 0 订阅
18 篇文章 0 订阅

 

Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.

Example:

Given "bcabc"
Return "abc"

Given "cbacdcbc"
Return "acdb"

 

 

 

思路:刚开始想到的是贪心算法,但贪婪的规则貌似不好想,在Discuss找到一个循环递归的解法

关键就是在某一个字符最后出现的地方做文章,也许这就是所谓的突破点吧!

/*
 * 令 x = 'a'最后一次出现的位置,那么结果一定包含 在x之前(包括x)的某个字符,否则就没有'a'了(不一定就是'a')
 * 既然要包含一个,那肯定是最小的一个
 * 如果最小的就是'a',那就从'a'后面的一个继续下去
 * 如果最小的不是'a',那就从最小的那个个继续下去,因为可以断定这个最小的位置肯定在'a'之前,所以'a'后面肯定还是会包括进来的
 * 因为目前最小的肯定是要包括到结果中的,那后面的即使有最小的也不能包括就去,所以递归的时候要去掉
 * 
 * 其他的字符也是类似
 */
public class Solution {
    public String removeDuplicateLetters(String s) {
    	
    	if("".equals(s))	return "";
    	
        char[] cs = s.toCharArray();
        int[] cnt = new int[26];
        for(char c : cs)	cnt[c-'a']++;
        
        int minPos = 0;
        for(int i=0; i<cs.length; i++) {
        	if(cs[i] < cs[minPos])	minPos = i;		// 获取最小的字符index
        	if(--cnt[cs[i]-'a'] == 0)	break;		// 当某个字符是最后一次出现时,跳出循环,拿出最小的继续递归
        }
        
    	return "" + cs[minPos] + removeDuplicateLetters(s.substring(minPos+1).replace(""+cs[minPos], ""));
    }
}

 

 

还有个思路就是用stack

public String removeDuplicateLetters(String sr) {

    int[] res = new int[26]; //will contain number of occurences of character (i+'a')
    boolean[] visited = new boolean[26]; //will contain if character (i+'a') is present in current result Stack
    char[] ch = sr.toCharArray();
    for(char c: ch){  //count number of occurences of character 
        res[c-'a']++;
    }
    Stack<Character> st = new Stack<>(); // answer stack
    int index;
    for(char s:ch){ 
        index= s-'a';
        res[index]--;   //decrement number of characters remaining in the string to be analysed
        if(visited[index]) //if character is already present in stack, dont bother
            continue;
        //if current character is smaller than last character in stack which occurs later in the string again
        //it can be removed and  added later e.g stack = bc remaining string abc then a can pop b and then c
        while(!st.isEmpty() && s<st.peek() && res[st.peek()-'a']!=0){ 
            visited[st.pop()-'a']=false;
        }
        st.push(s); //add current character and mark it as visited
        visited[index]=true;
    }

    StringBuilder sb = new StringBuilder();
    //pop character from stack and build answer string from back
    while(!st.isEmpty()){
        sb.insert(0,st.pop());
    }
    return sb.toString();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值