Java Массив, Поиск Дубликатов
У меня есть массив, и я ищу дубликаты.
duplicates = false;
for(j = 0; j < zipcodeList.length; j++){
for(k = 0; k < zipcodeList.length; k++){
if (zipcodeList[k] == zipcodeList[j]){
duplicates = true;
}
}
}
однако, этот код не работает, когда нет никаких дубликатов. Почему это?
13 ответов:
на носу ответ..
duplicates=false; for (j=0;j<zipcodeList.length;j++) for (k=j+1;k<zipcodeList.length;k++) if (k!=j && zipcodeList[k] == zipcodeList[j]) duplicates=true;редактировать, чтобы перейти
.equals()на==так как я где-то читал, что вы используетеint, что не было ясно в первоначальном вопросе. Также установитьk=j+1, чтобы вдвое сократить время выполнения, но это все еще O (n2).более быстрый (в пределе) способ
вот хэш подход. Вы должны заплатить за автобоксинг, но это O(n) вместо O (n2). Предприимчивая душа найдите примитивный набор хэшей на основе int (у Apache или Google Collections есть такая вещь, methinks.)
boolean duplicates(final int[] zipcodelist) { Set<Integer> lump = new HashSet<Integer>(); for (int i : zipcodelist) { if (lump.contains(i)) return true; lump.add(i); } return false; }поклонись Хьюлу
посмотреть ответ Хьюла для более или менее O (n) решения, которое, я думаю, нуждается в нескольких шагах add'L:
static boolean duplicates(final int[] zipcodelist) { final int MAXZIP = 99999; boolean[] bitmap = new boolean[MAXZIP+1]; java.util.Arrays.fill(bitmap, false); for (int item : zipcodeList) if (!bitmap[item]) bitmap[item] = true; else return true; } return false; }или просто быть компактными
static boolean duplicates(final int[] zipcodelist) { final int MAXZIP = 99999; boolean[] bitmap = new boolean[MAXZIP+1]; // Java guarantees init to false for (int item : zipcodeList) if (!(bitmap[item] ^= true)) return true; return false; }имеет ли это значение?
Ну, так что я провел небольшой тест, который сомнителен повсюду, но вот код:
import java.util.BitSet; class Yuk { static boolean duplicatesZero(final int[] zipcodelist) { boolean duplicates=false; for (int j=0;j<zipcodelist.length;j++) for (int k=j+1;k<zipcodelist.length;k++) if (k!=j && zipcodelist[k] == zipcodelist[j]) duplicates=true; return duplicates; } static boolean duplicatesOne(final int[] zipcodelist) { final int MAXZIP = 99999; boolean[] bitmap = new boolean[MAXZIP + 1]; java.util.Arrays.fill(bitmap, false); for (int item : zipcodelist) { if (!(bitmap[item] ^= true)) return true; } return false; } static boolean duplicatesTwo(final int[] zipcodelist) { final int MAXZIP = 99999; BitSet b = new BitSet(MAXZIP + 1); b.set(0, MAXZIP, false); for (int item : zipcodelist) { if (!b.get(item)) { b.set(item, true); } else return true; } return false; } enum ApproachT { NSQUARED, HASHSET, BITSET}; /** * @param args */ public static void main(String[] args) { ApproachT approach = ApproachT.BITSET; final int REPS = 100; final int MAXZIP = 99999; int[] sizes = new int[] { 10, 1000, 10000, 100000, 1000000 }; long[][] times = new long[sizes.length][REPS]; boolean tossme = false; for (int sizei = 0; sizei < sizes.length; sizei++) { System.err.println("Trial for zipcodelist size= "+sizes[sizei]); for (int rep = 0; rep < REPS; rep++) { int[] zipcodelist = new int[sizes[sizei]]; for (int i = 0; i < zipcodelist.length; i++) { zipcodelist[i] = (int) (Math.random() * (MAXZIP + 1)); } long begin = System.currentTimeMillis(); switch (approach) { case NSQUARED : tossme ^= (duplicatesZero(zipcodelist)); break; case HASHSET : tossme ^= (duplicatesOne(zipcodelist)); break; case BITSET : tossme ^= (duplicatesTwo(zipcodelist)); break; } long end = System.currentTimeMillis(); times[sizei][rep] = end - begin; } long avg = 0; for (int rep = 0; rep < REPS; rep++) { avg += times[sizei][rep]; } System.err.println("Size=" + sizes[sizei] + ", avg time = " + avg / (double)REPS + "ms"); } } }С NSQUARED:
Trial for size= 10 Size=10, avg time = 0.0ms Trial for size= 1000 Size=1000, avg time = 0.0ms Trial for size= 10000 Size=10000, avg time = 100.0ms Trial for size= 100000 Size=100000, avg time = 9923.3msС HashSet
Trial for zipcodelist size= 10 Size=10, avg time = 0.16ms Trial for zipcodelist size= 1000 Size=1000, avg time = 0.15ms Trial for zipcodelist size= 10000 Size=10000, avg time = 0.0ms Trial for zipcodelist size= 100000 Size=100000, avg time = 0.16ms Trial for zipcodelist size= 1000000 Size=1000000, avg time = 0.0msС BitSet
Trial for zipcodelist size= 10 Size=10, avg time = 0.0ms Trial for zipcodelist size= 1000 Size=1000, avg time = 0.0ms Trial for zipcodelist size= 10000 Size=10000, avg time = 0.0ms Trial for zipcodelist size= 100000 Size=100000, avg time = 0.0ms Trial for zipcodelist size= 1000000 Size=1000000, avg time = 0.0msBITSET побед!
но только на волосок... .15 мс находится в пределах ошибки для
currentTimeMillis()и есть некоторые зияющие дыры в моем эталоном. Обратите внимание, что для любого списка длиной более 100000, вы можете просто вернутьtrueпотому что будет дубликат. На самом деле, если список является чем-то вроде случайного, вы можете вернуть true WHP для a гораздо более короткий список. А в чем мораль? В пределе наиболее эффективной реализацией является:return true;и вы не будете ошибаться очень часто.
давайте посмотрим, как работает ваш алгоритм:
an array of unique values: [1, 2, 3] check 1 == 1. yes, there is duplicate, assigning duplicate to true. check 1 == 2. no, doing nothing. check 1 == 3. no, doing nothing. check 2 == 1. no, doing nothing. check 2 == 2. yes, there is duplicate, assigning duplicate to true. check 2 == 3. no, doing nothing. check 3 == 1. no, doing nothing. check 3 == 2. no, doing nothing. check 3 == 3. yes, there is duplicate, assigning duplicate to true.лучший алгоритм:
for (j=0;j<zipcodeList.length;j++) { for (k=j+1;k<zipcodeList.length;k++) { if (zipcodeList[k]==zipcodeList[j]){ // or use .equals() return true; } } } return false;
вы можете использовать растровое изображение для повышения производительности с большим массивом.
java.util.Arrays.fill(bitmap, false); for (int item : zipcodeList) if (!bitmap[item]) bitmap[item] = true; else break;обновление: это очень небрежный ответ моего назад в тот же день, сохраняя его здесь только для справки. Вы должны сослаться на отличный андерсой ответ.
потому что вы сравниваете первый элемент массива с самим собой, поэтому он обнаруживает, что есть дубликаты, даже если их нет.
инициализировать k = j+1. Вы не будете сравнивать элементы сами с собой, и вы также не будете дублировать сравнения. Например, j = 0, k = 1 и k = 0, j = 1 сравнивают один и тот же набор элементов. Это позволит удалить сравнение k = 0, j = 1.
не используйте
==использовать.equals.попробуйте вместо этого (если не ошибаюсь, нужно индекс реализовывать
Comparableдля этого, чтобы работать.boolean unique; Set<ZipCode> s = new TreeSet<ZipCode>(); for( ZipCode zc : zipcodelist ) unique||=s.add(zc); duplicates = !unique;
вы также можете работать с Set, который не допускает дубликатов в Java..
for (String name : names) { if (set.add(name) == false) { // your duplicate element } }С помощью метода add () и проверьте возвращаемое значение. Если add () возвращает false, это означает, что элемент не разрешен в наборе, и это ваш дубликат.
public static ArrayList<Integer> duplicate(final int[] zipcodelist) { HashSet<Integer> hs = new HashSet<>(); ArrayList<Integer> al = new ArrayList<>(); for(int element: zipcodelist) { if(hs.add(element)==false) { al.add(element); } } return al; }
Как насчет использования этого метода?
HashSet<Integer> zipcodeSet = new HashSet<Integer>(Arrays.asList(zipcodeList)); duplicates = zipcodeSet.size()!=zipcodeList.length;
@andersoj дал отличный ответ, но я также хочу добавить новый простой способ
private boolean checkDuplicateBySet(Integer[] zipcodeList) { Set<Integer> zipcodeSet = new HashSet(Arrays.asList(zipcodeList)); if (zipcodeSet.size() == zipcodeList.length) { return true; } return false; }в случае, если zipcodeList является int [], вам нужно сначала преобразовать int[] в Integer [] (это не автоматический бокс), code здесь
полный код будет такой:
private boolean checkDuplicateBySet2(int[] zipcodeList) { Integer[] zipcodeIntegerArray = new Integer[zipcodeList.length]; for (int i = 0; i < zipcodeList.length; i++) { zipcodeIntegerArray[i] = Integer.valueOf(zipcodeList[i]); } Set<Integer> zipcodeSet = new HashSet(Arrays.asList(zipcodeIntegerArray)); if (zipcodeSet.size() == zipcodeList.length) { return true; } return false; }надеюсь, что это помогает!
печать всех повторяющихся элементов. выход -1 когда повторяющиеся элементы не найдены.
import java.util.*; public class PrintDuplicate { public static void main(String args[]){ HashMap<Integer,Integer> h = new HashMap<Integer,Integer>(); Scanner s=new Scanner(System.in); int ii=s.nextInt(); int k=s.nextInt(); int[] arr=new int[k]; int[] arr1=new int[k]; int l=0; for(int i=0; i<arr.length; i++) arr[i]=s.nextInt(); for(int i=0; i<arr.length; i++){ if(h.containsKey(arr[i])){ h.put(arr[i], h.get(arr[i]) + 1); arr1[l++]=arr[i]; } else { h.put(arr[i], 1); } } if(l>0) { for(int i=0;i<l;i++) System.out.println(arr1[i]); } else System.out.println(-1); } }
import java.util.Scanner; public class Duplicates { public static void main(String[] args) { Scanner console = new Scanner(System.in); int number = console.nextInt(); String numb = "" + number; int leng = numb.length()-1; if (numb.charAt(0) != numb.charAt(1)) { System.out.print(numb.substring(0,1)); } for (int i = 0; i < leng; i++){ if (numb.charAt(i)==numb.charAt(i+1)){ System.out.print(numb.substring(i,i+1)); } else { System.out.print(numb.substring(i+1,i+2)); } } } }
Comments