Мне было интересно, какова временная сложность функции duplicate , потому что я думал, что это O (nlogn) из-за использования алгоритма двоичного поиска и в то же время реализация цикла while для поиска по левой и правой сторонам местоположения первого экземпляра внутри массива, где было найдено значение, чтобы увидеть, не дублируется ли оно внутри отсортированного массива. Я хотел бы знать, есть ли это O (logn) , потому что я думал, что цикл while на самом деле не перебирает все элементы, а только те, которые находятся рядом со значением, которое мы ищем, чтобы увидеть, дублируется ли оно. Буду признателен за любой совет, сделав это O (logn) , если это не так.

public class Problem2 {

    public static void main(String[] args) {
        
        int[] arrayA = {-1, 2, 3, 5, 6, 6, 6, 9, 10};
        
        int repeatedValue = 6;
        
        System.out.println(duplicates(arrayA, repeatedValue));
    }
    
    public static int duplicates(int[] a, int x){
        
        int counter = 0;                 //counter for duplicates.
        int index = binarySearch(a, x);  // index = 4 where x is.
        int leftIndex = index - 1;       // leftIndex = 3
        int rightIndex = index + 1;      // rightIndex = 5
        
        //Condition incase value does not exist.
        if(index == -1)
            return -1;
        
        //While loop to check left and right side of index for duplicates.
        while(a[leftIndex] == x || a[rightIndex] == x){
            
            if(a[leftIndex] == x){
                counter++;
                leftIndex--;
                
            }
            else if(a[rightIndex] == x){
                counter++;
                rightIndex++;
                
            }
           
        }
        
        //returning the counter plus one because we did not count the first instance
        //when it was searched.
        return counter + 1;
    }
    
    public static int binarySearch(int[] a, int x){
        
        int low = 0, high = a.length - 1;
        
        while(low <= high){
            
            int mid = (low + high) / 2;
            
            if(a[mid] < x)
                low = mid + 1;
            else if(a[mid] > x)
                high = mid - 1;
            else
                return mid;
        }
        return -1;
    }
}
1
Ale 20 Май 2021 в 02:34

1 ответ

Лучший ответ

Это не O(n*logn), потому что вы НЕ выполняете линейный поиск FOR для каждого двоичного поиска: вы выполняете линейный поиск И бинарный поиск.

I либо O(logn), либо O(n) в зависимости от того, сколько существует дубликатов вашего целевого числа. Поскольку O(n) больше, чем O(logn), ваша сложность наихудшего случая равна O(n).

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

Если в среднем количество дубликатов в списке размера n (который вы фактически ищете) меньше, чем logn, у вас будет O(logn) сложность в среднем случае.

Что касается совета, как это сделать O(logn):

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

Измените этап предварительного вычисления, чтобы не только отсортировать массив, но также дедуплицировать массив и сохранить количество дубликатов каждого уникального числа в отдельном массиве.

Тогда алгоритм поиска принимает следующий вид:

  1. Бинарный поиск нужного индекса вашего целевого числа
  2. Верните количество дубликатов для числа из отдельного массива с повторяющимися счетчиками, используя индекс, который вы нашли на шаге 1.

Это имеет смысл только в том случае, если вы ищете много разных целевых чисел в одних и тех же входных данных.

3
Erwin Bolwidt 19 Май 2021 в 23:50