Java 降低查找数组元素绝对和的复杂性
我在Hackerrank上遇到了这个问题。 给定一个整数数组,您必须回答许多查询。每个查询由单个整数x组成,执行方式如下:Java 降低查找数组元素绝对和的复杂性,java,performance,time-complexity,Java,Performance,Time Complexity,我在Hackerrank上遇到了这个问题。 给定一个整数数组,您必须回答许多查询。每个查询由单个整数x组成,执行方式如下: 将x添加到数组的每个元素中,永久地修改它以备将来查询 找到数组中每个元素的绝对值,并在新行上打印绝对值之和 我只需要完成以下方法 static int[] solution(int[] arr, int[] queries) 这里,arr是包含n元素的数组 和查询包含我需要与数组arr的每个值相加的所有x,然后得到arr元素的绝对和。因此,结果数组的大小将与数组查询
- 将x添加到数组的每个元素中,永久地修改它以备将来查询
- 找到数组中每个元素的绝对值,并在新行上打印绝对值之和
static int[] solution(int[] arr, int[] queries)
这里,arr
是包含n
元素的数组
和查询
包含我需要与数组arr
的每个值相加的所有x
,然后得到arr
元素的绝对和。因此,结果数组的大小将与数组查询的大小相同,即大小为m
。该方法将返回一个m
元素数组
下面是我的实现
static int[] solution(int[] arr, int[] queries)
{
int[] result = new int[queries.length];
for (int i = 0; i < queries.length; i++)
{
int total = 0;
for (int j = 0; j < arr.length; j++)
{
arr[j] += queries[i];
if (arr[j] > 0)
total += arr[j];
else
total -= arr[j];
}
result[i] = total;
}
return result;
}
静态int[]解决方案(int[]arr,int[]查询)
{
int[]结果=新的int[querys.length];
for(int i=0;i0)
总+=arr[j];
其他的
总计-=arr[j];
}
结果[i]=总数;
}
返回结果;
}
它工作得很好,它的复杂度是O(mn)
,但我需要用O(nlog_m)
或O(mlog_n)
的复杂度来完成它。
静态int[]解决方案(int[]arr,int[]查询)
{
int querySum=0;
for(int i;i
复杂度为O(n),额外内存消耗为O(1)答案
基本上,如果您知道有多少个数字是正的,有多少个是负的,您可以将这两个计数乘以累计查询总数(负数为*-1)
计算出有多少-/+的总计数以及每个步骤中所有这些值的总和。例如,将+1加到全部,直到所有负数都为正数;将-1加到全部,直到所有正数都为负数。存储每个步骤的结果(所有-/+计数和所有-/+值的总和)
现在,您可以引用每个步骤的总和和总计数-/+来计算每个查询的结果
您还需要将playingWithNumbers方法和结果数组的返回类型从int更改为long
static long[] playingWithNumbers(int[] arr, int[] queries) {
long[] results = new long[queries.length];
List<Integer> negatives = new ArrayList<>(arr.length);
List<Integer> positives = new ArrayList<>(arr.length);
long negativeSum = 0;
long positiveSum = 0;
for (int i : arr) {
if (i < 0) {
negatives.add(i);
negativeSum += i;
} else {
positives.add(i);
positiveSum += i;
}
}
int negativeCount = negatives.size();
int positiveCount = positives.size();
Collections.sort(negatives);
Collections.sort(positives);
Map<Integer, Integer> countMap = new HashMap<>(arr.length);
Map<Integer, Long> sumMap = new HashMap<>(arr.length);
long totalSum = positiveSum + (negativeSum * -1);
countMap.put(0, negativeCount);
sumMap.put(0, totalSum);
if (positiveCount != 0) {
long tmpTotalSum = totalSum;
int tmpNegativeCount = negativeCount;
int increment = negativeCount - positiveCount;
int index = 0;
for (int i = 1; i <= positives.get(positiveCount - 1) + 1; i++) {
while (index != positives.size() && positives.get(index) - i == -1) {
tmpNegativeCount++;
increment += 2;
index++;
}
tmpTotalSum += increment;
countMap.put(i * -1, tmpNegativeCount);
sumMap.put(i * -1, tmpTotalSum);
}
}
if (negativeCount != 0) {
long tmpTotalSum = totalSum;
int tmpNegativeCount = negativeCount;
int increment = positiveCount - negativeCount;
int index = negativeCount - 1;
for (int i = 1; i <= (negatives.get(0) - 1) * -1; i++) {
int incrementNxt = 0;
while (index != -1 && negatives.get(index) + i == 0) {
tmpNegativeCount--;
incrementNxt += 2;
index--;
}
tmpTotalSum += increment;
increment += incrementNxt;
countMap.put(i, tmpNegativeCount);
sumMap.put(i, tmpTotalSum);
}
}
int maxNegative = positiveCount != 0 ? (positives.get(positiveCount - 1) + 1) * -1 : 0;
int maxPositive = negativeCount != 0 ? ((negatives.get(0) - 1)) * -1 : 0;
int totalCount = positiveCount + negativeCount;
long accumulatedTotal = 0;
for (int i = 0; i < queries.length; i++) {
accumulatedTotal += queries[i];
if (accumulatedTotal >= maxNegative && accumulatedTotal <= maxPositive) {
results[i] = sumMap.get((int)accumulatedTotal);
} else if (accumulatedTotal < maxNegative) {
long extra = maxNegative - accumulatedTotal;
results[i] = sumMap.get(maxNegative) + countMap.get(maxNegative) * extra;
} else {
long extra = accumulatedTotal - maxPositive;
results[i] = sumMap.get(maxPositive) + (totalCount - countMap.get(maxPositive)) * extra;
}
}
return results;
}
static long[]playingWithNumbers(int[]arr,int[]querys){
long[]results=new long[querys.length];
列表负片=新数组列表(arr.length);
列表正片=新数组列表(arr.length);
长负esum=0;
长阳性率um=0;
用于(int i:arr){
if(i<0){
否定。加入(i);
负esum+=i;
}否则{
增加(i);
阳性血清um+=i;
}
}
int negativeCount=negatives.size();
int positiveCount=posities.size();
集合。排序(负片);
集合。排序(正数);
Map countMap=新的HashMap(arr.length);
Map sumMap=新HashMap(arr.length);
长总和=正总和+(负总和*-1);
countMap.put(0,负计数);
总和put(0,总和);
如果(正计数!=0){
长tmpTotalSum=总和;
int tmpNegativeCount=负计数;
int增量=负计数-正计数;
int指数=0;
对于(inti=1;i而言,受以下链接中h4z3给出的解释的启发,
我已经用Java实现了这个想法
复杂性为O(n logn)。
static int bisect_left(int[] num, int x)
{
int low = 0;
int high = num.length - 1;
while (low < high)
{
int mid = (low + high) / 2;
if (num[mid] >= x)
high = mid - 1;
else
low = mid + 1;
}
return (num[low] < x) ? low + 1 : low;
}
static int[] solution(int[] arr, int[] queries)
{
Arrays.sort(arr); // O(n log n)
int N = arr.length;
int[] results = new int[queries.length];
int[] sc = new int[N + 1];
sc[0] = 0;
sc[1] = arr[0];
for (int i = 1; i < N; i++)
sc[i + 1] = sc[i] + arr[i];
int q = 0;
for (int i = 0; i < queries.length; i++) // O(m)
{
q += queries[i];
int n = bisect_left(arr, -q); // O(log n)
results[i] = sc[N] + q * N - 2 * (sc[n] + q * n);
}
return results;
}
static int bisect_left(int[]num,int x)
{
int低=0;
int高=num.length-1;
while(低<高)
{
int mid=(低+高)/2;
如果(num[mid]>=x)
高=中-1;
其他的
低=中+1;
}
返回(数值[低] 问题:寻求帮助优化当前正在运行的代码通常更适合。你可能会考虑迁移你的问题到那里。首先我问了CoDeEvIEW.StActhExchange。com,有人说,因为我正在寻找新的实现,我应该在这里问。所以我删除它,并在这里问。你可以保持<代码>rr
在一个外部变量中的和,以及查询中整数的合计和
@azurefrog不太可能,CR不仅仅是一个优化。OP的代码不多,当它需要完全重写时,没有必要使它更好。你错过了“绝对值”.Hm,是的,你是对的,但它不会改变复杂性和内存消耗@Alexey,对于arr[]={0,-2,-3,2}和querys[]={-2,4,-1}来说,它仍然是错误的。输出应该是{11,7,7},你的答案将生成大小为4的数组,而不管查询大小如何。你能添加几个吗