Я пытаюсь решить проблему с алгоритмом, но думаю, что мое разрешение не очень хорошее по производительности. Так что, если кто-то может помочь, я буду очень благодарен.

Проблема в том, что у меня есть 3 массива A, B, C. Я хочу знать, сколько элементов находятся в пределах досягаемости каждого B [i] и C [i].

Example:
A = [1,3,5,8]
B = [3,8]
C= [7,8]

So for B[0] and C[0] the answer is 2, because 3 and 5 are within range
and for B[1] and C[1] the answer is 1, because 8 are within range

the result has to be an array of [2,1].

Specifications:
B.length == C.length
B[i] <= C[i]

Я попытался решить эту проблему следующим образом:

static int[] method(int[] A, int[] B, int[] C) {
    Arrays.sort(A);
    int[] result = new int[B.length];
    for (int i = 0; i < B.length; i++) {
        int x = B[i];
        int y = C[i];
        int init = -1;
        int end = -1;
        for (int j = 0; j < A.length; j++) {
            int a = A[j];
            if (a >= x && init == -1) {
                init = j;
            }
            if (a == y && end == -1) {
                end = j;
            }
            if (a > y && end == -1) {
                end = j - 1;
            }
            if (init != -1 && end != -1) {
                break;
            }
        }
        result[i] = end - init + 1;
    }
    return result;
}

Что, вы парни, думаете?

2
tester mi 26 Фев 2018 в 07:27

5 ответов

Лучший ответ

Чтобы добавить что-то к ответу Генри, когда чисел много, алгоритм двоичного поиска, безусловно, лучший. Также кажется, что ваше решение не учитывает повторяющиеся значения в A.

Полнофункциональный код:

static int[] method2(int[] A, int[] B, int[] C) {
    Arrays.sort(A);
    int[] result = new int[B.length];
    for (int i = 0; i < B.length; i++) {
        int posMin = java.util.Arrays.binarySearch(A, B[i]);
        int posMax = java.util.Arrays.binarySearch(A, C[i]);
        if (posMin < 0) { posMin = -(posMin+1);   }
        if (posMax < 0) { posMax = -(posMax+1)-1; }
        result[i] = posMax - posMin +1;
    }
    return result;
}

Из тестов я сделал 100 интервалов и 1 миллион выборок.

Метод = 16368 мс

Method2 = 433мс

0
TrapII 26 Фев 2018 в 11:33

Лучшая процедура зависит от размеров A и B.

Если A очень велико по сравнению с B, лучше не сортировать его. Пройдите через все элементы A и для каждого проверьте все интервалы, если они содержат элемент. Это дает время выполнения O (len A * len B)

С другой стороны, если интервалов много, лучше отсортировать A и использовать двоичный поиск, чтобы найти начальный и конечный индексы для каждого интервала. Это дает время выполнения O (len A * log (len A) + len B * log (len A)).

1
Henry 26 Фев 2018 в 10:50

Вы можете просто увеличивать результат [i] на лету, когда пробегаете массивы B и C.

static int[] method(int[] A, int[] B, int[] C)
{
    Arrays.sort(A);
    int[] result = new int[B.length];
    for (int i = 0; i < B.length; i++)
    {
        for (int j = 0; j < A.length; j++)
        {
            int a = A[j];
            if (B[i] <= a && a <= C[i])
            {
                result[i]++;
            }
            else if (a >= C[i])
            {
                break;
            }
        }
    }
    return result;
}
0
Bryan Patterson 26 Фев 2018 в 05:30
1) Concatenate the array A with B[i] & C[i]. i.e
   new array will be [1,3,5,8,3,7]
2) Sort the new array.
   sorted array [1,3,3,5,7,8]
3) filter out the elements between B[i] & C[i] from the array.
   filtered array [3,3,5,7]
0
AZ_ 26 Фев 2018 в 05:57

Здесь вы идете с Java8

public static int[] doTask(int[] A, int[] B, int[] C) {
    // Arrays.sort(A);

    List<Integer> aList = Arrays.stream(A).boxed().collect(Collectors.toList());

    int result[]=new int[B.length];
    for (int i=0; i < B.length; i++) {
        Integer b = B[i];
        Integer c = C[i];
        List<Integer> aList2 = aList.stream().filter(a -> a >= b && a <= c).collect(Collectors.toList());
        result[i] = aList2.size();
    }

    // System.out.println(result);
    return result;
}

Результат = [2, 1]

0
Mr. Mak 26 Фев 2018 в 06:04