我有一个任务,从给定的字符串(经典的面试问题)删除重复,但这是一个有点不同,最终的结果应该在最小的词典顺序可能的其他。例如, cbacdcbc => acdb, bc =>
. 我在so中看到了几个相关的问题,但我找不到答案。
编辑:这是我目前的代码(工作不正常):
public static String removeDuplicateCharsAlphbetically(String str) {
int len = str.length();
if (len<2) return str;
char[] letters = str.toCharArray();
int[] counts = new int[26];
for (char c : letters) {
counts[c-97]++;
}
StringBuilder sb = new StringBuilder();
for (int i=0;i<len-1;i++) {
if (letters[i]==letters[i+1]) continue;
if (counts[letters[i]-97]==1) {
sb.append(letters[i]);
} else if (counts[letters[i]-97] != 0) {
if (letters[i]<letters[i+1] && counts[letters[i]-97] == 1) {
sb.append(letters[i]);
counts[letters[i]-97]=0;
} else {
counts[letters[i]-97]--;
}
}
}
return sb.toString();
}
edit2:很抱歉没有把问题的链接放在前面。以下是链接:
4条答案
按热度按时间baubqpgj1#
通过从输入的末尾向后到开始构建结果。在每个步骤上:
如果遇到新的字母,请将其置于结果之前。
如果遇到重复,则将其与结果的开头进行比较。如果head更大,则从结果中删除duplicate并将其前置。
LinkedHashSet
对于存储结果集及其内部顺序都很好。ccrfmcuu2#
观察1:输出的第一个字母是最小的字母,因此所有其他字母都出现在字符串中最左边的位置。
观察结果2:输出的其余字母是第一个字母最左侧外观右侧字母的子序列。
这就提出了一种递归算法。
iqih9akk3#
首先,让我们创建一组字符串中所有不同的字母
s
. 这个集合的大小是答案的长度和我们算法中的步数。我们将在每个步骤的答案上添加一个字母,方法如下:在每一个步骤中,按字母顺序遍历剩余的字母
l
:查找第一次出现的
l
在s
. 我们来命名吧lpos
.如果子串
s[lpos, end]
包含所有剩余字母,然后添加l
结果,替换s
与s[lpos+1, end]
然后继续下一步,设置减少的剩余字母。通过一些优化来实现更好的时间复杂度:
可运行版本:https://ideone.com/wiki3x
x7rlezfr4#
这可以在o(stringlenght)时间内完成。串长=n;时间复杂度o(n),字符串的单次扫描。空间复杂性o(26)
解决方案:
创建一个字母数组,它将存储指向双链接列表节点的指针。
ListNode* array[26]; // Initialized with NULL value.
创建一个空的linkedlist,它将在任何时间点以相反的顺序表示解决方案字符串。扫描字符串,检查每个字母的字母,ltr,check
array[ltr-'a']
.... a、 )如果为空,则表示它是第一次出现,并将其添加到链表中。。。b、 )如果数组指向任何节点listnodeltr,则表示结果i中已经有字母。检查链接列表中listnode到listnodeltr的前一个listnode的值,如果值
listNodeltr->prev->val < listNode->val
,这意味着从该位置移除当前节点将使结果变小。所以从linkedlist中的当前位置删除listnodeltr并将其添加到末尾。cbacdcbc公司
[a] ->[b]->[c]
cbacdcbc[c]->[a]->[b]
cbacdcbc[d]->[c]->[a]->[b]
cbacdcbc[b]->[d]->[c]->[a]
cbacdcbc[b]->[d]->[c]->[a]
按相反顺序打印链接列表:acdb。