[英]counting number of swaps in insertion sort
在这里给出的问题中,我必须计算总数。 使用插入排序对数组进行排序时所需的交换数。
这是我的方法
#include <stdio.h>
int main()
{
int t, N, swaps, temp, i, j;
scanf("%d", &t);
while(t--){
scanf("%d", &N);
int arr[N];
swaps = 0;
for(i=0; i<N; ++i){
scanf("%d", &temp);
j=i;
while(j>0 && arr[j-1] > temp){
arr[j] = arr[j-1];
++swaps;
--j;
}
arr[j] = temp;
}
printf("%d\n", swaps);
}
return 0;
}
但是,这种解决方案给了时间限制。
我怎样才能使其更快?
并且,该问题还有哪些其他更好的解决方案?
这是一个名为倒数的标准问题
这可以使用O(n * lg(n))中的mergesort解决。 这是我计算反转的代码
int a[200001];
long long int count;
void Merge(int p,int q,int r)
{
int n1,n2,i,j,k,li,ri;
n1=q-p+1;
n2=r-q;
int l[n1+1],rt[n2+1];
for(i=0;i<n1;i++)
l[i]=a[p+i];
for(i=0;i<n2;i++)
rt[i]=a[q+1+i];
l[n1]=LONG_MAX;
rt[n2]=LONG_MAX;
li=0;ri=0;
for(i=p;i<=r;i++)
{
if(l[li]<=rt[ri])
a[i]=l[li++];
else
{
a[i]=rt[ri++];
count+=n1-li;
}
}
}
void mergesort(int p,int r)
{
if(p<r)
{
int q=(p+r)/2;
mergesort(p,q);
mergesort(q+1,r);
Merge(p,q,r);
}
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
count=0;
mergesort(0,n-1);
printf("%lld\n",count);
}
基本上,反转计数的问题是找到编号。 对i和j,其中j> i使得a [i]> a [j]
要了解其背后的想法,您应该了解基本的合并排序算法
理念:
使用分而治之
除法:将序列n的大小分为大小为n / 2的两个列表征服:递归计数两个列表的组合:这是一个技巧部分(在线性时间内完成)
结合使用合并和计数。 假设两个列表是A,B。它们已经被排序。 从A,B生成输出列表L,同时还计算反转数(a,b),其中a在-A处,b在-B处,并且a> b。
这个想法类似于合并排序中的“合并”。 将两个已排序的列表合并到一个输出列表中,但我们还要计算反转。
每次将a_i附加到输出后,都不会遇到新的求逆,因为a_i小于列表B中剩余的所有内容。如果将b_j附加到输出中,则它小于A中所有其余项,则我们增加了通过A中剩余元素的数量计算的反转数。
这使我想起了您可能要查看的类似问题: http : //www.spoj.pl/problems/YODANESS/
在您的问题中,如果需要进行多次交换,您将没有时间交换所有内容。 (想象一下,如果输入的顺序是相反的9,8,7,6 ..那么您就必须基本上将所有内容交换为所有内容。
我认为在您的情况下,每个数字都必须与它左边所有小于它的数字互换。
我建议您使用范围树http://en.wikipedia.org/wiki/Range_tree
关于范围树的妙处在于,每个节点都可以知道左侧和右侧有多少个节点。 您可以非常有效地问这棵树“有多少个数字大于10”,这就是您说9个字就需要进行多少次交换。
诀窍是在从i = 0到i = N-1的过程中构建范围树。 在将第i个数字插入到范围树之前,您可以在每个点针对第i个数字查询树。
祝好运!
我在c ++中执行了相同的代码,并且该代码被接受了,它在spoj上花费了大约4.2秒的时间( http://www.spoj.com/submit/CODESPTB/ )。
这是代码片段:
//http://www.spoj.com/problems/CODESPTB/ //mandeep singh @msdeep14 #include<iostream> using namespace std; int insertionsort(int arr[], int s) { int current,i,j,count=0; for(i=1;i<s;i++) { current=arr[i]; for(j=i-1;j>=0;j--) { if(current<arr[j]) { arr[j+1]=arr[j]; count++; } else break; } arr[j+1]=current; } return count; } int main() { int t,n,i,res; int arr[100000]; cin>>t; while(t--) { cin>>n; for(i=0;i<n;i++) { cin>>arr[i]; } res=insertionsort(arr,n); cout<<res<<endl; } return 0; }
#include < stdio.h >
int main() {
int N, swaps, temp[100], i, j;
scanf("%d", & N);
int arr[N];
swaps = 0;
for (i = 0; i < N; i++) {
scanf("%d", & temp[i]);
j = i;
while (j > 0 && arr[j - 1] > temp[i]) {
arr[j] = arr[j - 1];
++swaps;
--j;
}
arr[j] = temp[i];
}
printf("%d", swaps);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.