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