Related
Which is better to use for an array of millions of integers(ages)
public static int findMax(int[] x) {
int max = 0;
int curr = 0;
for (int a : x) {
curr = Math.max(curr, a);
max = Math.max(max, curr);
}
return max;
}
public static int findMax(int[] x){
List<Integer> list = new ArrayList<>();
for (int y : x){
list.add(y);
}
return Collections.max(list);
}
The first one will definitely be faster than the second one, as you really don't want to be making an arraylist for no reason just to find the maximum of an array!
Also, there is no reason to use two different variables for the current and the max, just the max will suffice, like so:
public static int findMax(int[] x) {
int max = Integer.MIN_VALUE;
for (int a : x) {
max = Math.max(max, a);
}
return max;
}
Note: I used the minimum integer because the largest value in your array may be negative. Also, you could just use an if-condition instead of Math.max(), but it'll work either way. This also saves you an extra operation. The runtime is O(n) in every case.
They both look like they are O(n). You could always use a logger and see what the time is. The following is a link that talks about logging time executed: How do I time a method's execution in Java?
I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}
I have a class Segment and an array of segments like this:
private static class Segment {
int number, type;
Segment(int number, int type) {
this.number = number;
this.type = type;
}
}
Segment[] points = new Segment[n];
points={(0,-1),(1,0),(5,1),(6,0),(6,-1),(10,1),(11,0)}
The element of the left is a list of points, and the list of the right is the type of point: -1 opens a segment, 1 closes a segment and 0 intersects the segment.
As you can see, this array is already sorted according to number, using this code (its an adapted selectionSort):
maxI finds the index of the biggest "number" element
private static int maxI(Segment[] segments, int size){
int max=0;
for (int i=0; i< size;i++){
if(segments[i].number > segments[max].number ){
max=i;
}
}
return max;
}
// swap method swaps elements of the array between index1 and index2
private static void swap(Segment[] segments, int index1, int index2){
int temp1;
int temp2;
temp1 = segments[index1].number;
temp2 = segments[index1].type;
segments[index1].number=segments[index2].number;
segments[index1].type=segments[index2].type;
segments[index2].number=temp1;
segments[index2].type=temp2;
}
selectSort is the sorting method (since Arrays.sort wont work with "segments")
private static void selectSort(Segment[] segments) {
int MaxPos;
for (int i=segments.length-1;i>0;i--){
MaxPos = maxI(segments, i+1);
swap (segments, MaxPos, i);
}
}
The original input was 2 ranges and 3 intersection points:
Range 1: 0 5
Range 2: 6 10
Intersection points: 1 6 11
So after sorting, the result as above is:
(0,-1),(1,0),(5,1),(6,0),(6,-1),(10,1),(11,0)
I've tried to modify the maxI method, so 6,-1 comes before 6,0 (-1 < 0) using a second if statement:
if (segments[i].number = segments[max].number && segments[i].type > segments[max].type)
But it messes the output.Since the input is random, the code must be prepared to sort testcases where many numbers are equal.
The closest question I've seen with this subject is one made in C++, I'm just learning Java so I'm struggling enough to try to understand C++. I feel the answer is close, but not sure what am I missing.Maybe I'm using the wrong data structure.
After this I just traverse the array, adding the sum of the types, so if a number passes 3 opening of ranges (x,-1), it's -3,in absolute= 3 so it's intersecting 3 ranges, which is the answer I'll need.
Just create a Comparator that compares number then type, then you can use Arrays.sort(). If you have Java 8, you can do it like this:
Arrays.sort(points, Comparator.comparingInt((Segment s) -> s.number).thenComparingInt((Segment s) -> s.type));
If you're using Java 7, you can do this:
Arrays.sort(points, new Comparator<Segment>() {
#Override
public int compare(Segment s1, Segment s2) {
int result = Integer.compare(s1.number, s2.number);
if (result == 0) {
result = Integer.compare(s1.type, s2.type);
}
return result;
}
});
Alternatively, you can have Segment implement the Comparable interface, and Arrays.sort(points) will work out of the box:
private static class Segment implements Comparable<Segment> {
int number, type;
Segment(int number, int type) {
this.number = number;
this.type = type;
}
#Override
public int compareTo(Segment s) {
int result = Integer.compare(this.number, s.number);
if (result == 0) {
result = Integer.compare(this.type, s.type);
}
return result;
}
}
I'm making a histogram program in which I have one array that generates a random number, another that makes them into an array, and a last one that attempts to use that array and tell how many characters are in each [] of the array. My problem is that I cannot find a way to count how many characters are in each array element and outprint it. I'm trying to use the .length function but it doesn't seem to be working. Is there another way that I could do this?
Here is my code. My problem is with my last method, before my main method.
package arrayhistogram;
/**
*
* #author Dominique
*/
public class ArrayHistogram {
public static int randomInt(int low, int high){
double x =Math.random ()* (high - low)+low;
int x1=(int)x;
return x1;
}
public static int[] randomIntArray(int n){
int[] a = new int[n];
for (int i=0; i<n; i++) {
a[i] = randomInt(-5, 15);
}
return a;
}
public static int[] arrayHist () {
int[] x=randomIntArray(30);
for (int i = 0; i < x.length; i++) {
System.out.println(x[i].length);
}
return x;
}
public static void main(String[] args) {
arrayHist();
}
}
Replace
System.out.println(x[i].length);
with
System.out.println(Integer.toString(x[i]).length());
There is no length property on an int. You can use this to get the number of digits in the int.
String.valueOf(x[i]).length()
This first transforms the int into a String and then returns the length of that String. E.g 123 => "123", whose length is 3.
I decided to implement a very simple program recursively, to see how well Java handles recursion*, and came up a bit short. This is what I ended up writing:
public class largestInIntArray {
public static void main(String[] args)
{
// These three lines just set up an array of ints:
int[] ints = new int[100];
java.util.Random r = new java.util.Random();
for(int i = 0; i < 100; i++) ints[i] = r.nextInt();
System.out.print("Normal:"+normal(ints,-1)+" Recursive:"+recursive(ints,-1));
}
private static int normal(int[] input, int largest) {
for(int i : input)
if(i > largest) largest = i;
return largest;
}
private static int recursive(int[] ints, int largest) {
if(ints.length == 1)
return ints[0] > largest ? ints[0] : largest;
int[] newints = new int[ints.length - 1];
System.arraycopy(ints, 1, newints, 0, ints.length - 1);
return recursive(newints, ints[0] > largest ? ints[0] : largest);
}
}
And that works fine, but as it's a bit ugly I wondered if there was a better way. If anyone has any thoughts/alternatives/syntactic sugar to share, that'd be much appreciated!
P.s. If you say "use Lisp" you win nothing (but respect). I want to know if this can be made to look nice in Java.
*and how well I handle recursion
Here's how I might make the recursive method look nicer:
private static int recursive(int[] ints, int largest, int start) {
if (start == ints.length) {
return largest;
}
return recursive(ints, Math.max(ints[start], largest), start + 1);
}
This avoids the expensive array copy, and works for an empty input array. You may implement an additional overloaded method with only two parameters for the same signature as the iterative function:
private static int recursive(int[] ints, int largest) {
return recursive(ints, largest, 0);
}
2 improvements:
no copy of the array (just using the offset)
no need to give the current max
private static int recursive(int[] ints, int offset) {
if (ints.length - 1 == offset) {
return ints[offset];
} else {
return Math.max(ints[offset], recursive(ints, offset + 1));
}
}
Start the recursion with recursive(ints, 0).
You could pass the current index as a parameter rather than copying almost the entire array each time or you could use a divide and conquer approach.
public static int max(int[] numbers) {
int size = numbers.length;
return max(numbers, size-1, numbers[size-1]);
}
public static int max(int[] numbers, int index, int largest) {
largest = Math.max(largest, numbers[index]);
return index > 0 ? max(numbers, index-1, largest) : largest;
}
... to see how well Java handles recursion
The simple answer is that Java doesn't handle recursion well. Specifically, Sun java compilers and Hotspot JVMs do not implement tail call recursion optimization, so recursion intensive algorithms can easily consume a lot of stack space.
However, I have seen articles that say that IBM's JVMs do support this optimization. And I saw an email from some non-Sun guy who said he was adding it as an experimental Hotspot extension as a thesis project.
Here's a slight variation showing how Linked Lists are often a little nicer for recursion, where "nicer" means "less parameters in method signature"
private static int recursive(LinkedList<Integer> list) {
if (list.size() == 1){
return list.removeFirst();
}
return Math.max(list.removeFirst(),recursive(list));
}
Your recursive code uses System.arrayCopy, but your iterative code doesn't do this, so your microbenchmark isn't going to be accurate. As others have mentioned, you can clean up that code by using Math.min and using an array index instead of the queue-like approach you had.
public class Maximum
{
/**
* Just adapted the iterative approach of finding maximum and formed a recursive function
*/
public static int max(int[] arr,int n,int m)
{
if(m < arr[n])
{
m = arr[n];
return max(arr,n - 1,m);
}
return m;
}
public static void main(String[] args)
{
int[] arr = {1,2,3,4,5,10,203,2,244,245,1000,55000,2223};
int max1 = max(arr,arr.length-1,arr[0]);
System.out.println("Max: "+ max1);
}
}
I actually have a pre made class that I setup for finding the largest integer of any set of values. You can put this class into your project and simply use it in any class like so:
System.out.println(figures.getLargest(8,6,12,9,120));
This would return the value "120" and place it in the output. Here is the methods source code if you are interested in using it:
public class figures {
public static int getLargest(int...f) {
int[] score = new int[f.length];
int largest=0;
for(int x=0;x<f.length;x++) {
for(int z=0;z<f.length;z++) {
if(f[x]>=f[z]) {
score[x]++;
}else if(f[x]<f[z]) {
}else {
continue;
}
if(z>=f.length) {
z=0;
break;
}
}
}
for(int fg=0;fg<f.length;fg++) {
if(score[fg]==f.length) {
largest = f[fg];
}
}
return largest;
}
}
The following is a sample code given by my Java instructor, Professor Penn Wu, in one of his lectures. Hope it helps.
import java.util.Random;
public class Recursion
{
static int s = 0;
public static Double max(Double[] d, int n, Double max)
{
if (n==0) { return max;}
else
{
if (d[n] > max)
{
max = d[n];
}
return max(d, n-1, max);
}
}
public static void main(String[] args)
{
Random rn = new Random();
Double[] d = new Double[15];
for (int i=0; i
{
d[i] = rn.nextDouble();
System.out.println(d[i]);
}
System.out.print("\nMax: " + max(d, d.length-1, d[0]));
}
}
Here is my alternative
public class recursion
{
public static int max( int[] n, int index )
{
if(index == n.length-1) // If it's simple, solve it immediately:
return n[index]; // when there's only one number, return it
if(max(n, index+1) > n [index]) // is one number bigger than n?
return max(n, index+1); // return the rest, which contains that bigger number
return n[index]; // if not, return n which must be the biggest number then
}
public static void main(String[] args)
{
int[] n = {100, 3, 5, 1, 2, 10, 2, 15, -1, 20, -1203}; // just some numbers for testing
System.out.println(max(n,0));
}
}