How to find the Kth largest difference in int[]? - java

I have an Algorithm question.
For example, there is an int[] array like [1,5,4,3,7,2].
I want to find the kth largest difference in this array like :
array[i] - array[j] = kth largest difference
(index i must smaller than j and array[i] must larger than array[j]).
The output is return the j in this question.
My current idea:
I can build a int[][] to store all the difference in the array.
Then sorting them and find the kth larget difference.
But time complexity is O(n^2).
Are there better solutions?

You could run 2 separate methods that finds the max and min of the corresponding arrays then find the difference.
OR
You can use your method of creating a new array that finds the difference of every single value THEN find the max of that array and output that.
Then use Array sort() method to reorder an array and print out the values of max differences when called by index+1

Example in Python
results = []
a = [1,5,4,3,7,2]
a_new = [(1,0), (5,1), (4,2), (3,3), (7,4), (2,5)] #(5,1) -> 5:value and 1:index
sort a_new by value # e.g. mergesort O(nlogn)
start_index = 0
end_index = len(a_new) - 1
i = -1
j = -1
diff = 0
while true: # sequential search
if(a_new[start_index][1] < a_new[end_index][1]): #compare i and j
tmp_diff = a_new[end_index][0] - a_new[start_index][0]
i = start_index
j = end_index
diff = tmp_diff
results.append((I,j,diff)) #add a tuple in results_list
end_index -= 1
else: # a_new[start_index][1] > a_new[end_index][1]
start_index += 1
if start_index == end_index: break
sort results by diff and return results[k-1]
I hope this help. I can't check typing error.
My Idea is: max difference is -> max_possible_element_value - min_element_value

Sample:
results = []
a_new = [(1,0), (2,5), (3,3), (4,2), (5,1), (7,4)]
start_index = 0
end_index = len(a_new) - 1
i = -1
j = -1
diff = 0
while True:
if(a_new[start_index][1] < a_new[end_index][1]):
i = a_new[start_index][1]
j = a_new[end_index][1]
diff = a_new[end_index][0] - a_new[start_index][0]
results.append((i, j, diff))
end_index -= 1
else:
start_index -= -1
if start_index == end_index: break
print(results)
Result:
[(0, 4, 6), (0, 1, 4), (0, 2, 3), (0, 3, 2), (0, 5, 1)]
you can sort the result array then get kth diff.

Pseudocode-wise, it could go this way :
You can sort the current array descending, then start your calculation like so :
diffList = {}
calculate(array,k) :
if (k<=0) OR (array.length < 2) OR (k > 2^(array.length-1))
return nothing // whatever behavior you want (exception or null Integer whatever suits you)
else
return kthLargest(k, 0 , array.length-1, array)
end if
kthLargest(count, upperBound, lowerBound, array) :
if count = 0
if upperBound != lowerBound
return max(array[upperBound]-array[lowerBound], max(sortDesc(diffList)))
else
return max(sort(diffList))
end if
else if upperBound = lowerBound
sortDesc(diffList)
return diffList[count]
else
topDiff = array[upperBound]-array[upperBound+1]
botDiff = array[lowerBound-1]-array[lowerbound]
if(topDiff > botDiff)
add botDiff to diffList
return kthLargest(count-1,upperBound,lowerBound-1,array)
else
add topDiff to diffList
return kthLargest(count-1,upperBound+1,lowerBound,array)
end if
end if
Call calculate(array,k) and you're set.
This basically keeps track of a 'discarded pile' of differences while iterating and reducing bounds to always have your final largest difference be the current bounds' difference or a potential better value in that discarded pile.
Both sorts (omitted for brevity) should make this O(n log n).
You can substitute arrays for the most convenient collections, and unwrap this into an iterative solution also.
Corrections appreciated!

It can be done in complexity O( N * logN + N * logValMax ). First lets sort the array. After that we can build a function countSmallerDiffs( x ) which counts how many differences smaller or equal to x are in the array, this function has complexity O( N ) using two pointers. After that we can binary search the result in range minVal-maxVal. We need to find p such that satisfies countSmallerDiffs( p ) <= k < countSmallerDiffs( p + 1 ). The answer will be p.
Hope this helps you out! Good luck!

Related

Finding the smallest sum between subset of array in java [duplicate]

I'm having some problems solving this question:
Given an array of ints, divide the input into 2 groups such that their sums are as close as possible, the 2 groups must be equal in length, or if the input is odd length then one group can have 1 more than the other. Then print the lower sum first, and the higher sum after.
Ex:
input -> [4,6,17,3,2,5,10]
output -> 23,24 ([17,5,2] , [10,6,4,3])
This is what I've come up with and so far what I've tested it's passed but I do not know if it's actually correct:
public static String closestSums(int[] input) {
Integer sum1 = 0;
Integer sum2 = 0;
Integer dif = 0;
Integer bigSum = 0;
List<Integer> list = new ArrayList<>();
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
for (int x = 0; x < input.length; x++) {
list.add(input[x]);
}
Collections.sort(list);
for (int x = list.size(); x >= 0; x--) {
bigSum += list.get(x);
if (dif == 0) {
dif = list.get(x);
list2.add(list.get(x));
}
else if (dif > 0) {
dif -= list.get(x);
list1.add(list.get(x));
}
else {
dif += list.get(x);
list2.add(list.get(x));
}
}
dif = Math.abs(dif);
if (dif != 0) {
sum2 = (bigSum / 2) + dif;
sum1 = bigSum / 2;
}
else {
sum2 = bigSum / 2;
sum1 = bigSum / 2;
}
return sum1 + ", " + sum2;
}
It's not correct.
Regardless of the bunch of small coding mistakes that are mentioned in the other answer, your algorithm doesn't work.
Consider the input [3, 3, 2, 2, 2]. Your algorithm will divide it into [3, 2, 2] and [3, 2] with a difference of 7-5=2. However, a better split with equal sums exists: [3, 3] and [2, 2, 2].
I am not going to provide a complete algorithm but give you a few hints:
1 - The minimum difference can be binary-searched. If you can come up with an algorithm that decides whether it is possible to split the array so that the difference of the sums of the pieces is at most d for a given d, then you can binary search the minimum d for which the algorithm outputs 1.
2 - Look at the subset sum problem, it can help with the subproblem I defined in item 1.
I have made 3 observations after analyzing & running your Code.
There lot of small errors throughout the code.
Syntaxical Error On Line 4 (Initialization of 'Dif') Line 11(The 'for' keyword)
Logical Error on Line 26, Line 27 (Instead of Accessing Index 'i', you must access index 'x')
Runtime Error on Line 17 (Initializing x=list.size() will throw a runtime error java.lang.IndexOutOfBoundsException)
Though, the important things to look at, are mentioned below
It's a suggestion, if you aren't printing the list with the 'sum1' & 'sum2', then creating and operating the two other output lists is redundant. The respective Sums of the list can be calculated while traversing the main list.
Most importantly, the way you are calculating sum1 and sum2 after traversing the list and then dividing them, is not reliable.
Eg. The Following input will give an unexpected output [4,6,45,3,2,5,10]. So, I suggest you to resort to the most reliable way of calculating the sum of list 1 & list 2, which is calculating them while traversing the list. (You may also remove the full logic of bigSum)
Last Words: Try and Implement the above mentioned Ideas yourself.

Binary-search with duplicate elements in array

I want find if there is a single element in a list of duplicate elements.
For this code
private static int findDuplicate(int array[]) {
int low = 0;
int high = array.length - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = array[mid];
if (midVal == mid)
low = mid + 1;
else
high = mid - 1;
}
return high;
}
It find the duplicate number but I want to find only the single number
in the duplicate and sorted array.
For example, given this int[] input:
[1,1,2,2,3,3,4,5,5]
Output would be '4'.
Or this int[] input:
[1,1,2,2,3,4,4,5,5,6,6]
Output would be '3'.
In this int[] input:
[1,1,2,7,7,9,9]
Output would be '2'.
I'm working in Java now but any language or psuedo-code is fine.
I know the obvious traversal at O(n) linear time, but I'm trying to see if this is possible via binary search at O(log n) time.
The elements are sorted and only duplicate twice!
I know the way with simple loop but I want to do it by binary search.
Consider each pair of 2 consecutive elements: (the pairs with 2 elements different are highlighted) (note that there's a stray element at the end)
(1 1) (2 2) (3 3) (4 5) (5 6) (6 7) (7 8) (8)
Observe that the only non-duplicated element will make the corresponding pair and all the later pairs have different values, the pairs before that have the same value.
So just binary search for the index of the different pair.
This algorithm also don't require that the list is sorted, only that there's exactly one element which appears once, and all other elements appear twice, in consecutive indices.
Special case: if the last element is the unique one, then all the pairs will have equal values.
Every pair of same values will be like below in terms of indices:
(0,1),
(2,3),
(4,5)
(6,7)
etc. You can clearly see that if index is even, check with next element for similarity. If index is odd, you can check with previous value for similarity.
If this symmetry is broken, you can move towards left side or if everything is ok, keep moving right.
Pseudocode(not tested):
low = 0,high = arr.length - 1
while low <= high:
mid = (low + high) / 2
if mid == 0 || mid == arr.length - 1 || arr[mid] != arr[mid-1] and arr[mid] != arr[mid + 1]: // if they are corner values or both left and right values are different, you are done
return arr[mid]
if(mid % 2 == 0):
if arr[mid + 1] != arr[mid]: // check with next index since even for symmetry
high = mid
else:
low = mid + 2
else:
if arr[mid - 1] != arr[mid]: // check with prev index since odd for symmetry
high = mid
else:
low = mid + 1
return -1

Make two array sum same with limited values

I have two arrays A & B (size of the array is 1 to 100,000) that can take values only 1,2,3,4,5,6.
Now my task is to make minimum numbers to be changed in arrays such that the sum of both the arrays is the same.
Example 2:
A=[5,4,1,2,6,6] & B=[2], we have to make A as [1,1,1,1,1,1] so we have to change A 5 times and then B=[6] once, so function should return 6.
Example 3:
A=[1,2,3,4,3,2,1] and B[6], function should return -1.
Method signature looks like this.
public int task(int[] A, int[] B) {
int diff = Math.abs(A.length - B.length);
if(diff >=6) return -1;
//
}
I am able to get answer for example 3 with simple condition. Bit not for first 2 examples.
What approach should I follow to solve this program? As we can turn each and every element in A & B and do a comparison, but that is more complex.
The alghorithm can be as following:
Prepare data part
Go through all items in array A and B and find out how many of each number (1,2,3,4,5,6) is in each array. Preferable have 2d array that stores the indexes of those numbers, so you can easily access it later.
i.e. array A=[1,1,1,4,6,4] will be translated into new 2d array as
2darr=
[]
[0,1,2]
[]
[]
[3,5]
[]
[4]
so when you i.e. want to see how many 1 are there you can see that 2darr[1].length is 3. And when you want to find out where it is i.e. the 2darr[1][0] will get you index in source array and A[0] is indeed 1
In process you can also count the sum, but even without it, the sum now can be easily found out just going through lengths of each subarray in 2darray.
Alghoritm
To find the minimum amount of changes, you will first find out which sum is smaller and which bigger. Then the best change is to start changing 1 values to 6 in smaller array or changing 6 values to 1 in bigger arrays. Then 2 to 6 in smaller array and 5 to 1 in bigger array. And then continue with other numbers.
In process you can changing the arrays based on indexes you already have and do it as long as needed to get both arrays to same sum. This is detailed alghoritm that will show you how actually both arrays will look like to satisfy your needs. Its O(n), so there is definitely no way how to make it faster as you have to go through all fields just to get the sum.
I suggest to do it so you can see the actual result. On the other hand, if you think more deeply, it can be done more easily, if you just seek the right answer - you just need to know how many times each number in each array is and then just find out how many changes are needed just by simple math. You already know, you are just changing up to all 1 to 6 in smaller array and up to all 6 to 1 in bigger array and it can be just counted easily how many of them you need to change and if it is sufficient or you change all of them and then you will continue with 5 to 1 and 2 to 6 etc.
Example
Imagine that A.length is 500 and B.length is 300. The sum of A=1000and B=700. You find out that A has 30 repetitions of number 6 and B has 20 repetitions of number 1. In A you change all those 6 to 1, therefore reducing it by 30*5=150 to total of A=850 and in B you change all those 1 to 6 and increasing the value 20*5=100 and therefore B=800. You did 50 changes in total.
Then you continue with higher number in smaller array and with lower number in bigger array. You find out that A has 100 numbers of 5. Reducing 5 to 1 decreases value by 4 for each. Right now you have only 50 value difference. 50/4=12.5, therefore you need to change 13 numbers and you are done. The answer is that minimum amount of changes is 63.
The impossibility-criteria is a simple one as you suspect, but it is different from what you guess: it depends on the length of the arrays, which determines their minimal and maximal sums. The shorter array can not produce a sum which is greater than 6 times its length (all elements are 6s) and the longer array can not produce a sum which is less than its length (all elements are 1s):
if( Math.min(A.length, B.length) * 6 < Math.max(A.length ,B.length) )
return -1;
Then you need the sums and the statistics what the other answer describes, but maybe there is place for a slightly different explanation. In order to have the two sums meet, the smaller one can be increased and the larger one can be decreased. For having the minimum amount of steps, you always want to make the largest steps possible, via starting to replace 1s with 6s in the smaller sum (each replacement increasing the sum by 5) and 6s with 1s in the larger sum (each replacement decreasing it by 5), and so on.
As you do not want to generate the steps (at least to my understanding), actually you can track the difference only and also count the pairs together (6s in the larger-sum-array and 1s in the smaller-sum-array, then the same with 5-2, etc.). And in fact you can do this pairing even at the beginning, without knowing which one is the larger/smaller sum, because the pairs will stay pairs, just their direction changes.
Example is JavaScript so it can run here, but I try to write it as Java as possible:
function task(A,B){
if( Math.min(A.length, B.length) * 6 < Math.max(A.length, B.length) )
return -1;
var diff=0;
var statistics=[0,0,0,0,0,0]; // would be a new int[6] in Java
for(var item of A){ // for(int item : A) in Java
// this loop guesses that A has the larger sum
diff+=item;
statistics[item-1]++; // 1s are counted in [0], 2s in [1], ... 6s in [5]
}
for(var item of B){ // for(int item : B) in Java
// this loop guesses that B has the smaller sum
diff-=item;
statistics[6-item]++; // 1s are counted in [5], 2s in [4], ... 6s in [0]
}
if(diff<0){
// the guess was wrong, swaps are needed
diff=-diff;
for(var i=0;i<3;i++){
var swap=statistics[i];
statistics[i]=statistics[5-i];
statistics[5-i]=swap;
}
}
var log=[A.join()," ",B.join()," ",diff," ",statistics.join()].join(); // <-- this one...
// at this point
// - array indices are conveniently denoting step sizes
// - diff is non-negative
// - and we know there is a solution (so we won't run out of array indices for example)
var changes=0;
var i=5;
while(diff>0){
var step = Math.min(statistics[i], Math.ceil(diff/i));
// would better be "int step = Math.min(statistics[i], (diff+i-1)/i);" in Java
// as Math.ceil() produces a double
changes += step;
diff -= i*step;
i--;
}
return [changes," ",log].join(); // <-- ... and this
// are only visuals
return changes;
}
console.log(task([1,2,3,4,3,2,1],[6]));
console.log(task([6],[1,2,3,4,3,2,1]));
console.log(task([2,3,1,1,2],[5,4,6]));
console.log(task([5,4,6],[2,3,1,1,2]));
console.log(task([5,4,1,2,6,6],[2]));
console.log(task([2],[5,4,1,2,6,6]));
At the end I've just thrown it together in Java too: https://ideone.com/mP3Sel
As others have noted, we can solve this with a greedy algorithm. Count the frequencies of numbers for each array, then iterate from the outside in. For the array with the larger sum, iterate over the negative multipliers; for the array with the smaller sum, the positive. Choose the greatest absolute multiplier, then the max frequency available (and needed) each time, and as soon as the sum difference is equal or reverses sign, stop.
2 3 1 1 2 = 9
mult 5 4 3 2 1 0
freq 2 2 1 0 0 0
^ -->
5 4 6 = 15
mult 0 -1 -2 -3 -4 -5
freq 0 0 0 1 1 1
<-- ^
function f(A, B){
let freqSm = [0, 0, 0, 0, 0, 0];
let freqLg = [0, 0, 0, 0, 0, 0];
let smSum = 0;
let lgSum = 0;
let sm = 'A';
let lg = 'B';
A.map(x => {
freqSm[x-1]++;
smSum += x;
});
B.map(x => {
freqLg[x-1]++;
lgSum += x;
});
if (lgSum < smSum){
sm = 'B';
lg = 'A';
let [_freq, _sum] = [freqSm, smSum];
freqSm = freqLg;
freqLg = _freq;
smSum = lgSum;
lgSum = _sum;
}
const smMult = [5, 4, 3, 2, 1, 0];
const lgMult = [0,-1,-2,-3,-4,-5];
const changes = [];
let diff = lgSum - smSum;
function numTxt(count, num){
const ws = [, 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
const countTxt = count < 10 ? ws[count] : count;
return `${ countTxt } ${ num }${ count > 1 ? 's' : '' }`;
}
function incSm(i){
const rem = diff % smMult[i];
const mult = Math.min(freqSm[i], Math.ceil(diff / smMult[i]));
diff -= mult * smMult[i];
let txt;
if (diff < 0 && rem){
if (mult > 1)
txt = `Change ${ numTxt(mult-1, i+1) } to 6 and one to ${ i + 1 + rem } in ${ sm }.`;
else
txt = `Change one ${ i + 1 } to ${ i + 1 + rem } in ${ sm }.`;
} else {
txt = `Change ${ numTxt(mult, i+1) } to 6 in ${ sm }.`;
}
changes.push(txt);
}
function decLg(j){
const rem = diff % -lgMult[j];
const mult = Math.min(freqLg[j], Math.ceil(-diff / lgMult[j]));
diff += mult * lgMult[j];
let txt;
if (diff < 0 && rem){
if (mult > 1)
txt = `Change ${ numTxt(mult-1, j+1) } to 1 and one to ${ j + 1 - rem } in ${ lg }.`;
else
txt = `Change one ${ j + 1 } to ${ j + 1 - rem } in ${ lg }.`;
} else {
txt = `Change ${ numTxt(mult, j+1) } to 1 in ${ lg }.`;
}
changes.push(txt);
}
for (let i=0; i<6; i++){
const j = 5 - i;
if (freqSm[i] >= freqLg[j]){
if (freqSm[i]){
incSm(i);
if (diff <= 0)
return changes.join('\n');
}
if (freqLg[j]){
decLg(j);
if (diff <= 0)
return changes.join('\n');
}
} else {
if (freqLg[j]){
decLg(j);
if (diff <= 0)
return changes.join('\n');
}
if (freqSm[i]){
incSm(i);
if (diff <= 0)
return changes.join('\n');
}
}
}
return -1;
}
var input = [
[[2,3,1,1,2], [5,4,6]],
[[5,4,1,2,6,6], [2]],
[[1,2,3,4,3,2,1], [6]]
];
for (let [A, B] of input){
console.log(`A: ${ A }`);
console.log(`B: ${ B }`);
console.log(f(A, B));
console.log('');
}

Find the minimal absolute value of a sum of two elements

I am solving the Codility problem provided below,
Let A be a non-empty array consisting of N integers.
The abs sum of two for a pair of indices (P, Q) is the absolute value |A[P] + A[Q]|, for 0 ≤ P ≤ Q < N.
For example, the following array A:
A[0] = 1 A1 = 4 A[2] = -3 has pairs of indices (0, 0), (0,
1), (0, 2), (1, 1), (1, 2), (2, 2). The abs sum of two for the pair
(0, 0) is A[0] + A[0] = |1 + 1| = 2. The abs sum of two for the pair
(0, 1) is A[0] + A1 = |1 + 4| = 5. The abs sum of two for the pair
(0, 2) is A[0] + A[2] = |1 + (−3)| = 2. The abs sum of two for the
pair (1, 1) is A1 + A1 = |4 + 4| = 8. The abs sum of two for the
pair (1, 2) is A1 + A[2] = |4 + (−3)| = 1. The abs sum of two for
the pair (2, 2) is A[2] + A[2] = |(−3) + (−3)| = 6.`
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A consisting of N integers, returns the minimal abs sum of two for any pair of indices in this array.
For example, given the following array A:
A[0] = 1 A1 = 4 A[2] = -3 the function should return 1, as
explained above.
Given array A:
A[0] = -8 A1 = 4 A[2] = 5 A[3] =-10 A[4] = 3 the function
should return |(−8) + 5| = 3.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000]; each element of array A is an integer within the range [−1,000,000,000..1,000,000,000].
I write the solution provided below.
public static int solution(int[] A) {
int N = A.length;
Arrays.sort(A);
if (A[0] >= 0) {
return 2 * A[0];
}
int i = 0;
int j = N - 1;
int sum = Math.abs((A[i] + A[j]));
// -10, -8, 3, 4, 5
while (i <= j) {
if (Math.abs(A[i + 1] + A[j]) < sum) {
++i;
sum = Math.abs(A[i] + A[j]);
} else if (Math.abs(A[i] + A[j - 1]) < sum) {
--j;
sum = Math.abs(A[i] + A[j]);
} else {
i++;
j--;
}
}
return sum;
}
The solution gets hanged in the online judge and seems it enters in a forever loop. Is there a possibility that the code can enter a non-ending loop?
UPDATE
After I update the solution with the all negatives check, the code passed the online judge and provides a good performance.
if(A[N-1] <=0){
return 2* Math.abs(A[N-1]);
}
For input arrays e.g({-1, -2, -3}, {-1, -2}, {-1} your algorithm throws ArrayIndexOutOfBoundsException, so arrays when there are only negative numbers and there is no repeats
There is no chance to reach endless loop because either i or j change only + or - 1
I would like to explain the algorithm that I have implemented and then the implementation in C++.
Sort the array because otherwise we would need to check any two arbitrary indices. That brute-force solution would result in O(N ^ 2) runtime complexity.
We initialise the min abs sum to something higher than the possible value in the arrays.
Apply the caterpillar method by having front and back indices.
In every iteration, update the min abs sum as and when needed.
There two special cases:
a. all values are zero or positive. We could return A[front] * 2 early.
b. all values are negative or zero. We could return A[back] * 2 early.
In both cases, we could return early, however, it would result in a bit more code, so I personally avoid that. In the above cases, we can still go through the array without degrading the overall runtime complexity. In these cases, it also does not matter how we go through the array with regards to the result, so I just go through the array in one way in both cases. But the code will be shared with the third case.
In the third case, where the array, and thereby the sorted array, contains both negative and positive values, we try to keep the sum of front and back to zero since this when the abs sum value is minimised. In other words, we try to keep the balance between the negative and positive numbers by keeping their distance to the minimum.
Therefore, if the sum of front and back are less than zero, then we know that the negative front value is greater than the positive back value. As a direct consequence of that, we need to advance the front index.
If the sum of front and back are equal to zero, then we found the smallest min abs sum that is ever possible. The absolute value cannot be less than zero. Whilst I could return at this point in the code for some constant optimisation, I do not do so to keep the code the minimal and also functional.
If the sum of front and back are greater than zero, then we know that the negative front value is less than the positive back value. As a direct consequence of that, we need to decrease the index.
We loop until the front and back indices meet, but we handle the case when they are equal since according to the task specification, the same index can be used twice for the absolute sum.
The runtime complexity of this solution is O(N * logN) because the sorting of the array is O(N * logN) and the loop is O(N) since we go through every element. Therefore, the sorting runtime complexity dominates the loop.
The space complexity is O(1) because we only allocate constant space independently from the number of inputs. The sorting is done in place.
int solution(vector<int> &A)
{
const int N = A.size();
sort(A.begin(), A.end());
int min_abs_sum_of_two = INT_MAX;
for (int front = 0, back = N - 1; front <= back;) {
const int ef = A[front];
const int eb = A[back];
min_abs_sum_of_two = min(min_abs_sum_of_two, abs(ef + eb));
if (ef + eb < 0) ++front; else --back;
}
return min_abs_sum_of_two;
}
I got 100% for following code ( java). Slightly modified version of https://www.techiedelight.com/find-pair-array-minimum-absolute-sum/
import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// sort the array if it is unsorted
Arrays.sort(A);
int low = 0;
int high = A.length - 1;
if (A[0] >= 0) {
return 2 * A[0];
}
if (A[high] <= 0) {
return -2 * A[high];
}
// maintain two indexes pointing to endpoints of the array
// `min` stores the minimum absolute difference
int min = Integer.MAX_VALUE;
int i = 0, j = 0;
// reduce the search space `A[low…high]` at each iteration of the loop
int sum = 0;
// loop if `low` is less than `high`
while (low < high)
{
// update the minimum if the current absolute sum is less.
sum = A[high] + A[low];
if (Math.abs(sum) < min)
{
min = Math.abs(sum);
i = low;
j = high;
}
// optimization: pair with zero-sum is found
if (min == 0) {
break;
}
// increment `low` index if the total is less than 0;
// decrement `high` index if the total is more than 0
if (sum < 0) {
low++;
}
else {
high--;
}
}
return min;
}
}
The Answer is late but I hope to help anyone have the same question
//============================================================================
// Author: Hamdy Abd El Fattah
// Code is like humor. When you have to explain it, it’s bad.
//============================================================================
#include <bits/stdc++.h>
#define FIO cin.tie(0), cin.sync_with_stdio(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int main() {
FIO;
ll n , m = INF , x;
vector<ll> positive,negative;
cin>>n;
while(n--){
cin>>x;
if(x < 0)
negative.push_back(x * -1);
else if(x > 0)
positive.push_back(x);
else
m = 0;
}
if(m == 0){
cout<<"0\n";
}else{
sort(positive.begin(), positive.end());
sort(negative.begin(), negative.end());
int i= 0, j = 0;
int positive_size = positive.size(), negative_size =negative.size();
while(i < positive_size || j < negative_size){
if(abs(positive[i] - negative[j]) < m){
m=abs(positive[i] - negative[j]);
m=min(min(m,positive[i]*2),negative[j] * 2);
}
if((i < positive_size && positive[i] <= negative[j]) || j == negative_size)
i++;
else if((j < negative_size && positive[i] > negative[j]) || i == positive_size)
j++;
}
cout<<m<<endl;
}
return 0;
}

Bad performance in Java exercise

I'm doing some tests in Java to warm up, and I just made this one:
A non-empty zero-indexed array A consisting of N integers is given.
The consecutive elements of array A represent consecutive cars on a
road.
Array A contains only 0s and/or 1s:
0 represents a car traveling east, 1 represents a car traveling west.
The goal is to count passing cars. We say that a pair of cars (P, Q),
where 0 ≤ P < Q < N, is passing when P is traveling to the east and Q
is traveling to the west.
For example, consider array A such that:
A[0] = 0 A[1] = 1 A[2] = 0 A[3] = 1 A[4] = 1 We have five
pairs of passing cars: (0, 1), (0, 3), (0, 4), (2, 3), (2, 4).
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A of N integers, returns
the number of pairs of passing cars.
The function should return −1 if the number of pairs of passing cars
exceeds 1,000,000,000.
For example, given:
A[0] = 0 A[1] = 1 A[2] = 0 A[3] = 1 A[4] = 1 the function
should return 5, as explained above.
Assume that:
N is an integer within the range [1..100,000]; each element of array A
is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N); expected worst-case space
complexity is O(1), beyond input storage (not counting the storage
required for input arguments). Elements of input arrays can be
modified.
My code is as follows:
public int solution(int[] A) {
// write your code in Java SE 8
int result = 0;
long mult = 0;
for(int value : A){
if(value == 0){
mult ++;
}
else {
result += mult;
}
}
return result;
}
The link with the result is this one:
https://codility.com/demo/results/trainingFFF4BS-AZ3/
If the link die, the result said:
Performance tests
▶ medium_random random, length = ~10,000 ✔OK ▶ large_random random,
length = ~100,000 ✘WRONG ANSWER got 1248768710 expected -1 ▶
large_big_answer
0..01..1, length = ~100,000 ✘WRONG ANSWER got -1794967296 expected -1 ▶ large_alternate
0101..01, length = ~100,000 ✘WRONG ANSWER got 1250025000 expected -1 ▶ large_extreme large test with all 1s/0s, length = ~100,000 ✔OK
Any ideas what is wrong in my code?.
Your rules say,
The function should return −1 if the number of pairs of passing cars exceeds 1,000,000,000.
And you don't test that condition. You could with a ternary operation and something like
return result > 1000000000 ? -1 : result;
or (debateably) more readable
if (result > 1000000000) {
return -1;
}
return result;
and for improved performance you might add that test like
for (int value : A) {
if (value == 0) {
mult++;
} else {
result += mult;
if (result > 1000000000) {
return -1;
}
}
}
return result;

Categories