[英]First Unique String in an String array
Given a String Array how would you find the first unique String element in the array给定一个字符串数组,你如何找到数组中第一个唯一的字符串元素
public static String UniqueString(String[] s) {
String str ="";
for(int i=0;i<s.length;i++) {
for(int j=i+1;j<s.length;j++) {
System.out.println(s[i]+" "+s[j]);
str = s[i];
if(str==s[j]) {
break;
}
}if(!(str==s[i+1])){
return str;
}
}
return str;
}
so a String array of {Dog,Cat,Dog,Wolf,lion} would return as Cat所以 {Dog,Cat,Dog,Wolf,lion} 的字符串数组将返回为 Cat
Your approach grows quadratically with the size of the list.您的方法随着列表的大小呈二次方增长。 There's a better approach that is essentially linear in the list size, which is to use an ordered map from strings to the number of occurrences.有一种更好的方法,它基本上与列表大小呈线性关系,即使用从字符串到出现次数的有序映射。 Use one pass through the list to build the map and then one pass through the map to find the first element (if any) with a count of 1. You can use a LinkedHashMap
to implement this.使用一次遍历列表来构建地图,然后一次遍历地图以找到计数为 1 的第一个元素(如果有)。您可以使用LinkedHashMap
来实现这一点。
public static String uniqueString(String[] list) {
Integer ZERO = 0; // to avoid repeated autoboxing below
final LinkedHashMap<String, Integer> map = new LinkedHashMap<>(list.size());
// build the map
for (String s : list) {
Integer count = map.getOrDefault(s, ZERO);
map.put(s, count + 1);
}
// find the first unique entry. Note that set order is deterministic here.
for (Set.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 1) {
return entry.getKey();
}
}
// if we get this far, there was no unique string in the list
return "";
}
Note that you could use any kind of Map
implementation (including HashMap
) and forgo the ordering property of LinkedHashMap
by replacing the second loop with a loop through the original list:请注意,您可以使用任何类型的Map
实现(包括HashMap
)并通过将第二个循环替换为原始列表的循环来放弃LinkedHashMap
的排序属性:
for (String s : list) {
if (map.get(s) == 1) {
return s;
}
}
However, if the list has lots of repeated strings then iterating through the map will probably require significantly fewer iterations.但是,如果列表有很多重复的字符串,那么遍历地图可能需要的迭代次数会少得多。 So might as well use the added functionality of LinkedHashMap
, which you get for very little performance penalty compared to HashMap
.所以不妨使用LinkedHashMap
的附加功能,与HashMap
相比,您获得的性能损失很小。
You were very close to a working solution, you need a flag to indicate whether you found the String
again in s
(not sure where you got names
).您非常接近工作解决方案,您需要一个标志来指示您是否在s
再次找到了String
(不确定您从哪里得到names
)。 Also we compare String
(s) with .equals
(not ==
).我们.equals
String
(s) 与.equals
(不是==
)进行比较。 And method names start with a lower case letter.方法名称以小写字母开头。 Something like,就像是,
public static String uniqueString(String[] s) {
for (int i = 0; i < s.length; i++) {
boolean unique = true;
for (int j = i + 1; j < s.length; j++) {
if (s[j].equals(s[i])) {
s[j] = s[s.length - 1]; // <-- handle bug, ensure that dupes aren't
// found again.
unique = false;
break;
}
}
if (unique) {
return s[i];
}
}
return "";
}
Java 8爪哇 8
public static String uniqueString(String[] s) {
StringBuilder result = new StringBuilder();
Stream.of(s)
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() == 1)
.findFirst()
.ifPresent(entry -> result.append(entry.getKey()));
return result.toString();
}
Update , after 2 years: 2年后更新:
Not sure why I had used a StringBuilder when I could just do it all in a single statement:不知道为什么我使用 StringBuilder 当我可以在一个语句中完成所有操作时:
public static String uniqueString(String[] s) {
return Stream.of(s)
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() == 1)
.findFirst()
.map(Map.Entry::getKey)
.orElse(null);
}
Perhaps there is another solution that can also solve your problem in a more java-8 way:也许还有另一种解决方案也可以以更 java-8 的方式解决您的问题:
map
to record the count of the duplicated strings and then使用map
记录重复字符串的数量,然后That could be like:那可能是这样的:
public static void main(String... args) {
String[] arr = {"Dog", "Cat", "Dog", "Wolf", "lion"};
Map<String, Long> stringCountMap = Arrays.stream(arr)
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
for (String s : arr) {
if (stringCountMap.get(s) == 1) {
System.out.println("The first non-duplicate string: " + s);
break;
}
}
}
Also you can turn to LinkedHashMap
as others mentioned to keep the order to avoid traverse the original array again as:您也可以像其他人提到的那样转向LinkedHashMap
以保持顺序以避免再次遍历原始数组:
private static void another(String[] arr) {
Map<String, Long> stringCountMap = Arrays.stream(arr)
.collect(Collectors.groupingBy(s -> s, LinkedHashMap::new, Collectors.counting()));
for (String s : stringCountMap.keySet()) {
if (stringCountMap.get(s) == 1) {
System.out.println("The first non-duplicate string: " + s);
break;
}
}
}
The output will always be:输出将始终为:
The first non-duplicate string: Cat
The above answer does not work in all cases.上述答案并不适用于所有情况。 for instance {"Dog","Dog",Cat} would return dog.例如 {"Dog","Dog",Cat} 将返回狗。 the problem being that It does not check the entire array for duplicates.问题是它不会检查整个数组是否有重复项。
private static String getFirstUniqueString(String[] names) {
for(int x=0;x<names.length;x++)
{
if(countOccurences(names[x],names) == 1 )
return names[x];
}
return "No Unique Strings";
}
private static int countOccurences(String string, String[] names)
{
int count=0;
for(int y = 0; y<names.length;y++)
{
if(names[y].equals(string))
{
count++;
if(count >1 )
return count;
}
}
return count;
}
Instead maybe break it into two pieces.相反,也许把它分成两部分。 One method to find the unique string the other to count occurrences this way we count exactly how many times the word is mentioned through the entire array.一种方法是找到唯一字符串,另一种方法是通过这种方式计算出现次数,我们准确计算整个数组中提到该单词的次数。 If you simply want to know there more then one and you want to save run time, uncomment the if statement.如果您只是想了解更多信息并且想节省运行时间,请取消对 if 语句的注释。
public static String FirstUniqueString(String[] strs) {
List<String> list = new LinkedList<>();
for (String s: strs) {
if (list.contains(s)) {
list.remove(s);
} else {
list.add(s);
}
}
return list.get(0);
}
We can use a simple LinkedList
to keep a track of the duplicates.我们可以使用一个简单的LinkedList
来跟踪重复项。 For example, if the input is new String[] {Dog, Cat, Dog, Wolf, Lion, Dog}
, the first unique element would still be Cat.例如,如果输入是new String[] {Dog, Cat, Dog, Wolf, Lion, Dog}
,第一个唯一元素仍然是 Cat。 The list after for-each loop will be in the following sequence: {Cat, Wolf, Lion, Dog}
. for-each 循环后的列表将按以下顺序排列: {Cat, Wolf, Lion, Dog}
。 Big O runtime will be O(N ^ 2) as the for-each loop and contains()
requiring O(N) respectively. Big O 运行时将是 O(N ^ 2) 作为 for-each 循环和contains()
分别需要 O(N)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.