Найти дубликаты в двух массивах

1

Мой вопрос был связан с поиском дубликатов в двух массивах.

array1 = [1,2,4,6,9,50,34];
array2 = [1,5,4,50,24,78,34];

Я знаю, что код для этого является использование двух for петель:

for(int i=0; i<arr1.length; i++){
    for(int j=0; j<arr2.length; j++) {
        if(arr1[i]==arr2[j]) {
            System.out.println(arr1[i]);
        }
    }
}

Интервьюер попросил лучшего метода с большим количеством итераций. Могу ли я получить какие-либо предложения по этому поводу?

  • 2
    Что значит «с большой итерацией»?
  • 0
    Вы ищете «сетку пересечения», которая имеет много разных подходов. Но ИМХО их реализации более сложны, чем этот трехстрочный цикл, даже если их сложность намного ниже.
Теги:

7 ответов

1
Лучший ответ

Я снова сделал тесты... набор и карты действительно намного быстрее, чем циклы

private static int size = 100000;

public static void main(String[] args) {
    int[] array1 = new int[size];
    int[] array2 = new int[size];

    for (int i = 0; i < size; i++) {
        array1[i] = i;
        array2[i] = i + i;
    }

    System.out.println("starting set");
    startTimer();
    compareAgainstSet(array1, array2);
    long set = stopTimer();
    System.out.println("against set: " + set + "ms\n");

    System.out.println("starting map");
    startTimer();
    compareAgainstMap(array1, array2);
    long map = stopTimer();
    System.out.println("against hashmap: " + map + "ms\n");

    System.out.println("starting loops with break");
    startTimer();
    twoLoopsWithBreak(array1, array2);
    long loopsBreak = stopTimer();
    System.out.println("2 loops with break: " + loopsBreak + "ms\n");

    System.out.println("starting loops without break");
    startTimer();
    twoLoopsWithoutBreak(array1, array2);
    long loops = stopTimer();
    System.out.println("2 loops without break: " + loops + "ms\n");

}

private static void twoLoopsWithoutBreak(int[] arr1, int[] arr2) {
    ArrayList<Integer> doubles = new ArrayList<>();
    for (int i : arr1) {
        for (int j : arr2) {
            if (i == j) {
                doubles.add(i);
            }
        }
    }
}

private static void twoLoopsWithBreak(int[] arr1, int[] arr2) {
    ArrayList<Integer> doubles = new ArrayList<>();
    for (int i : arr1) {
        for (int j : arr2) {
            if (i == j) {
                doubles.add(i);
                break;
            }
        }
    }
}

private static void compareAgainstSet(int[] arr1, int[] arr2) {
    ArrayList<Integer> doubles = new ArrayList<>();
    Set<Integer> set1 = new HashSet<Integer>();
    for (int i : arr1) {
        set1.add(i);
    }
    for (int i : arr2) {
        if (set1.contains(i)) {
            doubles.add(i);
        }
    }
}

private static void compareAgainstMap(int[] arr1, int[] arr2) {
    ArrayList<Integer> doubles = new ArrayList<>();
    HashMap<Integer, Integer> hashmap = new HashMap<Integer, Integer>();
    for (int i : arr1) {
        hashmap.put(i, 0);
    }
    for (int i : arr2) {
        if (hashmap.containsKey(i)) {
            doubles.add(i);
        }
    }
}

private static long startTime;

private static void startTimer() {
    startTime = System.currentTimeMillis();
}

private static long stopTimer() {
    return System.currentTimeMillis() - startTime;
}
  • 0
    Спасибо за решение ...
3

Код с двумя циклами - O (m * n), где m и n - размеры массива. Вы можете сделать это лучше, если вы поместите содержимое одного массива в контейнер на основе хэша, скажем, HashSet<T>, а затем просмотрите элементы второго массива, проверяя, находятся ли они в хэш-наборе или нет. Это имеет сложность O (m + n), т.е. линейное по общему числу элементов в обоих массивах.

1
import java.util.*;
public class Duplicate {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    int array1[]= {1,2,4,6,9,50,34};
    int array2[]= {1,5,4,50,24,78,34};

    HashSet<Integer> hashValue=new HashSet<>();
    for(int i=0;i<array1.length;i++) {
        hashValue.add(array1[i]);
    }

    for(int j=0;j<array2.length;j++) {
        if(hashValue.contains(array2[j])) {
            System.out.println("the duplicate value is  "+array2[j]);
        }
    }


}

}

1

Как сказал dasblinkenlight передо мной:

public static void main(String[] args) {
        int[] arr1 = new int[] { 10, 3, 4, 20};
        int[] arr2 = new int[] { 10, 20, 30 };

        //convert arr1 to java.util.Set
        Set<Integer> set1 = new HashSet<Integer>();
        for (int i : arr1) {
            set1.add(i);
        }
        // print the duplicates
        for (int i : arr2) {
            if (set1.contains(i)) {
                System.out.println(i); // print 10 20
            }
        }
    }
0

Если вам не нужны два цикла. Затем вы можете использовать хеш-таблицу. Итерируйте первый массив и вставьте в hastable. При повторении второго массива в хеш-таблицу, проверьте наличие ключа, если он есть, то он дублируется иначе.

При таком подходе временная сложность будет уменьшаться до O (kn), где k - постоянная, которая представляет собой количество массивов, которые у вас есть, но дополнительная сложность пространства будет увеличена.

0

Почему бы просто не использовать array_intersect?

$a = array(1, 2, 5, 10, 15, 16);
$b = array(1, 4, 5, 6, 10, 13, 15, 19);

print_r(array_intersect($a, $b));

Упс, я жестко это был PHP, а не JS...

Затем: Как получить пересечение между двумя массивами как новый массив?

  • 0
    Это тоже не JS, а просто Java :-)
0

Для вашего решения требуется время O(n^2) (если n - длина большего из двух массивов).

Лучшим решением было бы сортировать два массива - O(n log(n))
а затем найти дубликаты в одной итерации по обоим сортированным массивам - O(n).
Общее время работы будет O(n log(n)).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню