Arrays 例如,第一个数组中的12的索引为0,而排序数组中的索引为6 比较完成后,从两个数组中删除元素

Arrays 例如,第一个数组中的12的索引为0,而排序数组中的索引为6 比较完成后,从两个数组中删除元素,arrays,algorithm,Arrays,Algorithm,除了使用BST,我们还可以通过对合并排序算法进行一些修改(在O(n*logn)时间内)来优化解决这个问题 如果您更仔细地观察这个问题,您可以说,在这个问题中,我们需要计算每个元素所需的反转数,以使数组按升序排序,对吗 所以这个问题可以用分治范式来解决。在这里,您需要维护一个辅助数组,用于存储所需的反转计数(即,在其右侧小于它的元素) 下面是一个python程序: def mergeList(arr, pos, res, start, mid, end): temp = [0]*len(a

除了使用BST,我们还可以通过对合并排序算法进行一些修改(在O(n*logn)时间内)来优化解决这个问题

如果您更仔细地观察这个问题,您可以说,在这个问题中,我们需要计算每个元素所需的反转数,以使数组按升序排序,对吗

所以这个问题可以用分治范式来解决。在这里,您需要维护一个辅助数组,用于存储所需的反转计数(即,在其右侧小于它的元素)

下面是一个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)
def合并列表(arr、pos、res、start、mid、end):
温度=[0]*len(arr)
对于范围内的i(开始、结束+1):
温度[i]=位置[i]
cur=开始
leftcur=开始
rightcur=mid+1

而leftcur修改了合并排序(已测试代码)

需要
O(nlogn)
时间

public class MergeSort {
    static HashMap<Integer, Integer> valueToLowerCount = new HashMap<Integer, Integer>();

    public static void main(String[] args) {
        int []                 arr = new int[] {50, 33, 37, 26, 58, 36, 59};
        int [] lowerValuesOnRight  = new int[] {4,   1,  2,  0,  1,  0,  0};

        HashMap<Integer, Integer> expectedLowerCounts = new HashMap<Integer, Integer>();
        idx = 0;
        for (int x: arr) {
            expectedLowerCounts.put(x, lowerValuesOnRight[idx++]);
        }
        
        for (int x : arr) valueToLowerCount.put(x, 0);
        
        mergeSort(arr, 0, arr.length-1);
        
        //Testing       
        Assert.assertEquals("Count lower values on right side", expectedLowerCounts, valueToLowerCount);
    }
    public static void mergeSort(int []arr, int l, int r) {
        if (r <= l) return;
        int mid = (l+r)/2;
        mergeSort(arr, l, mid);
        mergeSort(arr, mid+1, r);
        mergeDecreasingOrder(arr, l, mid, r);
    }
    public static void mergeDecreasingOrder(int []arr, int l, int lr, int r) {
        int []leftArr = Arrays.copyOfRange(arr, l, lr+1);
        int []rightArr = Arrays.copyOfRange(arr, lr+1, r+1);
        int indexArr = l;
        int i = 0, j = 0;
        while (i < leftArr.length && j < rightArr.length) {
            if (leftArr[i] > rightArr[j]) {
                valueToLowerCount.put(leftArr[i], valueToLowerCount.get(leftArr[i]) + rightArr.length - j);
                arr[indexArr++] = leftArr[i++];
            }else {
                arr[indexArr++] = rightArr[j++];
            }
        }
        while (i < leftArr.length)  { 
            arr[indexArr++] = leftArr[i++]; 
        }
        while (j < rightArr.length) {
            arr[indexArr++] = rightArr[j++];
        }
    }   
}

if(leftArr[i]
这是天真的O(n^2)方法。。我想知道对于sameit的不是O(n^2)而是O(n*(n-1)),不是有任何O(nlogn)方法吗?常数值不会改变渐近增长率!如果内部循环从0变为arraylength,它将是n^2,但它不是,所以它更少…不,它不起作用。第二个递归调用中的pivot需要知道“另一半”,但事实并非如此。好主意,恐怕还是不行。
less
中的元素需要知道
less
中的所有元素,而不仅仅是轴。不,这不起作用。首先要构建树,现在假设控件转到if(t->key>key)返回count\u large(t->left\u child,key,current\u large+(t->right\u child->size)+1);在搜索任何元素时。。问题是(T->right\u child->size)+1);将包括在搜索元素之前插入的元素。@RamanBhatia它将起作用。对于从右侧开始的每个元素,(1)增加该元素的计数并更新树,(2)查找累积计数。进行查找时,树只包含当前元素右侧的项和元素本身。是的。。这就是我发布的内容(编辑了这个问题,并在那里发布了我的解决方案),我将您的“当您搜索节点(从根到达节点)”误认为是在为每个元素构建整个树之后进行搜索。。我的坏…@RamanBhatia:+1问。在“(T->right\u child->size)”中,大小是什么意思?它是节点中的一个特殊字段还是其他内容。。当a-z表示“搜索节点时(从根到达)存储在该节点根的子树元素数”时,他是什么意思。请用少量的输入数据进行解释。谢谢你advance@Imposter:“T->right_child”是指向树中节点*T的右子节点的指针。我们将以节点(例如*T)为根的子树的大小存储在名为“size”的变量中;所以“T->right\u child->size”表示以*T的右子树为根的子树的大小。该算法只是在BST中搜索一个键,我们只需计算大于键且位于下一个子树(左或右)之外的元素的数量。您将在这一行获得一个编译数组“greaterThan[i]=m.end()-iter;”不能减去映射迭代器。如果一个[i],该程序将中断,但从数组中删除将需要O(n)。不是吗??那么总体复杂度将是O(n^2)。如果我错了,请纠正我。我们还可以使用改进的mergesort(分治范式)在O(nlogn)时间内优化解决这个问题。示例只是请注意,虽然使用BST可以工作,但最坏情况下的复杂性将是O(n^2)输入数组已排序。(因为BST将完全倾斜)
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)
}
def count_next_smaller_elements(xs):
    # prepare list "ys" containing item's 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's 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]
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;
}
auto i = m.find(element);
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;
}
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)
public class MergeSort {
    static HashMap<Integer, Integer> valueToLowerCount = new HashMap<Integer, Integer>();

    public static void main(String[] args) {
        int []                 arr = new int[] {50, 33, 37, 26, 58, 36, 59};
        int [] lowerValuesOnRight  = new int[] {4,   1,  2,  0,  1,  0,  0};

        HashMap<Integer, Integer> expectedLowerCounts = new HashMap<Integer, Integer>();
        idx = 0;
        for (int x: arr) {
            expectedLowerCounts.put(x, lowerValuesOnRight[idx++]);
        }
        
        for (int x : arr) valueToLowerCount.put(x, 0);
        
        mergeSort(arr, 0, arr.length-1);
        
        //Testing       
        Assert.assertEquals("Count lower values on right side", expectedLowerCounts, valueToLowerCount);
    }
    public static void mergeSort(int []arr, int l, int r) {
        if (r <= l) return;
        int mid = (l+r)/2;
        mergeSort(arr, l, mid);
        mergeSort(arr, mid+1, r);
        mergeDecreasingOrder(arr, l, mid, r);
    }
    public static void mergeDecreasingOrder(int []arr, int l, int lr, int r) {
        int []leftArr = Arrays.copyOfRange(arr, l, lr+1);
        int []rightArr = Arrays.copyOfRange(arr, lr+1, r+1);
        int indexArr = l;
        int i = 0, j = 0;
        while (i < leftArr.length && j < rightArr.length) {
            if (leftArr[i] > rightArr[j]) {
                valueToLowerCount.put(leftArr[i], valueToLowerCount.get(leftArr[i]) + rightArr.length - j);
                arr[indexArr++] = leftArr[i++];
            }else {
                arr[indexArr++] = rightArr[j++];
            }
        }
        while (i < leftArr.length)  { 
            arr[indexArr++] = leftArr[i++]; 
        }
        while (j < rightArr.length) {
            arr[indexArr++] = rightArr[j++];
        }
    }   
}
if (leftArr[i] > rightArr[j])
if (leftArr[i] < rightArr[j])