Algorithm 求数组中每对整数的绝对差之和
给定一个数组,求每对整数的绝对差之和 例如:给定Algorithm 求数组中每对整数的绝对差之和,algorithm,Algorithm,给定一个数组,求每对整数的绝对差之和 例如:给定a[]={2,3,5,7} 输出将是(3-2)+(5-2)+(7-2)+(5-3)+(7-3)+(7-5)=17 它必须比O(n^2)做得更好 原始数组不一定要排序。注意,每个数字加起来正好是k次(如果对列表排序,k是它的位置) 同样,你将每个数字精确地减去n-1-k次 您可以对列表进行排序(O(nlogn)),然后迭代排序后的数组,将每个元素相乘,如上所述 例如:给定一个[]={2,3,5,7} 输出为(3-2)+(5-2)+(7-2)+(5-3
a[]={2,3,5,7}代码>
输出将是(3-2)+(5-2)+(7-2)+(5-3)+(7-3)+(7-5)=17
它必须比O(n^2)
做得更好
原始数组不一定要排序。注意,每个数字加起来正好是k次(如果对列表排序,k是它的位置)
同样,你将每个数字精确地减去n-1-k次
您可以对列表进行排序(O(nlogn)),然后迭代排序后的数组,将每个元素相乘,如上所述
例如:给定一个[]={2,3,5,7}
输出为(3-2)+(5-2)+(7-2)+(5-3)+(7-3)+(7-5)=17
我想你可以
- 用#count-1将每个数字的乘法相加,得到总数
- 用#count-1对前面开始的每个数字的乘法求和,得到要减去的总数
这将变成(7*3+5*2+3*1)-(2*3+3*2+5*1)=17
我想我已经找到了答案。我是通过查看我帖子中的结果表达式得到的
这里是C++中的代码.< /P>
intabsdiff(inta[],intn)
{
如果(n<2)返回0;
排序(a,a+n);
整数和=0;
int i;
对于(i=n-1;i>=0;i--)
{
总和+=(a[i]*(i)-a[i]*(n-i-1));
}
回报金额;
}
这只是另一种观点。下面是一个代码:
With[{n = Length@# - 1}, Range[-n, n, 2].Sort[#]] &
n
=比列表长度小一个
Range[-n,n,2]
以2
的步骤创建一个从-n
到n
的数字列表,例如Range[-4,4,2]
={-4,-2,0,2,4}
是向量点积,例如{a,b,c}。{x,y,z}
=a x+b y+c z
Sort
就是排序
例如,我们有:{-3,-1,1,3}。{2,3,5,7}
=17
下面是列表长度与时间的关系图:
如果数组的大小=4,下面的代码将计算[0](-3)+a[1](-1)+a[2](1)+a[3](3)
result := 0
for i := 0 to sizeof(a)-1 do
begin
result := result + a[i] * (i*2 - sizeof(a) + 1)
end
如果你需要处理排序数组,你可以先用快速排序算法进行排序,算法的复杂度为O(n*log(n))。我想我发布这篇文章有点晚了,但我想这个CPP程序应该可以用
//JUST LIKE ANIMALS !!!!
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll funcy(ll a[], ll n)
{
ll sum = 0;
ll i;
for(i=0;i<n;i++)
{
sum += (a[i]*(i) - a[i]*(n-i-1));
}
return sum;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
ll i,n;cin>>n;ll v[n+1];
for(i=0;i<n;i++)cin>>v[i];
sort(&v[0],&v[n]);
cout<<AbsDiff(v,n);
return 0;
//就像动物一样!!!!
#包括
使用名称空间std;
typedef long long int ll;
ll funcy(ll a[],ll n)
{
ll sum=0;
我会的;
对于(i=0;i>n;ll v[n+1];
对于(i=0;i>v[i];
排序(&v[0],&v[n]);
在JAVA中看一看这段工作代码。
希望它有帮助,有意义
import java.util.Arrays;
public class PairDifference {
public static void main(String[] args) {
int[] arr = {2,3,5,7};
System.out.println(getPairDifference(arr));
}
static int getPairDifference(int[] a){
int diff = 0;
Arrays.sort(a);
int n = a.length;
for(int i=0; i<n; i++)
diff += (a[i]*i) - (a[n-1-i]*i);
return diff;
}
}
导入java.util.array;
公共类对差{
公共静态void main(字符串[]args){
int[]arr={2,3,5,7};
System.out.println(getPairDifference(arr));
}
静态int getPairDifference(int[]a){
int-diff=0;
数组。排序(a);
int n=a.长度;
对于(int i=0;i,首先需要在O(nlogn)时间内对数组进行排序
现在我不会给你这个问题的确切答案,而是给你一个解决这个问题的直觉。
如果我们试图概括指数i上某个特定数字被加和被减的次数,那么对于每个指数i,我们可以使用数学推导的公式来计算绝对差中每个数字在O(N)时间和O(1)额外空间中的贡献之和。
如果您在理解此概念时遇到困难,可以参考此视频
视频链接:-我知道明显的暴力解决方案。我还认为,连续数字之间的差异将精确显示(n-1)次。但结果与暴力解决方案不匹配。是的,答案基于此。我自己在回答这个问题时也发布了代码。@Gunner-试图解释问题时找到答案的典型案例:).1但我觉得被接受的答案应该是amit。他比我们两个都快。注意,在迭代数组之前需要排序,否则你甚至可能会得到否定的答案。不创建范围列表和点积都是ω(n)?如果我理解正确,排序仍然存在于这两种算法中,并且实际上在大小为n的数组上有2次隐式迭代,而不是1次(点积和创建列表)@amit我想Gunner已经在做我想说明的事情了,但我错过了,因为我不喜欢阅读程序代码。你的观察可能是正确的,但这是在Mathematica中做类似事情的最自然的方式。我的图表显示它的复杂性还不错。@Mr.Wizard:当然不错,它是O(nlogn)用于排序,但如果有,它将比迭代方法更慢,而不是更快。@amit我修改了帖子以纠正这一点。我在发表声明时认为Gunner做的事情效率更低。@Mr.Wizard:毫无疑问,你的选择对于基于数学的语言来说要优雅得多。实际上,你不能用O(n)来做吗使用基数或计数排序,然后按照您提到的方式进行后处理。@Sumod:如果数字的范围有限-是的,您可以使用基数排序/计数排序进行优化。