import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* 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.
* <p>
* Example:
* Given "bcabc"
* Return "abc"
* <p>
* Given "cbacdcbc"
* Return "acdb"
* <p>
* Tags: Stack, Greedy
*/
public class RemoveDuplicateLetters {
private RemoveDuplicateLetters r;
public String removeDuplicateLetters(String s) {
if (s == null || s.length() <= 1) return s;
int[] count = new int[26];
for (int i = 0; i < s.length(); i++) {
count[s.charAt(i) - 'a']++;
}
int minPos = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) < s.charAt(minPos)) minPos = i;
if (--count[s.charAt(i) - 'a'] == 0) break;
}
return s.charAt(minPos) + removeDuplicateLetters(s.substring(minPos + 1).replace(String.valueOf(s.charAt(minPos)), ""));
}
@Before
public void setUp() {
r = new RemoveDuplicateLetters();
}
@Test
public void testEdgeCases() {
Assert.assertNull(r.removeDuplicateLetters(null));
Assert.assertEquals("", r.removeDuplicateLetters(""));
Assert.assertEquals("a", r.removeDuplicateLetters("a"));
}
@Test
public void testExamples() {
Assert.assertEquals("a", r.removeDuplicateLetters("aa"));
Assert.assertEquals("abc", r.removeDuplicateLetters("bcabc"));
Assert.assertEquals("acdb", r.removeDuplicateLetters("cbacdcbc"));
}
@After
public void tearDown() {
r = null;
}
}