[英]Find one unique element in List with duplicates in Java
我們列出了整數(或其他對象),例如:
[0, 0, 1, 1, ... , 777777, ... , 999999, 999999]
爪哇代碼:
List<Integer> ints = new LinkedList<Integer>();
for (int i = 0; i < 999999; i++) {
ints.add(i); // add first value
if (i!=777777){
ints.add(i); // add duplicate value in not '5'
}
}
我是這樣解決這個問題的:
Integer unique = null;
while (true) {
unique = ints.get(0);
ints.remove(0);
if (ints.contains(unique)) {
ints.remove(ints.indexOf(unique));
} else {
break;
}
}
System.out.println(unique);// 777777
大約需要 30 毫秒。 使用 ArrayList,它的工作時間更長。 問題是如何以最佳(正確/優雅/最快)方式從此列表中獲取一個唯一值(例如 777777)。
您的實現非常低效,因為您在循環中運行線性時間操作,例如ints.contains(unique)
和ints.indexOf(unique)
。 因此,在最壞的情況下,您的運行時間為O(n^2)
。
如果數字總是排序的(就像它們在你的例子中一樣),你可以在列表的元素上迭代一次,找到不等於list.get(i-1)
和list.get(i+1)
的元素list.get(i)
list.get(i+1)
。 這將需要O(n)
。
如果數字並不總是排序,你可以在O(nlogn)
對它們進行排序並像以前一樣繼續。
或者你也可以遍歷數一次,統計每個號碼(可以存儲在計數的出現次數HashMap
),並找到其計為1。這將需要數O(n)
不管是否輸入列表是否排序。
除了其他答案給出的Set
解決方案之外,如果您知道重復元素只出現兩次(或偶數次)並且只有一個非重復數字,則可以對所有值進行異或以找到唯一的一。
public int findUnique(int[] nums) { // Or (List<Integer> nums), it works also
int xor = 0;
for(int i : nums){
xor ^= i;
}
return xor;
}
該解決方案比其他解決方案更快、更短。
你也可以用 Java 8 風格來做,但它當然會更慢:
public int findUnique(int[] nums) {
return Arrays.stream(nums)
.reduce((acc,i) -> acc ^= i)
.orElseThrow(IllegalArgumentException::new);
}
您正在使用錯誤的集合。 List 不是這個問題的正確集合。
你應該使用HashSet來解決這個問題。
private void find(List<Integer> ints){
HashSet<Integer> set = new HashSet<>();
for(int i=0;i<ints.size();i++){
if(set.contains(i)){
set.remove(i);
}else{
set.add(i);
}
}
Iterator<Integer> itr = set.iterator();
if(itr.hasNext()){
System.out.println("Unique value is :"+itr.next());
}else{
System.out.println("There is no duplicated value");
}
}
此方法僅適用於 2 和 1 計數列表項。 如果你有 3 次相同的數字,這種方法會發現它是重復的。
排序可能是答案,但排序最多只有 O(logn),之后 O(n) 用於查找重復元素。 如果您可以在創建列表時創建哈希集,則此方法將發現重復元素為 O(1)。
首先獲取唯一元素,然后使用集合 api 的頻率方法來獲取重復的出現次數
Set<String> uniqueSet = new HashSet<String>(list);
for (String temp : uniqueSet) {
if(Collections.frequency(list, temp)==1) {
System.out.println(temp);
}
}
這將從列表中返回唯一元素。
如何嘗試 jdk8 的流 API,如下所示:
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FiindUnique {
public static void main(String[] args) {
System.out.println("Hello World");
Collection<String> list = Arrays.asList("A", "B", "C", "D", "A", "B", "C");
//solution 1
List<String> distinctElements = list.stream().filter(name -> Collections.frequency(list, name) == 1).collect(Collectors.toList());
System.out.println(distinctElements);
//Solution 2
List<String> distinctElements2 = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1)
.map(e -> e.getKey())
.collect(Collectors.toList());
System.out.println(distinctElements2);
}
}
通過二分查找找到反轉點,即唯一數偶數和奇數索引前的數相同,唯一數后奇數和偶數的數相同,所以我們可以進行二分查找來找到反演點時間復雜度為 log(N)
您是否假設數組已排序? 這應該會更快。
HashSet<Integer> s = new HashSet<Integer>();
for ( Integer i : ints){
if ( s.contains(i)){
s.remove(i); // remove dups
}
else{
s.add(i); //add uniques
}
}
for ( Integer unique: s){
// should contain one value
System.out.println(unique);// 777777
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.