It's trivial to write a function to determine the min/max value in an array, such as:
/**
*
* #param chars
* #return the max value in the array of chars
*/
private static int maxValue(char[] chars) {
int max = chars[0];
for (int ktr = 0; ktr < chars.length; ktr++) {
if (chars[ktr] > max) {
max = chars[ktr];
}
}
return max;
}
but isn't this already done somewhere?
Using Commons Lang (to convert) + Collections (to min/max)
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang.ArrayUtils;
public class MinMaxValue {
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
List b = Arrays.asList(ArrayUtils.toObject(a));
System.out.println(Collections.min(b));
System.out.println(Collections.max(b));
}
}
Note that Arrays.asList() wraps the underlying array, so it should not be too memory intensive and it should not perform a copy on the elements of the array.
You can simply use the new Java 8 Streams but you have to work with int.
The stream method of the utility class Arrays gives you an IntStream on which you can use the min method. You can also do max, sum, average,...
The getAsInt method is used to get the value from the OptionalInt
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
int min = Arrays.stream(tab).min().getAsInt();
int max = Arrays.stream(tab).max().getAsInt();
System.out.println("Min = " + min);
System.out.println("Max = " + max)
}
}
==UPDATE==
If execution time is important and you want to go through the data only once you can use the summaryStatistics() method like this
import java.util.Arrays;
import java.util.IntSummaryStatistics;
public class SOTest {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
int min = stat.getMin();
int max = stat.getMax();
System.out.println("Min = " + min);
System.out.println("Max = " + max);
}
}
This approach can give better performance than classical loop because the summaryStatistics method is a reduction operation and it allows parallelization.
The Google Guava library has min and max methods in its Chars, Ints, Longs, etc. classes.
So you can simply use:
Chars.min(myarray)
No conversions are required and presumably it's efficiently implemented.
By sorting the array, you get the first and last values for min / max.
import java.util.Arrays;
public class apples {
public static void main(String[] args) {
int a[] = {2,5,3,7,8};
Arrays.sort(a);
int min =a[0];
System.out.println(min);
int max= a[a.length-1];
System.out.println(max);
}
}
Although the sorting operation is more expensive than simply finding min/max values with a simple loop. But when performance is not a concern (e.g. small arrays, or your the cost is irrelevant for your application), it is a quite simple solution.
Note: the array also gets modified after this.
Yes, it's done in the Collections class. Note that you will need to convert your primitive char array to a Character[] manually.
A short demo:
import java.util.*;
public class Main {
public static Character[] convert(char[] chars) {
Character[] copy = new Character[chars.length];
for(int i = 0; i < copy.length; i++) {
copy[i] = Character.valueOf(chars[i]);
}
return copy;
}
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
Character[] b = convert(a);
System.out.println(Collections.max(Arrays.asList(b)));
}
}
I have a little helper class in all of my applications with methods like:
public static double arrayMax(double[] arr) {
double max = Double.NEGATIVE_INFINITY;
for(double cur: arr)
max = Math.max(max, cur);
return max;
}
You could easily do it with an IntStream and the max() method.
Example
public static int maxValue(final int[] intArray) {
return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}
Explanation
range(0, intArray.length) - To get a stream with as many elements as present in the intArray.
map(i -> intArray[i]) - Map every element of the stream to an actual element of the intArray.
max() - Get the maximum element of this stream as OptionalInt.
getAsInt() - Unwrap the OptionalInt. (You could also use here: orElse(0), just in case the OptionalInt is empty.)
public int getMin(int[] values){
int ret = values[0];
for(int i = 1; i < values.length; i++)
ret = Math.min(ret,values[i]);
return ret;
}
import java.util.Random;
public class Main {
public static void main(String[] args) {
int a[] = new int [100];
Random rnd = new Random ();
for (int i = 0; i< a.length; i++) {
a[i] = rnd.nextInt(99-0)+0;
System.out.println(a[i]);
}
int max = 0;
for (int i = 0; i < a.length; i++) {
a[i] = max;
for (int j = i+1; j<a.length; j++) {
if (a[j] > max) {
max = a[j];
}
}
}
System.out.println("Max element: " + max);
}
}
A solution with reduce():
int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97
In the code above, reduce() returns data in Optional format, which you can convert to int by getAsInt().
If we want to compare the max value with a certain number, we can set a start value in reduce():
int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100
In the code above, when reduce() with an identity (start value) as the first parameter, it returns data in the same format with the identity. With this property, we can apply this solution to other arrays:
double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Here's a utility class providing min/max methods for primitive types: Primitives.java
int [] numbers= {10,1,8,7,6,5,2};
int a=Integer.MAX_VALUE;
for(int c:numbers) {
a=c<a?c:a;
}
System.out.println("Lowest value is"+a);
Example with float:
public static float getMaxFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[data.length - 1];
}
public static float getMinFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[0];
}
Pass the array to a method that sorts it with Arrays.sort() so it only sorts the array the method is using then sets min to array[0] and max to array[array.length-1].
The basic way to get the min/max value of an Array. If you need the unsorted array, you may create a copy or pass it to a method that returns the min or max. If not, sorted array is better since it performs faster in some cases.
public class MinMaxValueOfArray {
public static void main(String[] args) {
int[] A = {2, 4, 3, 5, 5};
Arrays.sort(A);
int min = A[0];
int max = A[A.length -1];
System.out.println("Min Value = " + min);
System.out.println("Max Value = " + max);
}
}
Here is a solution to get the max value in about 99% of runs (change the 0.01 to get a better result):
public static double getMax(double[] vals){
final double[] max = {Double.NEGATIVE_INFINITY};
IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
.forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
return max[0];
}
(Not completely serious)
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
int max_ = Collections.max(list);
int i;
if (max_ > 0) {
for (i = 1; i < Collections.max(list); i++) {
if (!list.contains(i)) {
System.out.println(i);
break;
}
}
if(i==max_){
System.out.println(i+1);
}
} else {
System.out.println("1");
}
}
Related
I tried the codility demo test, but never get more than 77% due to their performance tests.
the test mainly states:
given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
Whats wrong with my solution?
The failed performance test comlains:TIMEOUT ERROR
running time: 0.152 sec., time limit: 0.100 sec.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
class Solution3 {
int solution(int[] A) {
ArrayList<Integer> list = Arrays.stream(A).boxed().distinct().sorted()
.filter(i -> i > 0)
.collect(Collectors.toCollection(ArrayList::new));
Integer prev_item = 0;
for (int i = 0; i < list.size(); i++) {
Integer item = list.get(i);
if (!(item - 1 == prev_item)) {
return prev_item + 1;
}
prev_item = item;
}
return prev_item + 1;
}
public static void main(String[] args) {
Solution3 solution3 = new Solution3();
int[] A = new int[6];
A[0] = 1;
A[1] = 2;
A[2] = 3;
A[3] = 8;
A[4] = 8;
A[5] = 11;
int solution = solution3.solution(A);
System.out.println("solution: " + solution);
}
}
I came up with this solution and it scored 100%. It is in python, if someone wants it in java I will post that too. Just let me know.
def solution(A):
A.sort()
smallest = 1
for i in range(0, len(A)):
if A[i] > 0:
if smallest < A[i]:
return smallest
elif smallest == A[i]:
smallest = smallest + 1
return smallest
I think the main problem is that and how you transform the array to an ArrayList and put work into cleaning it from negative values.
It would be a lot better in terms of performance if you would just sort the array with Arrays.sort(A) and then binary search it for the first positive value and do the rest from there.
I found the solution with following code:
function smallest(A) {
const set = new Set(A);
let i=1;
while(set.includes(i)) {
i++;
}
return i;
}
how could I know that brute force iteration is a solution here. would expect that performance is bad for big arrays
public class Foo {
public static void main(String[] args) {
Integer[] ints = { 11, 2, 6, 3, 4, 8, 1, 5 };
System.out.println(findSmallest(ints));
}
private static Integer findSmallest(Integer[] ints){
List<Integer> integers = Arrays.asList(ints);
for (int i = 1; i < Integer.MAX_VALUE; i++) {
if (!integers.contains(i)) {
return i;
}
}
return Integer.MAX_VALUE;
}
}
I am struggling in my code with an error.
This is the error I got:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method recur(Integer[]) in the type D_and_con is not applicable for the arguments (int[])
at edu.uqu.algorithms.inversions.D_and_con.recur(D_and_con.java:27)
at edu.uqu.algorithms.inversions.MainTest.main(MainTest.java:27)
The code computes the number of inversions.
It is:
package edu.uqu.algorithms.inversions;
import java.io.FileNotFoundException;
import java.util.Arrays;
import edu.uqu.algorithms.inversions.util.IOUtil;
public class MainTest {
public static void main(String[] args) {
try {
/*//Inversions using BRUTE FORCE
Integer[] tokens1 = IOUtil.loadFileIntoArray("IntegerArray.txt");
long startTime1 = System.currentTimeMillis();
System.out.println("Started Computing Total nb of invertions BRUTE FORCE..........................");
System.out.println("Total nb of invertions BRUTE FORCE: " + Inversions.countInvertionsBruteForce(tokens1));
long runningTime1 = (System.currentTimeMillis() - startTime1);
System.out.println("BRUTE FORCE Running time: " + runningTime1);
System.out.println("\n");*/
//Inversions using DIVIDE & CONQUER
Integer[] tokens2 = IOUtil.loadFileIntoArray("IntegerArray.txt");
long startTime2 = System.currentTimeMillis();
System.out.println("Started Computing Total nb of invertions DIVIDE & CONQUER..........................");
System.out.println("MMMMM" + D_and_con.recur(tokens2) );
long runningTime2 = (System.currentTimeMillis() - startTime2);
System.out.println("DIVIDE & CONQUER Running time: " + runningTime2);
System.out.println("----------------------- FINISHED -------------------------");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
----------------------------------------
/************************************
*
* The aim of this code is to count the number of inversions in
* an array of integers. Two ways of counting are used, a Brute Force algorithm and
* a recursive Divide and Conquer algorithm.
*
***********************************/
package edu.uqu.algorithms.inversions;
/**
public class Inversions{
/**
* Brute force inversions counting method.
*/
public static long countInvertionsBruteForce(Integer[] entries_p)
{
long result = 0;
for(int i = 0; i < entries_p.length; i++){
for(int j = i+1; j < entries_p.length; j++){
if(entries_p[i] > entries_p[j]) result++;
}
//System.out.println("BRUTE FORCE intermediate result for i = " + i + " IS: " + result);
}
return result;
}
}
--------------------------
Divide and conquer
/************************************
*
* The aim of this code is to count the number of inversions in
* an array of integers. Two ways of counting are used, a Brute Force algorithm and
* a recursive Divide and Conquer algorithm.
*
***********************************/
package edu.uqu.algorithms.inversions;
import java.math.BigDecimal;
public class D_and_con{
private static BigDecimal totalcount = new BigDecimal(0);
public static Integer[] recur(Integer[] entries_p)
{
int n = entries_p.length;
if(n == 1)
{
return entries_p;
}
int middel = n/2;
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
System.arraycopy(entries_p , 0 , Larray, 0 , Larray.length );
System.arraycopy(entries_p , Larray.length , Rarray , 0 , Rarray.length);
recur(Larray);\\ERROR APPEAR HERE
recur(Rarray);\\ERROR APPEAR HERE
comb(Larray , Rarray , entries_p );
return entries_p;
}
private static void comb(int[] Larray, int[] Rarray, Integer[] newarray)
{
int LarrayL = Larray.length;
int RarrayL = Rarray.length;
int i=0 , j=0 , k=0 ;
while(i< LarrayL && i<RarrayL)
{
if(Larray[i] < Rarray[i] )
{
newarray[k] = Larray[i];
i++;
}
else
{
newarray[k] = Rarray[j];
i++;
totalcount = totalcount.add (new BigDecimal(Larray.length - 1));
}
k++;
}
while(i < LarrayL) {
newarray[k] = Larray[i];
i++;
k++;
}
while(j < RarrayL) {
newarray[k] = Rarray[j];
j++;
k++;
}
}
}
Explanation
The compiler complaints that you feed your recur method with something of type int[] but you declared that it accepts Integer[]. Therefore take a look at the method signature
// entries_p is Integer[], not int[]
public static Integer[] recur(Integer[] entries_p)
but you feed the method with int[] as seen here
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
...
recur(Larray);
recur(Rarray);
Integer is different to int. Though Java can automatically convert both into each other (boxing) it won't do that for advanced types liked arrays Integer[] and int[].
Converting
You will need to convert the types by yourself. Note that Integer[] in contrast to int[] is capable of storing null.
Here are some easy conversions, first without using Streams:
// from int[] to Integer[]
int[] source = ...
Integer[] target = new Integer[source.length];
for (int i = 0; i < source.length; i++) {
// Convert int to Integer
target[i] = Integer.valueOf(source[i]);
}
// from Integer[] to int[]
Integer[] source = ...
int[] target = new int[source.length];
for (int i = 0; i < source.length; i++) {
if (source[i] == null) {
// Don't support null values
throw IllegalArgumentException();
}
// Convert Integer to int
target[i] = source[i].intValue();
}
And now the same using Streams (Java 8):
// from int[] to Integer[]
int[] source = ...
Integer[] target = Arrays.stream() // IntStream
.boxed() // Stream<Integer>
.toArray(Integer[]::new)
// from Integer[] to int[]
Integer[] source = ...
int[] target = Arrays.stream() // Stream<Integer>
.mapToInt(Integer::intValue) // Stream<Integer>
.toArray(int[]::new)
Changing method or argument
Instead of converting the array from one into the other type you may also adjust your method or the argument. For example you could change the method signature from
public static Integer[] recur(Integer[] entries_p)
to
public static Integer[] recur(int[] entries_p)
then it will accept int[] as argument. You may also change the return type to int[]. The other alternative would, as said, be to change the argument from int[] to Integer[]. This applies to that code section:
// You may change both to Integer[]
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
Change your Integer[] arrays to int[] arrays!
"int" is a primitive data-type and "Integer" is a Class.
To solve your problem:-
1 - Integer[] tokens2 = IOUtil.loadFileIntoArray("IntegerArray.txt"); //Read data from file in int[].
2 - Integer[] recur(Integer[] entries_p){} //change it as int[] recur(int[] entries_p)
I am using a list of integer arrays, which is a class variable, to hold the answers. The integer arrays are added to the list in a method, and the results are fine (has 1s). But when I fetch it in main method, the value in it is all 0s! I do not understand, where is the list changed?
public class test {
private static int sum=0;
static ArrayList<Integer[]> res = new ArrayList<Integer[]>();
private static double max=0;
public static void main(String[] args) {
int n = 6;
double B = 23.6;
double[] menu = { 1.2, 2, 2.5, 3.5, 3.2, 6.2, 7.8, 4.0, 5.6, 10, 6.5 };
Integer[] solution = new Integer[menu.length];
combinate(menu, 0, n,0, res, solution);
for(int i=0;i<res.size();i++) {
//not getting the element!!!!!!!!!!!!
//Integer[] sol = res.get(i);
System.out.println(i+" "+res.get(i));
System.out.println("Arraylist contains:"+Arrays.toString( res.get( i ) ) );
double sums = 0.0;
for (int j = 0; j < res.get(i).length; j++) {
if(res.get(i)[j]!=null)
sums += menu[j] * res.get(i)[j];
}
if (max < sums && sums < B) {
max = sums;
}
}
System.out.println(max + " max");
}
public static void combinate(double[] left, int n, int k,int sum,
ArrayList<Integer[]> res, Integer[] holder) {
if (n == left.length) {
if (sum == k) {
res.add(holder);
System.out.println(res.size()+" "+Arrays.toString(res.get(res.size()-1)));
}
sum = 0;
return;
}
{
holder[n] = 1;
sum++;
combinate(left, n + 1, k, sum,res, holder);
holder[n] = 0;
sum--;
combinate(left, n + 1, k, sum,res, holder);
}
}
}
}
The answers looks like this:
when print in method combinate, the list elements looks like [1111100000]
while in main method, there are all [000000000000]
what goes wrong here?
if (sum == k)
{
res.add(holder.clone()); // take copy of holder at that moment
System.out.println(res.size()+" "+Arrays.toString(res.get(res.size()-1)));
}
Will Help.
[See Experiment : http://rextester.com/DNNZ68674 ]
Have your method "combinate" return new res like public static ArrayList<Integer[]> combinate(double[] left, int n, int k,int sum,
ArrayList<Integer[]> res, Integer[] holder)
then in your main : res = combinate(...);
You have only a single Integer[] instance that you add to your result (res.add(holder)) and overwrite while unwinding the recursion.
You should add a clone of your array to the result:
res.add(holder.clone());
In the original code you're passing the "holder"-variable as a parameter. In Java parameters are passed by value.
This means, you can change the value inside of the combinate-function, but this will never be reflected back to the calling main-function - that's the nature of call by value.
It's trivial to write a function to determine the min/max value in an array, such as:
/**
*
* #param chars
* #return the max value in the array of chars
*/
private static int maxValue(char[] chars) {
int max = chars[0];
for (int ktr = 0; ktr < chars.length; ktr++) {
if (chars[ktr] > max) {
max = chars[ktr];
}
}
return max;
}
but isn't this already done somewhere?
Using Commons Lang (to convert) + Collections (to min/max)
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang.ArrayUtils;
public class MinMaxValue {
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
List b = Arrays.asList(ArrayUtils.toObject(a));
System.out.println(Collections.min(b));
System.out.println(Collections.max(b));
}
}
Note that Arrays.asList() wraps the underlying array, so it should not be too memory intensive and it should not perform a copy on the elements of the array.
You can simply use the new Java 8 Streams but you have to work with int.
The stream method of the utility class Arrays gives you an IntStream on which you can use the min method. You can also do max, sum, average,...
The getAsInt method is used to get the value from the OptionalInt
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
int min = Arrays.stream(tab).min().getAsInt();
int max = Arrays.stream(tab).max().getAsInt();
System.out.println("Min = " + min);
System.out.println("Max = " + max)
}
}
==UPDATE==
If execution time is important and you want to go through the data only once you can use the summaryStatistics() method like this
import java.util.Arrays;
import java.util.IntSummaryStatistics;
public class SOTest {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
int min = stat.getMin();
int max = stat.getMax();
System.out.println("Min = " + min);
System.out.println("Max = " + max);
}
}
This approach can give better performance than classical loop because the summaryStatistics method is a reduction operation and it allows parallelization.
The Google Guava library has min and max methods in its Chars, Ints, Longs, etc. classes.
So you can simply use:
Chars.min(myarray)
No conversions are required and presumably it's efficiently implemented.
By sorting the array, you get the first and last values for min / max.
import java.util.Arrays;
public class apples {
public static void main(String[] args) {
int a[] = {2,5,3,7,8};
Arrays.sort(a);
int min =a[0];
System.out.println(min);
int max= a[a.length-1];
System.out.println(max);
}
}
Although the sorting operation is more expensive than simply finding min/max values with a simple loop. But when performance is not a concern (e.g. small arrays, or your the cost is irrelevant for your application), it is a quite simple solution.
Note: the array also gets modified after this.
Yes, it's done in the Collections class. Note that you will need to convert your primitive char array to a Character[] manually.
A short demo:
import java.util.*;
public class Main {
public static Character[] convert(char[] chars) {
Character[] copy = new Character[chars.length];
for(int i = 0; i < copy.length; i++) {
copy[i] = Character.valueOf(chars[i]);
}
return copy;
}
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
Character[] b = convert(a);
System.out.println(Collections.max(Arrays.asList(b)));
}
}
I have a little helper class in all of my applications with methods like:
public static double arrayMax(double[] arr) {
double max = Double.NEGATIVE_INFINITY;
for(double cur: arr)
max = Math.max(max, cur);
return max;
}
You could easily do it with an IntStream and the max() method.
Example
public static int maxValue(final int[] intArray) {
return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}
Explanation
range(0, intArray.length) - To get a stream with as many elements as present in the intArray.
map(i -> intArray[i]) - Map every element of the stream to an actual element of the intArray.
max() - Get the maximum element of this stream as OptionalInt.
getAsInt() - Unwrap the OptionalInt. (You could also use here: orElse(0), just in case the OptionalInt is empty.)
public int getMin(int[] values){
int ret = values[0];
for(int i = 1; i < values.length; i++)
ret = Math.min(ret,values[i]);
return ret;
}
import java.util.Random;
public class Main {
public static void main(String[] args) {
int a[] = new int [100];
Random rnd = new Random ();
for (int i = 0; i< a.length; i++) {
a[i] = rnd.nextInt(99-0)+0;
System.out.println(a[i]);
}
int max = 0;
for (int i = 0; i < a.length; i++) {
a[i] = max;
for (int j = i+1; j<a.length; j++) {
if (a[j] > max) {
max = a[j];
}
}
}
System.out.println("Max element: " + max);
}
}
A solution with reduce():
int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97
In the code above, reduce() returns data in Optional format, which you can convert to int by getAsInt().
If we want to compare the max value with a certain number, we can set a start value in reduce():
int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100
In the code above, when reduce() with an identity (start value) as the first parameter, it returns data in the same format with the identity. With this property, we can apply this solution to other arrays:
double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Here's a utility class providing min/max methods for primitive types: Primitives.java
int [] numbers= {10,1,8,7,6,5,2};
int a=Integer.MAX_VALUE;
for(int c:numbers) {
a=c<a?c:a;
}
System.out.println("Lowest value is"+a);
Example with float:
public static float getMaxFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[data.length - 1];
}
public static float getMinFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[0];
}
Pass the array to a method that sorts it with Arrays.sort() so it only sorts the array the method is using then sets min to array[0] and max to array[array.length-1].
The basic way to get the min/max value of an Array. If you need the unsorted array, you may create a copy or pass it to a method that returns the min or max. If not, sorted array is better since it performs faster in some cases.
public class MinMaxValueOfArray {
public static void main(String[] args) {
int[] A = {2, 4, 3, 5, 5};
Arrays.sort(A);
int min = A[0];
int max = A[A.length -1];
System.out.println("Min Value = " + min);
System.out.println("Max Value = " + max);
}
}
Here is a solution to get the max value in about 99% of runs (change the 0.01 to get a better result):
public static double getMax(double[] vals){
final double[] max = {Double.NEGATIVE_INFINITY};
IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
.forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
return max[0];
}
(Not completely serious)
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
int max_ = Collections.max(list);
int i;
if (max_ > 0) {
for (i = 1; i < Collections.max(list); i++) {
if (!list.contains(i)) {
System.out.println(i);
break;
}
}
if(i==max_){
System.out.println(i+1);
}
} else {
System.out.println("1");
}
}
I'm trying to calculate the total, mean and median of an array thats populated by input received by a textfield. I've managed to work out the total and the mean, I just can't get the median to work. I think the array needs to be sorted before I can do this, but I'm not sure how to do this. Is this the problem, or is there another one that I didn't find? Here is my code:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;
public class whileloopq extends Applet implements ActionListener
{
Label label;
TextField input;
int num;
int index;
int[] numArray = new int[20];
int sum;
int total;
double avg;
int median;
public void init ()
{
label = new Label("Enter numbers");
input = new TextField(5);
add(label);
add(input);
input.addActionListener(this);
index = 0;
}
public void actionPerformed (ActionEvent ev)
{
int num = Integer.parseInt(input.getText());
numArray[index] = num;
index++;
if (index == 20)
input.setEnabled(false);
input.setText("");
sum = 0;
for (int i = 0; i < numArray.length; i++)
{
sum += numArray[i];
}
total = sum;
avg = total / index;
median = numArray[numArray.length/2];
repaint();
}
public void paint (Graphics graf)
{
graf.drawString("Total = " + Integer.toString(total), 25, 85);
graf.drawString("Average = " + Double.toString(avg), 25, 100);
graf.drawString("Median = " + Integer.toString(median), 25, 115);
}
}
The Arrays class in Java has a static sort function, which you can invoke with Arrays.sort(numArray).
Arrays.sort(numArray);
double median;
if (numArray.length % 2 == 0)
median = ((double)numArray[numArray.length/2] + (double)numArray[numArray.length/2 - 1])/2;
else
median = (double) numArray[numArray.length/2];
Sorting the array is unnecessary and inefficient. There's a variation of the QuickSort (QuickSelect) algorithm which has an average run time of O(n); if you sort first, you're down to O(n log n). It actually finds the nth smallest item in a list; for a median, you just use n = half the list length. Let's call it quickNth (list, n).
The concept is that to find the nth smallest, choose a 'pivot' value. (Exactly how you choose it isn't critical; if you know the data will be thoroughly random, you can take the first item on the list.)
Split the original list into three smaller lists:
One with values smaller than the pivot.
One with values equal to the pivot.
And one with values greater than the pivot.
You then have three cases:
The "smaller" list has >= n items. In that case, you know that the nth smallest is in that list. Return quickNth(smaller, n).
The smaller list has < n items, but the sum of the lengths of the smaller and equal lists have >= n items. In this case, the nth is equal to any item in the "equal" list; you're done.
n is greater than the sum of the lengths of the smaller and equal lists. In that case, you can essentially skip over those two, and adjust n accordingly. Return quickNth(greater, n - length(smaller) - length(equal)).
Done.
If you're not sure that the data is thoroughly random, you need to be more sophisticated about choosing the pivot. Taking the median of the first value in the list, the last value in the list, and the one midway between the two works pretty well.
If you're very unlucky with your choice of pivots, and you always choose the smallest or highest value as your pivot, this takes O(n^2) time; that's bad. But, it's also very unlikely if you choose your pivot with a decent algorithm.
Sample code:
import java.util.*;
public class Utility {
/****************
* #param coll an ArrayList of Comparable objects
* #return the median of coll
*****************/
public static <T extends Number> double median(ArrayList<T> coll, Comparator<T> comp) {
double result;
int n = coll.size()/2;
if (coll.size() % 2 == 0) // even number of items; find the middle two and average them
result = (nth(coll, n-1, comp).doubleValue() + nth(coll, n, comp).doubleValue()) / 2.0;
else // odd number of items; return the one in the middle
result = nth(coll, n, comp).doubleValue();
return result;
} // median(coll)
/*****************
* #param coll a collection of Comparable objects
* #param n the position of the desired object, using the ordering defined on the list elements
* #return the nth smallest object
*******************/
public static <T> T nth(ArrayList<T> coll, int n, Comparator<T> comp) {
T result, pivot;
ArrayList<T> underPivot = new ArrayList<>(), overPivot = new ArrayList<>(), equalPivot = new ArrayList<>();
// choosing a pivot is a whole topic in itself.
// this implementation uses the simple strategy of grabbing something from the middle of the ArrayList.
pivot = coll.get(n/2);
// split coll into 3 lists based on comparison with the pivot
for (T obj : coll) {
int order = comp.compare(obj, pivot);
if (order < 0) // obj < pivot
underPivot.add(obj);
else if (order > 0) // obj > pivot
overPivot.add(obj);
else // obj = pivot
equalPivot.add(obj);
} // for each obj in coll
// recurse on the appropriate list
if (n < underPivot.size())
result = nth(underPivot, n, comp);
else if (n < underPivot.size() + equalPivot.size()) // equal to pivot; just return it
result = pivot;
else // everything in underPivot and equalPivot is too small. Adjust n accordingly in the recursion.
result = nth(overPivot, n - underPivot.size() - equalPivot.size(), comp);
return result;
} // nth(coll, n)
public static void main (String[] args) {
Comparator<Integer> comp = Comparator.naturalOrder();
Random rnd = new Random();
for (int size = 1; size <= 10; size++) {
ArrayList<Integer> coll = new ArrayList<>(size);
for (int i = 0; i < size; i++)
coll.add(rnd.nextInt(100));
System.out.println("Median of " + coll.toString() + " is " + median(coll, comp));
} // for a range of possible input sizes
} // main(args)
} // Utility
If you want to use any external library here is Apache commons math library using you can calculate the Median.
For more methods and use take look at the API documentation
import org.apache.commons.math3.*;
.....
......
........
//calculate median
public double getMedian(double[] values){
Median median = new Median();
double medianValue = median.evaluate(values);
return medianValue;
}
.......
For more on evaluate method AbstractUnivariateStatistic#evaluate
Update
Calculate in program
Generally, median is calculated using the following two formulas given here
If n is odd then Median (M) = value of ((n + 1)/2)th item term.
If n is even then Median (M) = value of [((n)/2)th item term + ((n)/2 + 1)th item term ]/2
In your program you have numArray, first you need to sort array using Arrays#sort
Arrays.sort(numArray);
int middle = numArray.length/2;
int medianValue = 0; //declare variable
if (numArray.length%2 == 1)
medianValue = numArray[middle];
else
medianValue = (numArray[middle-1] + numArray[middle]) / 2;
Arrays.sort(numArray);
return (numArray[size/2] + numArray[(size-1)/2]) / 2;
Arrays.sort(numArray);
int middle = ((numArray.length) / 2);
if(numArray.length % 2 == 0){
int medianA = numArray[middle];
int medianB = numArray[middle-1];
median = (medianA + medianB) / 2;
} else{
median = numArray[middle + 1];
}
EDIT: I initially had medianB setting to middle+1 in the even length arrays, this was wrong due to arrays starting count at 0. I have updated it to use middle-1 which is correct and should work properly for an array with an even length.
You can find good explanation at https://www.youtube.com/watch?time_continue=23&v=VmogG01IjYc
The idea it to use 2 Heaps viz one max heap and mean heap.
class Heap {
private Queue<Integer> low = new PriorityQueue<>(Comparator.reverseOrder());
private Queue<Integer> high = new PriorityQueue<>();
public void add(int number) {
Queue<Integer> target = low.size() <= high.size() ? low : high;
target.add(number);
balance();
}
private void balance() {
while(!low.isEmpty() && !high.isEmpty() && low.peek() > high.peek()) {
Integer lowHead= low.poll();
Integer highHead = high.poll();
low.add(highHead);
high.add(lowHead);
}
}
public double median() {
if(low.isEmpty() && high.isEmpty()) {
throw new IllegalStateException("Heap is empty");
} else {
return low.size() == high.size() ? (low.peek() + high.peek()) / 2.0 : low.peek();
}
}
}
Try sorting the array first. Then after it's sorted, if the array has an even amount of elements the mean of the middle two is the median, if it has a odd number, the middle element is the median.
Use Arrays.sort and then take the middle element (in case the number n of elements in the array is odd) or take the average of the two middle elements (in case n is even).
public static long median(long[] l)
{
Arrays.sort(l);
int middle = l.length / 2;
if (l.length % 2 == 0)
{
long left = l[middle - 1];
long right = l[middle];
return (left + right) / 2;
}
else
{
return l[middle];
}
}
Here are some examples:
#Test
public void evenTest()
{
long[] l = {
5, 6, 1, 3, 2
};
Assert.assertEquals((3 + 4) / 2, median(l));
}
#Test
public oddTest()
{
long[] l = {
5, 1, 3, 2, 4
};
Assert.assertEquals(3, median(l));
}
And in case your input is a Collection, you might use Google Guava to do something like this:
public static long median(Collection<Long> numbers)
{
return median(Longs.toArray(numbers)); // requires import com.google.common.primitives.Longs;
}
I was looking at the same statistics problems. The approach you are thinking it is good and it will work. (Answer to the sorting has been given)
But in case you are interested in algorithm performance, I think there are a couple of algorithms that have better performance than just sorting the array, one (QuickSelect) is indicated by #bruce-feist's answer and is very well explained.
[Java implementation: https://discuss.leetcode.com/topic/14611/java-quick-select ]
But there is a variation of this algorithm named median of medians, you can find a good explanation on this link:
http://austinrochford.com/posts/2013-10-28-median-of-medians.html
Java implementation of this:
- https://stackoverflow.com/a/27719796/957979
I faced a similar problem yesterday.
I wrote a method with Java generics in order to calculate the median value of every collection of Numbers; you can apply my method to collections of Doubles, Integers, Floats and returns a double. Please consider that my method creates another collection in order to not alter the original one.
I provide also a test, have fun. ;-)
public static <T extends Number & Comparable<T>> double median(Collection<T> numbers){
if(numbers.isEmpty()){
throw new IllegalArgumentException("Cannot compute median on empty collection of numbers");
}
List<T> numbersList = new ArrayList<>(numbers);
Collections.sort(numbersList);
int middle = numbersList.size()/2;
if(numbersList.size() % 2 == 0){
return 0.5 * (numbersList.get(middle).doubleValue() + numbersList.get(middle-1).doubleValue());
} else {
return numbersList.get(middle).doubleValue();
}
}
JUnit test code snippet:
/**
* Test of median method, of class Utils.
*/
#Test
public void testMedian() {
System.out.println("median");
Double expResult = 3.0;
Double result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,13.0));
assertEquals(expResult, result);
expResult = 3.5;
result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,4.0,13.0));
assertEquals(expResult, result);
}
Usage example (consider the class name is Utils):
List<Integer> intValues = ... //omitted init
Set<Float> floatValues = ... //omitted init
.....
double intListMedian = Utils.median(intValues);
double floatSetMedian = Utils.median(floatValues);
Note: my method works on collections, you can convert arrays of numbers to list of numbers as pointed here
And nobody paying attention when list contains only one element (list.size == 1). All your answers will crash with index out of bound exception, because integer division returns zero (1 / 2 = 0). Correct answer (in Kotlin):
MEDIAN("MEDIAN") {
override fun calculate(values: List<BigDecimal>): BigDecimal? {
if (values.size == 1) {
return values.first()
}
if (values.size > 1) {
val valuesSorted = values.sorted()
val mid = valuesSorted.size / 2
return if (valuesSorted.size % 2 != 0) {
valuesSorted[mid]
} else {
AVERAGE.calculate(listOf(valuesSorted[mid - 1], valuesSorted[mid]))
}
}
return null
}
},
As #Bruce-Feist mentions, for a large number of elements, I'd avoid any solution involving sort if performance is something you are concerned about. A different approach than those suggested in the other answers is Hoare's algorithm to find the k-th smallest of element of n items. This algorithm runs in O(n).
public int findKthSmallest(int[] array, int k)
{
if (array.length < 10)
{
Arrays.sort(array);
return array[k];
}
int start = 0;
int end = array.length - 1;
int x, temp;
int i, j;
while (start < end)
{
x = array[k];
i = start;
j = end;
do
{
while (array[i] < x)
i++;
while (x < array[j])
j--;
if (i <= j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
} while (i <= j);
if (j < k)
start = i;
if (k < i)
end = j;
}
return array[k];
}
And to find the median:
public int median(int[] array)
{
int length = array.length;
if ((length & 1) == 0) // even
return (findKthSmallest(array, array.length / 2) + findKthSmallest(array, array.length / 2 + 1)) / 2;
else // odd
return findKthSmallest(array, array.length / 2);
}
public static int median(int[] arr) {
int median = 0;
java.util.Arrays.sort(arr);
for (int i=0;i<arr.length;i++) {
if (arr.length % 2 == 1) {
median = Math.round(arr[arr.length/2]);
} else {
median = (arr[(arr.length/2)] + arr[(arr.length/2)-1])/2;
}
}
return median;
}
Check out the Arrays.sort methods:
http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html
You should also really abstract finding the median into its own method, and just return the value to the calling method. This will make testing your code much easier.
public int[] data={31, 29, 47, 48, 23, 30, 21
, 40, 23, 39, 47, 47, 42, 44, 23, 26, 44, 32, 20, 40};
public double median()
{
Arrays.sort(this.data);
double result=0;
int size=this.data.length;
if(size%2==1)
{
result=data[((size-1)/2)+1];
System.out.println(" uneven size : "+result);
}
else
{
int middle_pair_first_index =(size-1)/2;
result=(data[middle_pair_first_index+1]+data[middle_pair_first_index])/2;
System.out.println(" Even size : "+result);
}
return result;
}
package arrays;
public class Arraymidleelement {
static public double middleArrayElement(int [] arr)
{
double mid;
if(arr.length%2==0)
{
mid=((double)arr[arr.length/2]+(double)arr[arr.length/2-1])/2;
return mid;
}
return arr[arr.length/2];
}
public static void main(String[] args) {
int arr[]= {1,2,3,4,5,6};
System.out.println( middleArrayElement(arr));
}
}