Calculating the maximum difference between two adjacent numbers in an array - java

Recently I've been assigned a task which asks to me to "calculate the maximum difference between two adjacent numbers in the array that is passed to it". I'm fairly new to Java (I have only done VB in the past) and since this topic was not well explained to me, I'm not quite sure how to go about it.
Here is some additional information about the task itself:
The function has to pass the following test. The function maxDiff should calculate the maximum difference between two adjacent numbers in the array that is passed to it.
#Test
public void assessmentTest() {
int [] numbers = {12, 8, 34, 10, 59};
assertEquals(49, maxDiff(numbers));
int [] numbers2 = {-50, 100, 20, -40};
assertEquals(150, maxDiff(numbers2));
}

You must assure to take the absolute difference, don't forget it. That's why I used the Math.abs() function.
public static int maxDiff(int[] numbers) {
int diff = Math.abs(numbers[1] - numbers[0]);
for(int i = 1; i < numbers.length-1; i++)
if(Math.abs(numbers[i+1]-numbers[i]) > diff)
diff = Math.abs(numbers[i+1] - numbers[i]);
return diff;
}

Something like this should do the trick:
public static int maxDiff(int[] numbers) {
if (numbers.length < 2) {
return 0;
}
if (numbers.length == 2) {
return Math.abs(numbers[1] - numbers[0]);
}
int max = Math.abs(numbers[1] - numbers[0]);
for (int i = 2; i < numbers.length; i++) {
int diff = Math.abs(numbers[i-1] - numbers[i]);
if (diff > max) {
max = diff;
}
}
return max;
}

For the specific question you asked:
public static int maxDiff(int[] arr) {
if(arr.length < 2)
return -1; // error condition: throw exception?
int maxdiff = Integer.MIN_VALUE;
for(int i = 1; i < arr.length; ++i) {
int diff = Math.abs(arr[i] - arr[i-1]);
if(diff > maxdiff)
maxdiff = diff;
}
return maxdiff;
}
If you want the max difference across all numbers in the array (not just adjacent ones) the most efficient way to do it would be to iterate the array just once to find the minimum and maximum, then return the absolute value of the two values subtracted from each other.
public static int maxDiff(int[] arr) {
if(arr.length < 2)
return -1; // error condition: throw exception?
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int i = 0; i < arr.length; ++i) {
if(arr[i] < min)
min = arr[i];
if(arr[i] > max)
max = arr[i];
}
return Math.abs(max - min);
}

This piece of code can help you:
int[] numbers = {12, 8, 34, 10, 59};
int diff = 0;
int previous = 0;
for (int n : numbers) {
diff = Math.max(diff, Math.abs(n - previous));
previous = n;
}
Variable "diff" will contain the value you look for.

You can use this for Java;
int arrayMaximalAdjacentDifference(int[] inputArray) {
int max=0;
for( int i = 1 ; i < inputArray.length ; i++ ){
max = Math.max(max,Math.abs(inputArray[i] - inputArray[i-1]));
}
return max;
}

Related

What is going on in my Java code to make the answers negatives?

public static int distanceBetweenMinAndMax (double[] list) {
if (list == null || list.length == 0) return 0;
int min = 0;
int max = 0;
for (int i = 1; i < list.length; i++)
{
if (list[min] > list[i])
{
min = i;
}
if (list[max] < list[i])
{
max = i;
}
}
int distanceBetweenMinandMax = max - min;
return distanceBetweenMinandMax;
}
Okay, the point of the exercise is to find the distance from the max index to the min index. No matter what, my test cases are messing up. I'll be expecting 1 and get -1. Expect 3 and get -3. And so on. I assumed it had to be the int distance... = max - min line. But even if I flip them, the result is still negative.
I've tried everything for hours. Does anyone have any input on what may be wrong here that causes the answer to be negative?
NOTE: you just can't change the public static inc to a double.
use Math.abs(min-max) -- because the index positions of Max and Min values can be crossed based on the input
int distanceBetweenMinandMax = Math.abs(min - max);
Try changing from:
int distanceBetweenMinandMax = max - min;
To:
int distanceBetweenMinandMax = max>min?(max-min):(min-max);
try this solution
public static int distanceBetweenMinAndMax (double[] list) {
if (list == null || list.length == 0) return 0;
double min = 0;
double max = 0;
int mxi=0;
int mni=0;
for (int i = 0; i < list.length; i++)
{
if (min > list[i])
{
min = list[i];
mni=i;
}
if (max < list[i])
{
max = list[i];
mxi=i;
}
}
int distanceBetweenMinandMax = mxi - mni;
return distanceBetweenMinandMax;
}
so if the result is (-) then max value is before the min value index
and if the result is (+) then max value is after the min value index
#Ptoh64 Your code is almost correct actually you get negative distance only when the max value comes earlier than the min value in the array. I mean the index of max value is less than the index of min value in array.
You have to return the absolute difference of max and min to avoid negative value for distance e.i
int distanceBetweenMinandMax = Math.abs(max - min)
The whole code will be same except above changes
public static int distanceBetweenMinAndMax(double[] list) {
if (list == null || list.length == 0)
return 0;
int min = 0;
int max = 0;
for (int i = 1; i < list.length; i++) {
if (list[min] > list[i]) {
min = i;
}
if (list[max] < list[i]) {
max = i;
}
}
int distanceBetweenMinandMax = Math.abs(max - min); // here take absolute difference
return distanceBetweenMinandMax;
}

Maximum increasing difference

I need to find the maximum increasing distance or difference between numbers in a vector. For example, in the vector [10, 5, 20, 45, 5, 5, 7] on first pass it looks that the difference between 10 and 45 is maximum. But on the second iteration the difference between 5 and 45 is larger, so it should be chosen by the algorithm.
I have a solution but it is O(n^2) and for the life of me I can't figure out if there is a solution with lower computational complexity.
public void maxDistance(int inputArray[]) {
int trueMaxValue = 0, trueMinIndex = 0, trueMaxIndex = 0, tempMaxValue;
for (int i = 0; i < inputArray.length - 1; ++i) {
for (int j = i + 1; j < inputArray.length; ++j) {
tempMaxValue = inputArray[j] - inputArray[i];
if (tempMaxValue > trueMaxValue) {
trueMaxValue = tempMaxValue;
trueMinIndex = i;
trueMaxIndex = j;
}
}
}
}
I also need to know which two numbers in the array were used in the max. Can you please help? I just don't know if I should continue to think about it or O(n^2) is the best that you can do?
You can do it in O(n) Stephany. You need to add a few variables to remember what is the current best solution. Using your current naming convention you can do the following:
public void maxDistance(int inputArray[]) {
int currentMin = inputArray[0], currentMinIndex = 0;
int trueMaxValue = 0, trueMinIndex = 0, trueMaxIndex = 0;
int tempMaxValue;
int i = 1;
while (i < inputArray.length) {
tempMaxValue = inputArray[i] - inputArray[currentMinIndex];
if (tempMaxValue > trueMaxValue) {
trueMaxValue = tempMaxValue;
trueMinIndex = currentMinIndex;
trueMaxIndex = i;
}
if (inputArray[i] < currentMin) {
currentMinIndex = i;
currentMin = inputArray[i];
}
++i;
}
Maybe I am missing something but:
iterate the array
determine the smallest entry
determine the biggest entry
compute the delta (max - min)
All of that can be done in one iteration. This would find 5 and 45 and give a difference of 40. And as said - one pass only.
This can be done in linear time.
Here is an outline:
Iterate over the array, keeping track of the smallest number seen
thus far.
Compute the difference between the smallest number seen thus far and the current number, and keep track of the largest such difference.
VoilĂ .
You've definitely got better options. I'm not sure why a nested loop was even necessary here. I'll edit to include the indices, but I'm not sure why that's helpful in the case scenario considering your array can have duplicate numbers.
int[] inputArray = new int[] {10,5,20,5,5,46,7};
int max = 0;
int min = Integer.MAX_VALUE;
for (int i = 0; i < inputArray.length; i++) {
max = inputArray[i] > max ? inputArray[i] : max;
min = inputArray[i] < min ? inputArray[i] : min;
}
int delta = max - min;
I'll edit to include the indices, but I'm not sure why that's helpful in the case scenario considering your array can have duplicate numbers.
int[] inputArray = new int[] {10,5,20,5,5,46,7};
int max = 0;
int min = Integer.MAX_VALUE;
int maxIndex = -1;
int minIndex = -1;
for (int i = 0; i < inputArray.length; i++) {
if (inputArray[i] > max) {
max = inputArray[i];
maxIndex = i;
}
if (inputArray[i] < min) {
min = inputArray[i];
minIndex = i;
}
}
int delta = max - min;

Given an array and a sum, find the max length continous subarray less than the sum

I have an array[1,2,3] and sum as 4. so all the continous sub arrays are [1],[1,2][2,3] ans [1,2,3]. So the max length subarray less than or equal to sum is [1,2]and the length is 2.
I have approached in a the following way to find all the subarrays and to check the sum of the subarrays as below. But this approach is not working with negative numbers.
{1,2,1,1,3,-2,-3,7,9}; - Ans : 7
private static void maximumSubArray(int[] a, int sum) {
int start = 0;
int end =0;
int mylen =-1;
int subarrSum =0;
for(int i=0;i<a.length;i++){
subarrSum += a[i];
end++;
while(subarrSum > sum){
subarrSum-= a[start];
start +=1;
}
mylen = Math.max(mylen, end-start);
}
System.out.println(mylen + " -- My len");
}
This is a variation of the classical maximum contiguous subarray problem. You can use dynamic programming (memorization) to solve this problem. Try something like this:
private static void maximumSubArray(int[] a, long sum, int maxLen) {
long maximumSoFar = Long.MIN_VALUE;
long maximumEndingHere = Long.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
// if you're inside the array beyond maxLen, start dropping off the previous start element
int prevStart = i >= maxLen ? a[i - maxLen] : 0;
maximumEndingHere = Math.max(a[i], maximumEndingHere + a[i] - prevStart);
if (maximumEndingHere > maximumSoFar && maximumEndingHere <= sum) {
maximumSoFar = maximumEndingHere;
} else if (a[i] > maximumSoFar && a[i] <= sum) {
maximumSoFar = a[i];
} else if (maximumEndingHere > sum) {
maximumEndingHere -= prevStart;
}
}
System.out.println(maximumSoFar);
}
If I had some more time, I'd write the logic inside for loop in a cleaner way, but this should work and it works in O(n) time.

Function takes a martix (2d array) and prints the max number of the even numbers in each line

I am defining a function to accept a matrix (2d array), for example x[][]; and the function should print the biggest even number in each line
public static void biggestEvenNumOfEachLine(int x[][]){
int even,t=0,max;
int arr[] = new int [x.length];
for(int i = 0; i < x.length;i++){
for(int j = 0; j < x[i].length;j++,t++){
if(x[i][j] % 2 == 0){
even = x[i][j];
arr[j] = even;
}
}
}
}
What am I missing?
I would start by finding the biggest even number in a single line array. Start with the smallest possible value, and then iterate the array. Test for even, and then set the max (and then return it). Something like,
private static int biggestEvenNum(int[] x) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 == 0) {
max = Math.max(max, x[i]);
}
}
return max;
}
But, in Java 8+, I would prefer to filter for even values and get the max like
private static int biggestEvenNum(int[] x) {
return IntStream.of(x).filter(v -> v % 2 == 0).max().getAsInt();
}
Then your method is as simple as iterating the line(s) in your matrix, printing the result. Like,
public static void biggestEvenNumOfEachLine(int[][] x) {
for (int[] line : x) {
System.out.println(biggestEvenNum(line));
}
}
public static void biggestEvenNumOfEachLine(int x[][])
{
int arr[] = new int [x.length];
for(int i = 0; i < x.length;i++)
for(int j = 0; j < x[i].length;j++)
if(x[i][j] % 2 == 0 && x[i][j] > arr[i]){
arr[i] = x[i][j];
System.out.println(arr[i]);
}
}
This will work but if there is no even number at particular line then corresponding number to that line will be zero.

How can I find the smallest covering prefix of an array in Java?

Find the first covering prefix of a given array.
A non-empty zero-indexed array A consisting of N integers is given. The first covering
prefix of array A is the smallest integer P such that and such that every value that
occurs in array A also occurs in sequence.
For example, the first covering prefix of array A with
A[0]=2, A[1]=2, A[2]=1, A[3]=0, A[4]=1 is 3, because sequence A[0],
A[1], A[2], A[3] equal to 2, 2, 1, 0 contains all values that occur in
array A.
My solution is
int ps ( int[] A )
{
int largestvalue=0;
int index=0;
for(each element in Array){
if(A[i]>largestvalue)
{
largestvalue=A[i];
index=i;
}
}
for(each element in Array)
{
if(A[i]==index)
index=i;
}
return index;
}
But this only works for this input, this is not a generalized solution.
Got 100% with the below.
public int ps (int[] a)
{
var length = a.Length;
var temp = new HashSet<int>();
var result = 0;
for (int i=0; i<length; i++)
{
if (!temp.Contains(a[i]))
{
temp.Add(a[i]);
result = i;
}
}
return result;
}
I would do this
int coveringPrefixIndex(final int[] arr) {
Map<Integer,Integer> indexes = new HashMap<Integer,Integer>();
// start from the back
for(int i = arr.length - 1; i >= 0; i--) {
indexes.put(arr[i],i);
}
// now find the highest value in the map
int highestIndex = 0;
for(Integer i : indexes.values()) {
if(highestIndex < i.intValue()) highestIndex = i.intValue();
}
return highestIndex;
}
Your question is from Alpha 2010 Start Challenge of Codility platform. And here is my solution which got score of 100. The idea is simple, I track an array of counters for the input array. Traversing the input array backwards, decrement the respective counter, if that counter becomes zero it means we have found the first covering prefix.
public static int solution(int[] A) {
int size = A.length;
int[] counters = new int[size];
for (int a : A)
counters[a]++;
for (int i = size - 1; i >= 0; i--) {
if (--counters[A[i]] == 0)
return i;
}
return 0;
}
here's my solution in C#:
public static int CoveringPrefix(int[] Array1)
{
// Step 1. Get length of Array1
int Array1Length = 0;
foreach (int i in Array1) Array1Length++;
// Step 2. Create a second array with the highest value of the first array as its length
int highestNum = 0;
for (int i = 0; i < Array1Length; i++)
{
if (Array1[i] > highestNum) highestNum = Array1[i];
}
highestNum++; // Make array compatible for our operation
int[] Array2 = new int[highestNum];
for (int i = 0; i < highestNum; i++) Array2[i] = 0; // Fill values with zeros
// Step 3. Final operation will determine unique values in Array1 and return the index of the highest unique value
int highestIndex = 0;
for (int i = 0; i < Array1Length; i++)
{
if (Array2[Array1[i]] < 1)
{
Array2[Array1[i]]++;
highestIndex = i;
}
}
return highestIndex;
}
100p
public static int ps(int[] a) {
Set<Integer> temp = new HashSet<Integer>();
int p = 0;
for (int i = 0; i < a.length; i++) {
if (temp.add(a[i])) {
p = i+1;
}
}
return p;
}
You can try this solution as well
import java.util.HashSet;
import java.util.Set;
class Solution {
public int ps ( int[] A ) {
Set set = new HashSet();
int index =-1;
for(int i=0;i<A.length;i++){
if(set.contains(A[i])){
if(index==-1)
index = i;
}else{
index = i;
set.add(A[i]);
}
}
return index;
}
}
Without using any Collection:
search the index of the first occurrence of each element,
the prefix is the maximum of that index. Do it backwards to finish early:
private static int prefix(int[] array) {
int max = -1;
int i = array.length - 1;
while (i > max) {
for (int j = 0; j <= i; j++) { // include i
if (array[i] == array[j]) {
if (j > max) {
max = j;
}
break;
}
}
i--;
}
return max;
}
// TEST
private static void test(int... array) {
int prefix = prefix(array);
int[] segment = Arrays.copyOf(array, prefix+1);
System.out.printf("%s = %d = %s%n", Arrays.toString(array), prefix, Arrays.toString(segment));
}
public static void main(String[] args) {
test(2, 2, 1, 0, 1);
test(2, 2, 1, 0, 4);
test(2, 0, 1, 0, 1, 2);
test(1, 1, 1);
test(1, 2, 3);
test(4);
test(); // empty array
}
This is what I tried first. I got 24%
public int ps ( int[] A ) {
int n = A.length, i = 0, r = 0,j = 0;
for (i=0;i<n;i++) {
for (j=0;j<n;j++) {
if ((long) A[i] == (long) A[j]) {
r += 1;
}
if (r == n) return i;
}
}
return -1;
}
//method must be public for codility to access
public int solution(int A[]){
Set<Integer> set = new HashSet<Integer>(A.length);
int index= A[0];
for (int i = 0; i < A.length; i++) {
if( set.contains(A[i])) continue;
index = i;
set.add(A[i]);
}
return index;
}
this got 100%, however detected time was O(N * log N) due to the HashSet.
your solutions without hashsets i don't really follow...
shortest code possible in java:
public static int solution(int A[]){
Set<Integer> set = new HashSet<Integer>(A.length);//avoid resizing
int index= -1; //value does not matter;
for (int i = 0; i < A.length; i++)
if( !set.contains(A[i])) set.add(A[index = i]); //assignment + eval
return index;
}
I got 100% with this one:
public int solution (int A[]){
int index = -1;
boolean found[] = new boolean[A.length];
for (int i = 0; i < A.length; i++)
if (!found [A[i]] ){
index = i;
found [A[i]] = true;
}
return index;
}
I used a boolean array which keeps track of the read elements.
This is what I did in Java to achieve 100% correctness and 81% performance, using a list to store and compare the values with.
It wasn't quick enough to pass random_n_log_100000 random_n_10000 or random_n_100000 tests, but it is a correct answer.
public int solution(int[] A) {
int N = A.length;
ArrayList<Integer> temp = new ArrayList<Integer>();
for(int i=0; i<N; i++){
if(!temp.contains(A[i])){
temp.add(A[i]);
}
}
for(int j=0; j<N; j++){
if(temp.contains(A[j])){
temp.remove((Object)A[j]);
}
if(temp.isEmpty()){
return j;
}
}
return -1;
}
Correctness and Performance: 100%:
import java.util.HashMap;
class Solution {
public int solution(int[] inputArray)
{
int covering;
int[] A = inputArray;
int N = A.length;
HashMap<Integer, Integer> map = new HashMap<>();
covering = 0;
for (int i = 0; i < N; i++)
{
if (map.get(A[i]) == null)
{
map.put(A[i], A[i]);
covering = i;
}
}
return covering;
}
}
Here is my Objective-C Solution to PrefixSet from Codility. 100% correctness and performance.
What can be changed to make it even more efficient? (without out using c code).
HOW IT WORKS:
Everytime I come across a number in the array I check to see if I have added it to the dictionary yet.
If it is in the dictionary then I know it is not a new number so not important in relation to the problem. If it is a new number that we haven't come across already, then I need to update the indexOftheLastPrefix to this array position and add it to the dictionary as a key.
It only used one for loop so takes just one pass. Objective-c code is quiet heavy so would like to hear of any tweaks to make this go faster. It did get 100% for performance though.
int solution(NSMutableArray *A)
{
NSUInteger arraySize = [A count];
NSUInteger indexOflastPrefix=0;
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
for (int i=0; i<arraySize; i++)
{
if ([myDict objectForKey:[[A objectAtIndex:i]stringValue]])
{
}
else
{
[myDict setValue:#"YES" forKey:[[A objectAtIndex:i]stringValue]];
indexOflastPrefix = i;
}
}
return indexOflastPrefix;
}
int solution(vector &A) {
// write your code in C++11 (g++ 4.8.2)
int max = 0, min = -1;
int maxindex =0,minindex = 0;
min = max =A[0];
for(unsigned int i=1;i<A.size();i++)
{
if(max < A[i] )
{
max = A[i];
maxindex =i;
}
if(min > A[i])
{
min =A[i];
minindex = i;
}
}
if(maxindex > minindex)
return maxindex;
else
return minindex;
}
fwiw: Also gets 100% on codility and it's easy to understand with only one HashMap
public static int solution(int[] A) {
// write your code in Java SE 8
int firstCoveringPrefix = 0;
//HashMap stores unique keys
HashMap hm = new HashMap();
for(int i = 0; i < A.length; i++){
if(!hm.containsKey(A[i])){
hm.put( A[i] , i );
firstCoveringPrefix = i;
}
}
return firstCoveringPrefix;
}
I was looking for the this answer in JavaScript but didn't find it so I convert the Java answer to javascript and got 93%
function solution(A) {
result=0;
temp = [];
for(i=0;i<A.length;i++){
if (!temp.includes(A[i])){
temp.push(A[i]);
result=i;
}
}
return result;
}
// you can also use imports, for example:
import java.util.*;
// you can use System.out.println for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
Set<Integer> s = new HashSet<Integer>();
int index = 0;
for (int i = 0; i < A.length; i++) {
if (!s.contains(A[i])) {
s.add(A[i]);
index = i;
}
}
return index;
}
}

Categories