我在Hackerrank上遇到了这个问题。 https://www.hackerrank.com/challenges/playing-with-numbers/problem
给定一个整数数组,您必须回答许多查询。每个查询都由一个整数x组成,并按以下方式执行:
我需要完成以下方法
static int[] solution(int[] arr, int[] queries)
在这里,arr
是具有n
个元素的数组
和queries
包含我需要与数组x
的每个值相加的所有arr
,然后获得arr
元素的绝对和。因此,结果数组的大小将与数组queries
相同,假设大小为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;
}
它工作正常,复杂度为O(mn)
,但我需要以O(nlog_m)
或O(mlog_n)
或类似的复杂度来做到这一点。
答案 0 :(得分:1)
灵感是受 h4z3 在以下链接中给出的说明的启发, Absolute Elements Sums
我已经用Java实现了这个想法,
复杂度为O(n log n)。
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;
}
答案 1 :(得分:0)
答案
从本质上讲,如果您知道有多少个数字为正数,有多少个数字为负数,则可以将这两个计数乘以累积的查询总数(对于负数,则为* -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;
}
答案 2 :(得分:-1)
static int[] solution(int[] arr, int[] queries)
{
int querySum = 0;
for (int i; i < queries.length; i++) {
querySum += queries[i];
}
for (int j; j < arr.length; j++) {
arr[j] += querySum;
arr[j] = Math.abs(arr[j]);
}
return arr;
}
复杂度为O(n),额外的内存消耗为O(1)