这是一个面试问题。找到给定字符串中的第一个字符,该字符只出现一次(我想解决方案应该是Java)。
例如:
"babcbcd" -> 'a' // both 'a' and 'd' appear only once but 'a' appears before 'd'
琐碎的解决方案是
HashMap
):char - >字符串中出现的次数; 有意义吗?什么是最好的地图实施?有没有更好,更有效的解决方案?
答案 0 :(得分:3)
在Java中,您可以使用LinkedHashMap<Character,Integer>
来计算每个字符在字符串中出现的次数。由于LinkedHashMap
保留了插入顺序,因此您可以迭代其条目以查找恰好出现一次的第一个字符。
在合理的假设下,这将给出O(n)
解决方案。
答案 1 :(得分:3)
这是Haskell中的一个版本。
import Data.List (elemIndices)
firstSingle str = take 1 [a | a <- str, length (elemIndices a str) == 1]
* Main Data.List&gt; firstSingle“babcbcd”
“一”
答案 2 :(得分:2)
如果我正在面试,我希望(尽管不一定期待)这样的事情:
def string = 'babcbcd'
def singles = string.toList().groupBy{ it }.findAll{ it.value.size() == 1 }.collect{ it.key }
println "First char that appears once: " + string.find{ singles.contains it }
关键是中间线。它将字符串作为字符列表groups the list逐个字符,因此您可以过滤掉一次不会发生的任何事情,最后生成一次出现的字符列表。然后我们只搜索字符串中该列表中的第一个字符。
这是Groovy,因为在Java中不可能优雅。也许一旦JDK 8终于成功......
更新:更简洁的版本,受@groovy's Haskell solution的启发。我现在几乎因为我的第一个人的笨拙而感到尴尬:)。
def firstUnique(seq) { seq.findAll{ seq.count(it) == 1 }.first() }
答案 3 :(得分:1)
您可以在原始字符串的一次传递中执行此操作:创建链接的哈希映射,存储您到目前为止找到的字符的计数。然后浏览地图条目(它将按插入顺序,因为它是一个链接的地图),当你看到一个计数时停止。
答案 4 :(得分:1)
你已经找到了一个很好的解决方案,但如果你想我建议采用不同的方法:
final String abc = "abcdefg....z";
boolean scanned[] = new boolean[abc.lenght()];
//set all to false ...
for(int i = 0; i<yourString.lenght(); i++){
char c = yourString.charAt(i);
if(!scanned[abc.indexOf(c)]){
for(int j=i+1; j<yourString.lenght(); j++)
if(yourString.charAt(i) == c){ // founded another
scanned[abc.indexOf(c)] = true;
break;
}
if(!scanned[abc.indexOf(c)])
return c;
}
}
答案 5 :(得分:1)
所有上述解决方案都需要O(n)内存。为了在O(1)内存中执行它,您可以为所有字符运行for循环(在ASCII中有128个)并计算出现次数和第一个外观然后找到fisrt非重复的char。时间复杂度O(128 | s |)。
int min=Integer.MAX_VALUE;
char ans=' '; //any initialization
for ( i=0; i<128;i++){
int count=0,first=-1;
for(j=0;j<s.length();j++){
if(s.charAt(j)==(char)(i)) count++;
if(count==1) first=j;
if(count>1) break;
}
if(count==1 && min>first){
first=min;ans=s.charAt(first);
}
}
if(min!=Integer.MAX_VALUE) System.out.println(ans);
else System.out.println("No such char found");
答案 6 :(得分:1)
假设String
仅由a-z字符组成,您可以使用队列来查看到目前为止看到的字符并保持计数。
public static String findFirstLetterThatAppearsOnceInString(String str) {
int[] seenCount = new int[26];
int[] queue = new int[26];
int queueSize = 0;
for (char c : str.toCharArray()) { // Iterate over the input characters
int i = c-'a';
if (seenCount[i]<2) {
seenCount[i]++;
// If seen for the first time, store it in queue
if (seenCount[i]==1) queue[queueSize++]=i;
}
}
for (int qi=0;qi<queueSize;qi++) if (seenCount[queue[qi]]==1) return (char)(queue[qi]+'a')+"";
return null;
}
答案 7 :(得分:1)
简单的非地图解决方案,假设没有unicode:
public String firstLonelyChar(String input)
{
while(input.length() > 0)
{
int curLength = input.length();
String first = String.valueOf(input.charAt(0));
input = input.replaceAll(first, "");
if(input.length() == curLength - 1)
return first;
}
return null;
}