Это легко сделать с помощью бинарного дерева поиска.Вам необходимо сохранить сумму индексов узлов, присутствующих в правом поддереве, и количества узлов, присутствующих в правом поддереве.Таким образом, всякий раз, когда вы вставляете новый узел, и он идет влево от любого узла, расстояние будет обновляться на
`(no of nodes in right subtree* index of val which is to be inserted) - sum of indices of nodes present in right subtree)`
Давайте пройдем для ввода 5, 2, 3, 4, 1
первый узел будетбыть с val 5 и расстоянием до настоящего момента 0;
Ситуация после вставки 2
sizeOfRightSubTree : 1
index: 1
sumOfIndicesOnRight: 0
inserted: 2, distance: 1
После вставки 3
sizeOfRightSubTree : 1
index: 2
sumOfIndicesOnRight: 0
inserted: 3, distance: 3
После вставки 4
sizeOfRightSubTree : 1
index: 3
sumOfIndicesOnRight: 0
inserted: 4, distance: 6
После вставки 1. Обратите внимание, что он должен пройти влево дважды, чтобы достичь своей конечной позиции, поэтому расстояние обновляется дважды.sizeOfRightSubTree : 1
index: 4
sumOfIndicesOnRight: 0
sizeOfRightSubTree : 3
index: 4
sumOfIndicesOnRight: 6
inserted: 1, distance: 16
Ниже приведен код Java
public class DistanceFromSortedArray
{
class Node {
int val;
Node left;
Node right;
int index;
int sumOfIndicesOnRight;
int sizeOfRightSubTree;
Node(int num, int index)
{
this.val = num;
this.index = index;
sizeOfRightSubTree = 1;
sumOfIndicesOnRight = index;
}
void addIndexToRight(int index)
{
sizeOfRightSubTree++;
sumOfIndicesOnRight += index;
}
int distance(int index)
{
return sizeOfRightSubTree*index - sumOfIndicesOnRight;
}
}
private Node head;
private int distance;
public int calculate(int[] nums){
head = null;
distance = 0;
for(int i=0; i<nums.length; i++){
insert(nums[i], i);
}
return distance;
}
private void insert(int num, int index)
{
Node toInsert = new Node(num, index);
if(head == null){
head = toInsert;
return;
}
Node current = head;
Node previous = null;
while (current != null){
previous = current;
if(current.val > num){
distance += current.distance(index);
current = current.left;
}
else {
current.addIndexToRight(index);
current = current.right;
}
}
if(previous.val > num){
previous.left = toInsert;
}
else {
previous.right = toInsert;
}
}
}
Вот несколько тестов
@Test
public void calculate()
{
int[] nums = {5, 2, 3, 4, 1};
assertEquals(16, new DistanceFromSortedArray().calculate(nums));
}
@Test
public void reverseCalculate()
{
int[] nums = {5, 4, 3, 2, 1};
assertEquals(20, new DistanceFromSortedArray().calculate(nums));
}
@Test
public void SizeTwoCalculate()
{
int[] nums = {4, 5};
assertEquals(0, new DistanceFromSortedArray().calculate(nums));
int [] nums2 = {5, 4};
assertEquals(1, new DistanceFromSortedArray().calculate(nums2));
}
@Test
public void twistedCalculate()
{
int[] nums = {8, 3, 6, 5, 7, 1};
assertEquals(26, new DistanceFromSortedArray().calculate(nums));
}
@Test
public void AllSameCalculate()
{
int[] nums = {1, 1, 1, 1, 1, 1};
assertEquals(0, new DistanceFromSortedArray().calculate(nums));
}