Подсчет инверсий в подмассивах
Учитывая массив arr[] , цель состоит в том, чтобы подсчитать количество инверсий во всех подмассивах. Инверсия — это пара индексов i и j , таких что i > j и arr[i] < arr[j] . Подмассив от индекса x до y ( x<= y) состоит из элементов arr[x], arr[x+1], …, arr[y] . Массив arr[] также может содержать повторяющиеся элементы.
Примеры:
Input: arr[] = {3, 6, 1, 6, 5, 3, 9}
Output:
0 0 2 2 4 7 7
0 0 1 1 3 6 6
0 0 0 0 1 3 3
0 0 0 0 1 3 3
0 0 0 0 0 1 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Explanation:
The element in the i’th row and j’th column of the output denotes the number of inversions from index i to j (inclusive). Consider i = 1 and j = 4 (assuming 0-based indexing), the number of inversions in the subarray {6, 1, 6, 5} is 3. The element pairs are (6, 1), (6, 5) and (6, 5) (from the second 6).Input: arr[] = {3, 2, 1}
Output:
0 1 3
0 0 1
0 0 0
Explanation:
From index 0 to 1 there is 1 inversion, from index 2 to 3 there is 1 inversion and from index 0 to 2 there are 3 inversions. The i’th row and j’th column of the output is 0 if i >= j.
Наивный подход. Наивный подход заключается в создании всех возможных подмассивов и подсчете количества инверсий в каждом из подмассивов.
Ниже приведена реализация вышеуказанного подхода:
Временная сложность: O(N 4 )
Вспомогательное пространство: O(N 2 )
Эффективный подход: приведенный выше метод можно немного оптимизировать, используя приведенный здесь метод, чтобы найти количество инверсий в подмассиве. Сначала посмотрите некоторые наблюдения для решения этой проблемы:
First create a 2d array greater[][], where greater[i][j] denotes the number of elements in the range i to j which are greater than arr[i]. Iterate over the array and for each element, find the number of elements to its right which are less than the element. This can be done using a naive approach in O(N^2). Now to find the number of inversions in a range say x to y, the answer will be greater[x][y] + greater[x+1][y] + … + greater[y-1][y] + greater[y][y].
With the greater[][] table this value can be calculated in O(n) for each sub-array resulting in a complexity of O(n^3).(There are O(n^2) sub-array, and it takes O(n) time to compute the number of inversions in each sub-array). To find this value in O(1) each time build a prefix sum table from the greater[][] table where prefix[i][j] denotes the value of greater[0][j] + greater[1][j] + … + greater[i][j]. This table can also be built in O(N^2) time. Now the answer for each sub-array from x to y (inclusive) would become prefix[y][y] – prefix[x-1][y] if x >= 1 and prefix[y][y] if x = 0.
Следуйте шагу ниже, чтобы решить эту проблему:
- Инициализировать массивы больших[][] для хранения где больше[i][j] обозначает количество элементов в диапазоне от i до j , которые больше, чем arr[i], префикс[][] для хранения суммы префиксов для подмассива и инверсий[][] для хранения количество инверсий.
- Итерация в диапазоне [0, N-1] с использованием переменной i :
- Выполните итерацию в диапазоне [i+1, N-1] , используя переменную j:
- Обновить большее[i][j] как большее[i][j-1]
- Если arr[i] больше, чем arr[j], то Увеличивайте Greater[i][j] на 1.
- Выполните итерацию в диапазоне [i+1, N-1] , используя переменную j:
- Итерация в диапазоне [0, N-1] с использованием переменной i :
- Обновить префикс[0][j] как больший[0][j]
- Выполнить итерацию в диапазоне [1, N-1] , используя переменную j и обновить префикс [i][j] как префикс [i-1][j] + больше[i][j].
- Итерация в диапазоне [0, N-1] с использованием переменной i :
- Итерация в диапазоне [i, N-1] с использованием переменной j:
- Если i = 0, то обновить инверсии[i][j] как префикс [j][j]
- В противном случае обновите инверсии[i][j] как префикс[j][j] + префикс[i-1][j].
- Итерация в диапазоне [i, N-1] с использованием переменной j:
- После выполнения вышеуказанных шагов выведите массив inversions[][] в качестве ответа.
Ниже приведена реализация вышеуказанного подхода:
Временная сложность: O(N 2 )
Космическая сложность: O(N 2 )
Заметки-
- Некоторое пространство можно сэкономить, построив таблицу префиксов[][] поверх таблицы больших[][], но порядок останется прежним.
- Невозможно работать лучше, чем O (N ^ 2), если вы хотите найти точное количество инверсий во всех подмассивах, поскольку количество подмассивов всегда равно O (N ^ 2).