Заданный массив для каждого элемента, узнать общее количество элементов, меньшее его, которые справа от него
Ранее я задавал вопрос Учитывая массив, узнайте следующий меньший элемент для каждого элемента
теперь, я пытался узнать, если есть какой-то способ узнать "заданный массив" для каждого элемента, узнать общее количество элементов, меньшее, чем оно, которые справа от него ",
например, массив [4 2 1 5 3] должен давать [3 1 0 1 0]??
[EDIT]
Я разработал решение, пожалуйста, взгляните на него и сообщите мне, есть ли какая-либо ошибка.
1 Создайте сбалансированные элементы вставки BST, перемещая массив справа налево
2 BST выполнен таким образом, что каждый элемент имеет размер дерева, внедренного в этот элемент
3 Теперь, когда вы ищете правильную позицию для вставки какого-либо элемента, учтите общий размер поддерева, корневого в левой части сиблинга + 1 (для родителя), если вы переместитесь вправо
Теперь, поскольку счет вычисляется во время вставки элемента и что мы движемся справа налево, мы получаем точное количество элементов, меньшее, чем данный элемент, появляющийся после него.
Ответы
Ответ 1
Его можно решить в O (n log n).
Если в BST вы сохраняете количество элементов поддерева, внедренных в этот node при поиске node (до достижения этого из корня), вы можете подсчитать количество элементов, большее или меньшее, чем в пути
int count_larger(node *T, int key, int current_larger){
if (*T == nil)
return -1;
if (T->key == key)
return current_larger + (T->right_child->size);
if (T->key > key)
return count_larger(T->left_child, key, current_larger + (T->right_child->size) + 1);
return count_larger(T->right_child, key, current_larger)
}
** например, если это является нашим деревом, и мы ищем ключ 3, count_larger будет вызываться для:
- > (node 2, 3, 0)
- > (node 4, 3, 0)
--- > (node 3, 3, 2)
и окончательный ответ будет 2, как ожидалось.
Ответ 2
Предположим, что массив равен 6, -1,5,10,12,4,1,3,7,50
Шаги
1. Мы начинаем строить BST с правого конца массива. Поскольку нас интересуют все элементы, подходящие для любого элемента.
2. Предположим, что мы сформировали парное дерево решений до 10.
![enter image description here]()
3. Теперь при вставке 5 мы обходим дерево и вставляем справа от 4.
Обратите внимание, что каждый раз, когда мы проходим справа от любого node, мы увеличиваем на 1 и добавляем no. элементов в левом поддереве того, что node.
например:
за 50 это 0 для 7 это 0 для 12 это 1 правое перемещение + левый размер 7 = 1 + 3 = 4
для 10 таких же, как указано выше.
для 4 это 1 + 1 = 2
При построении bst мы можем легко поддерживать размер левого поддерева для каждого node, просто поддерживая соответствующую ему переменную и увеличивая ее на 1 каждый раз, когда node пересекает ее слева.
Следовательно, решение Среднее значение O (nlogn).
Мы можем использовать другие оптимизации, такие как предопределение, сортировка массива в порядке убывания
найдите группы элементов в порядке убывания, рассматривая их как одиночные.
Ответ 3
Я думаю, что можно сделать это в O(nlog(n))
с измененной версией quicksort. В основном каждый раз, когда вы добавляете элемент в меньшее, вы проверяете, является ли этот элемент рангом в исходном массиве, превосходящем ранг текущего стержня. Это может выглядеть как
oldrank -> original positions
count -> what you want
function quicksort('array')
if length('array') ≤ 1
return 'array' // an array of zero or one elements is already sorted
select and remove a pivot value 'pivot' from 'array'
create empty lists 'less' and 'greater'
for each 'x' in 'array'
if 'x' ≤ 'pivot'
append 'x' to 'less'
if oldrank(x) > = oldrank(pivot) increment count(pivot)
else
append 'x' to 'greater'
if oldrank(x) < oldrank(pivot) increment count(x) //This was missing
return concatenate(quicksort('less'), 'pivot', quicksort('greater')) // two recursive calls
EDIT:
На самом деле это можно сделать с использованием любого алгоритма сортировки на основе сравнения. Каждый раз, когда вы сравниваете два элемента таким образом, чтобы относительное упорядочение между ними изменилось, вы увеличиваете счетчик большего элемента.
Оригинальный псевдокод в Википедии.
Ответ 4
Вы также можете использовать двоичное дерево индексов
int tree[1000005];
void update(int idx,int val)
{
while(idx<=1000000)
{
tree[idx]+=val;
idx+=(idx & -idx);
}
}
int sum(int idx)
{
int sm=0;
while(idx>0)
{
sm+=tree[idx];
idx-=(idx & -idx);
}
return sm;
}
int main()
{
int a[]={4,2,1,5,3};
int s=0,sz=6;
int b[10];
b[sz-1]=0;
for(int i=sz-2;i>=0;i--)
{
if(a[i]!=0)
{
update(a[i],1);
b[i]=sum(a[i]-1)+s;
}
else s++;
}
for(int i=0;i<sz-1;i++)
{
cout<<b[i]<<" ";
}
return 0;
}
Ответ 5
//some array called newarray
for(int x=0; x <=array.length;x++)
{
for(int y=x;y<array.length;y++)
{
if(array[y] < array[x])
{
newarray[x] = newarray[x]+1;
}
}
}
что-то вроде этого, где array - ваш входной массив и newarray ваш выходной массив
убедитесь, что все правильно правильно (0 для значений newarrays)
Ответ 6
Другой подход без использования дерева.
- Построить другой отсортированный массив. Например, для входного массива {12, 1, 2, 3, 0, 11, 4} он будет {0, 1, 2, 3, 4, 11, 12}
- Теперь сравните положение каждого элемента из входного массива с отсортированным массивом. Например, 12 в первом массиве имеют индекс 0, а отсортированный массив - как 6
- После выполнения сравнения удалите элемент из обоих массивов
Ответ 7
Вы также можете использовать массив вместо двоичного дерева поиска.
def count_next_smaller_elements(xs):
# prepare list "ys" containing item numeric order
ys = sorted((x,i) for i,x in enumerate(xs))
zs = [0] * len(ys)
for i in range(1, len(ys)):
zs[ys[i][1]] = zs[ys[i-1][1]]
if ys[i][0] != ys[i-1][0]: zs[ys[i][1]] += 1
# use list "ts" as binary search tree, every element keeps count of
# number of children with value less than the current element value
ts = [0] * (zs[ys[-1][1]]+1)
us = [0] * len(xs)
for i in range(len(xs)-1,-1,-1):
x = zs[i]+1
while True:
us[i] += ts[x-1]
x -= (x & (-x))
if x <= 0: break
x = zs[i]+1
while True:
x += (x & (-x))
if x > len(ts): break
ts[x-1] += 1
return us
print count_next_smaller_elements([40, 20, 10, 50, 20, 40, 30])
# outputs: [4, 1, 0, 2, 0, 1, 0]
Ответ 8
Вместо BST вы можете использовать stl-карту.
Начните вставлять справа.
После вставки элемента найдите его итератор:
auto i = m.find(element);
Затем вычтите его из m.end(). Это дает вам количество элементов на карте, которые больше текущего элемента.
map<int, bool> m;
for (int i = array.size() - 1; i >= 0; --i) {
m[array[i]] = true;
auto iter = m.find(array[i])
greaterThan[i] = m.end() - iter;
}
Надеюсь, что это помогло.
Ответ 9
Кроме использования BST, мы также можем решить эту проблему оптимально, выполнив некоторую модификацию в алгоритме сортировки слиянием (в O (n * logn) time).
Если вы более внимательно наблюдаете за этой проблемой, вы можете сказать, что в задаче нам нужно подсчитать количество инверсий, необходимых для каждого элемента, чтобы отсортировать массив в порядке возрастания, правильно?
Таким образом, эту проблему можно решить с помощью парадигмы Divide и Conquer. Здесь вам нужно сохранить вспомогательный массив для хранения требуемого количества инверсий (т.е. Элементов, меньших, чем у него в правой части).
Ниже приведена программа python:
def mergeList(arr, pos, res, start, mid, end):
temp = [0]*len(arr)
for i in range(start, end+1):
temp[i] = pos[i]
cur = start
leftcur = start
rightcur = mid + 1
while leftcur <= mid and rightcur <= end:
if arr[temp[leftcur]] <= arr[temp[rightcur]]:
pos[cur] = temp[leftcur]
res[pos[cur]] += rightcur - mid - 1
leftcur += 1
cur += 1
else:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
while leftcur <= mid:
pos[cur] = temp[leftcur]
res[pos[cur]] += end - mid
cur += 1
leftcur += 1
while rightcur <= end:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
def mergeSort(arr, pos, res, start, end):
if start < end:
mid = (start + end)/2
mergeSort(arr, pos, res, start, mid)
mergeSort(arr, pos, res, mid+1, end)
mergeList(arr, pos, res, start, mid, end)
def printResult(arr, res):
print
for i in range(0, len(arr)):
print arr[i], '->', res[i]
if __name__ == '__main__':
inp = input('enter elements separated by ,\n')
inp = list(inp)
res = [0]*len(inp)
pos = [ind for ind, v in enumerate(inp)]
mergeSort(inp, pos, res, 0, len(inp)-1)
printResult(inp, res)
Время: O (n * logn)
Пространство: O (n)