How to find the largest number in the array - java

I have an array of grades(g) which is an int[] and I'm trying to find the largest grade in that array. I have tried this:
public static String highestGradeName(int[] g, String[] n) {
String highStudent;
int highest = g[0];
for (int i=1; i < g.length; i++) {
if (highest < g[i]) {
highStudent = n[i+1];
return (highStudent);
}
}
return null;
}
I have another array which is a String array and contains the names of the students, I have the return null there because it said it needed a return statement however I didn't plan on it ever being null. What's causing it to return null instead of highstudent?
I've used the exact code to find the lowest grade and it works fine the only thing I did to this one was change the if statement from highest > g[i] to highest < g[i].

Returning from inside the loop is wrong, as you can always have an even larger number later on in the array. You should keep the index of the highest grade and just return the corresponding name at the end:
public static String highestGradeName(int[] g, String[] n) {
int highest = 0;
for (int i = 1; i < g.length; i++) {
if (g[highest] < g[i]) {
highest = i;
}
}
return n[highest];
}

According to your logic let's break things.
Raw Test Case:
Take {0,1,2} as an integer arrays.
Take {"arya", "jon", "tyrion"} as an string arrays.
highest = 0; // according to your code.
For int i = 1, i < 3; i++
0 < 1
highstudent = 2 // tyrion
// returns tyrion
The reason why you are getting null is your integer at 0 index should be greater or equal to the index at 1.
Now, when you are using a type String in your method. You should return a string and that's what your editor said to have something return. You should use return out of the loop because you need to find the highest student which is only possible after looping all the list.
You can try this:
public static String highestGradeName(int[] g, String[] n) {
int max = 0;
int index = 0;
for (int i = 0; i < g.length; i++) {
if (max < g[i]) {
max = g[i];
index = i;
}
}
return n[index];
}
PS: Imporve code according to mureinik answer, I have one more variable to help you understand easily.

Related

Trying to create a array with the intersection of two arrays but fails at creating array with the proper structure

So, I am trying to create 2 randomly generated arrays,(a, and b, each with 10 unique whole numbers from 0 to 20), and then creating 2 arrays with the info of the last two. One containing the numbers that appear in both a and b, and another with the numbers that are unique to a and to b. The arrays must be listed in a "a -> [1, 2, 3,...]" format. At the moment I only know how to generate the 2 arrays, and am currently at the Intersection part. The problem is, that I can create a array with the correct list of numbers, but it will have the same length of the other two, and the spaces where it shouldn't have anything, it will be filled with 0s when its supposed to create a smaller array with only the right numbers.
package tps.tp1.pack2Arrays;
public class P02ArraysExtractUniqsAndReps {
public static void main(String[] args) {
int nbr = 10;
int min = 0;
int max = 20;
generateArray(nbr, min, max);
System.out.println();
}
public static int[] generateArray(int nbr, int min, int max) {
int[] a = new int[nbr];
int[] b = new int[nbr];
int[] s = new int[nbr];
s[0] = 0;
for (int i = 0; i < a.length; i++) {
a[i] = (int) (Math.random() * (max - min));
b[i] = (int) (Math.random() * (max - min));
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
i--;
}
if (b[i] == b[j]) {
i--;
}
}
}
System.out.println("a - > " + Arrays.toString(a));
System.out.println("b - > " + Arrays.toString(b));
for (int k = 0; k < a.length; k++) {
for (int l = 0; l < b.length; l++) {
if (a[k] == b[l]) {
s[l] = b[l];
}else {
}
}
}
System.out.println("(a ∪ (b/(a ∩ b)) - > " + Arrays.toString(s));
return null;
}
public static boolean hasValue(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
}
Is there any way to create the array without the incorrect 0s? (I say incorrect because it is possible to have 0 in both a and b).
Any help/clarification is appreciated.
First, allocate an array large enough to hold the intersection. It needs to be no bigger that the smaller of the source arrays.
When you add a value to the intersection array, always add it starting at the beginning of the array. Use a counter to update the next position. This also allows the value 0 to be a valid value.
Then when finished. use Array.copyOf() to copy only the first part of the array to itself, thus removing the empty (unfilled 0 value) spaces. This works as follow assuming count is the index you have been using to add to the array: Assume count = 3
int[] inter = {1,2,3,0,0,0,0};
inter = Arrays.copyOf(inter, count);
System.out.println(Arrays.toString(inter);
prints
[1,2,3]
Here is an approach using a List
int[] b = {4,3,1,2,5,0,2};
int [] a = {3,5,2,3,7,8,2,0,9,10};
Add one of the arrays to the list.
List<Integer> list = new ArrayList<>();
for(int i : a) {
list.add(i);
}
Allocate the intersection array with count used as the next location. It doesn't matter which array's length you use.
int count = 0;
int [] intersection = new int[a.length];
Now simply iterate thru the other array.
if the list contains the value, add it to the intersection array.
then remove it from the list and increment count. NOTE - The removed value must be converted to an Integer object, otherwise, if a simple int value, it would be interpreted as an index and the value at that index would be removed and not the actual value itself (or an Exception might be thrown).
once finished the intersection array will have the values and probably unseen zeroes at the end.
for(int i = 0; i < b.length; i++) {
int val = b[i];
if (list.contains(val)) {
intersection[count++] = val;
list.remove(Integer.valueOf(val));
}
}
To shorten the array, use the copy method mentioned above.
intersection = Arrays.copyOf(intersection, count);
System.out.println(Arrays.toString(intersection));
prints
[3, 2, 5, 0, 2]
Note that it does not matter which array is which. If you reverse the arrays for a and b above, the same intersection will result, albeit in a different order.
The first thing I notice is that you are declaring your intersection array at the top of the method.
int[] s = new int[nbr];
You are declaring the same amount of space for the array regardless of the amount you actually use.
Method Arrays.toString(int []) will print any uninitialized slots in the array as "0"
There are several different approaches you can take here:
You can delay initializing the array until you have determined the size of the set you are dealing with.
You can transfer your content into another well sized array after figuring out your result set.
You could forego using Array.toString, and build the string up yourself.

Terminated due to timeout for my hacker rank solution

Hello all please check the problemHackerRank Problem Statement
This is my solution for the above problem(link)
static int migratoryBirds(List<Integer> arr) {
int ar[]=new int[arr.size()];
for(int i=0;i<arr.size();i++){
ar[i] = Collections.frequency(arr,arr.get(i));
// ar[i] = obj.occuranceOfElement(arr,arr.get(i));
}
int maxAt = 0;
for (int i = 0; i < ar.length; i++) {
maxAt = ar[i] > ar[maxAt] ? i : maxAt;
}
return arr.get(maxAt);
}
my code is unable to handle when the array size is bigger,example 17623 elements in array.
Terminated due to timeout
The problem is in the second for loop which iterates over the array and gives me the index of the largest number in the array.Is there any other way that I could increase the performance.
Your problem is in this part:
for(int i = 0; i < arr.size(); i++)
ar[i] = Collections.frequency(arr, arr.get(i));
This is O(N²): Collections.frequency() iterates over whole list to calculate frequency for only one element. Manually, you can iterate over the list to calculate frequencey for all elements.
Moreover, ther're only 5 birds, so you need only 5 length array.
static int migratoryBirds(int[] arr) {
int max = 1;
int[] freq = new int[6];
for (int val : arr)
freq[val]++;
for (int i = 2; i < freq.length; i++)
max = freq[i] > freq[max] ? i : max;
return max;
}
Your problem is the call to Colletions.frequency, which is an O(N) operation. When you call it from inside a loop it becomes O(N²) and that consumes all your time.
Also, are you sure which implmentation of List you receive? You call list.get(i) which might also be O(N) if the implementation is a LinkedList.
The target of this exercise is to calculate the frequency of each value in one pass over the input. You need a place where you store and increase the number of occurrences for each value and you need to store the largest value of the input.
You have also skipped over a crucial part of the specification. The input has limits which makes solving the problem easier than you now think.
Here's another one:
static int migratoryBirds(List<Integer> arr) {
int freq[]=new int[6];
for(int i=0;i<arr.size();i++){
++freq[arr.get(i)];
}
int maxAt = 1;
for (int i = 2; i < freq.length; i++) {
if (freq[i] > freq[maxAt]) {
maxAt = i;
}
}
return maxAt;
}
We can determine the type number of the most common bird in one loop. This has the time complexity O(n).
static int migratoryBirds(int[] arr) {
int highestFrequency = 0;
int highestFrequencyBirdType = 0;
int[] frequencies = new int[5]; // there are 5 bird types
for (int birdType : arr) {
int frequency = ++frequencies[birdType - 1];
if (frequency > highestFrequency) {
highestFrequency = frequency;
highestFrequencyBirdType = birdType;
} else if (frequency == highestFrequency && birdType < highestFrequencyBirdType) {
highestFrequencyBirdType = birdType;
}
}
return highestFrequencyBirdType;
}
For each element in the array arr we update the overall highestFrequency and are storing the corresponding value representing the highestFrequencyBirdType . If two different bird types have the highest frequency the lower type (with the smallest ID number) is set.

I am trying to loop through an ArrayList to find the lowest value of a sensor reading

My instructions are: Create a sensor object that refers to element zero. Write a for loop that starts at element 1, loops through all the elements of the arraylist and check to see if the value of the sensor reading is smaller than element zero. I am supposed to assume that element zero has the minimum value already. If the value is smaller, set that as the minimum value. Here is the code I have, but it is not finding the minimum value.
public int findMinReadingIndex() {
ArrayList<SensorReading> sensorReadings = new ArrayList<>();
sensorReadings.get(0);
int minIndex = 0;
for(int i=1; i< sensorReadings.size(); i++) {
if (this.sensorReadings.get(i).getValue() < i)
minIndex = i;
}
return minIndex;
}
It is better to focus on the problem: you have a list, and you want to find an index with minimum value. So you have to write method that accepts List<SensorReading> and retrieves int value. Note, that using get() is not optimal, especially if you do not know concrete implementation of the List. You have to use iterator instead.
public int findMinReadingIndex(List<SensorReading> sensorReadings) {
int minIndex = 0;
int minValue = 0;
int i = 0;
for(SensorReading sensorReading : sensorReadings) {
if(i == 0 || sensorReading.getValue() < minValue) {
minValue = sensorReading.getValue();
minIndex = i;
}
i++;
}
return minIndex;
}
Minor change is below:
public int findMinReadingIndex() {
ArrayList<SensorReading> sensorReadings = new ArrayList<>();
float minReading = sensorReadings.get(0).getValue();
int minIndex = 0;
for(int index = 1; index < sensorReadings.size(); index ++) {
float reading = this.sensorReadings.get(index).getValue();
if (reading < minReading)
minIndex = index;
}
return minIndex;
}
If you using Java 8 one liner code use stream with Comparator API.
SensorReading minVal = sensorReadingList.stream().min(Comparator.comparing(SensorReading::getValue))
.orElseThrow(NoSuchElementException::new);
System.out.println(minVal.getValue());
First of all calling stream() method on the list to get a stream of
values from the list.
After that call to min() method on the stream to get the minimum
value from the list.
We are passing a lambda function as a comparator, sort the list and
deciding the minimum value.
After that we call orElseThrow() to throw an exception if no value
is received from min()

nested for loops integers missing from array

Beginner here. I'm having problems running this series of for loops to find which integers are missing from an array.
public class FunWithArrays{
public static void main(String[] args){
String nString = args[0];
int n = Integer.parseInt(nString);
int inputArray [] = {1,2,4};
System.out.println(" The missing numbers are " );
findMissingNum(n, inputArray);
}
public static void findMissingNum(int n, int[] inputArray){
for (int i = 1; i <= inputArray.length; i++){
int count = 0;
for( int j = 0; j < n; j++){
if(inputArray[j] == i){
count ++;
}
if (count == 0){
System.out.println(i);
}
}
}
}
}
I get the answer I want, namely 3, however it doesn't print but rather shows up in a runtime error:
java.lang.ArrayIndexOutOfBoundsException: 3
at FunWithArrays.findMissingNum(FunWithArrays.java:17)
at FunWithArrays.main(FunWithArrays.java:9)
the method should take an input n from the user (when the program is run) as the largest value of the array and print all the ones missing
The logic is the outer for loop should traverse the array for numbers 1-n, and the inner loop should add to the count variable each time it finds a certain number. At the end of iteration it should print any numbers with a final "count" of 0. THIS IS LITERALLY DRIVING ME CRAZY!!! thanks in advance :)
First of all, you should traverse from 0 to (inputArray.length-1) index of inputArray. This will get rid of the ArrayIndexOutOfBoundsException, because java array indexing starts from 0 not 1.
And for inner loop, run from 0 to n, since n is the max number.
And Thirdly, it should be inputArray[i] == j, not inputArray[j] == i, same for printing the value. In you case I believe you have n>=4, so it was trying to access inputArray[3] via inputArray[j] call. That's why you are getting this out of bound error.
I think your code means like this: nest loop always run through inner loop first before run the outer loop.
public static void findMissingNum(int n, int[] inputArray){
for (int i = 1; i <= n; i++){
int count = 0;
for( int j = 0; j < inputArray.length; j++){
if(inputArray[j] == i){
count ++;
}
if (count == 0){
System.out.println(i);
}
}
}
}
I will just use a while loop instead:
int num =1;
while(num<=n){
for(int i = 0;i<inputArray.length;i++){
if(inputArray[i]!=num){
System.out.println(num);
}
}
num++;
}
The i incrementing to <= ipnutArray.length is not causing the error because i is never used as the index. What is causing the error is when n > length.
Also, you should not be checking n elements starting from the beginning because n is the max value, not the number of elements.

Returning the highest value java

I'm trying to search an ArrayList and find the highest student mark. The values are randomly inputted. I have written code that works if the values are in order. But when I try to enter values in a random order, the loop always returns the last value entered! (Which is starting to frustrate me a little as I thought it worked!) It's probably something simple but I have missed the point again.
One other note .getName retrieves the student name with the highest mark.
Here is the code:
public String top()
{
int highest = 0;
int k;
for (k = 0; k < people.size();k++)
{
if (people.get(k).getMark() > highest)
{
highest = k;
}
}
return people.get(highest).getName();
}
You're setting highest to the index of the student with the highest mark, not to the highest mark itself. You probably want to keep both:
public String top()
{
int highestIndex = 0;
int highestMark = people.get(0).getMark();
for (int k = 1; k < people.size(); k++)
{
int mark = people.get(k).getMark();
if (mark > highestMark)
{
highestMark = mark;
highestIndex = k;
}
}
return people.get(highestIndex).getName();
}
Note two other changes I've made:
There's no point in declaring k before the loop; in general, it's tidiest to give local variables the smallest scope you can
I've used initial values from the first person in the collection; this will now work with negative marks as well
Separately, you should think about what you want to happen if people is empty. (Currently the code will throw an exception.)
the problem is that highest is the index, so your if condition should be:
if (people.get(k).getMark() > people.get(highest).getMark())
You can also store both the highest value and the index in two variables:
int highestVal = -1;
int highestIdx = -1;
for (int k = 0; k < people.size(); k++)
{
if (people.get(k).getMark() > highestVal)
{
highestVal = people.get(k).getMark();
highestIdx = k;
}
}
return people.get(highestIdx).getName();
You are comparing indices and values.
Try:
if (people.get(k).getMark() > people.get(highest).getMark())
You're confusing what your variables represent. You're comparing the indivduals marks to 'highst', but then you're setting highest to equal the index of that person (k).
So you're comparing indexes with marks...
highest is the index, you are comparing the mark to the index of the mark
if (people.get(k).getMark() > highest)
Instead of comparing to highest in the loop you should compare to people.get(highest).getMark()
Use an extra variable to hold the person's index.
public String top()
{
int highest = 0;
int k;
int topPerson;
for (k = 0; k < people.size();k++)
{
if (people.get(k).getMark() > highest)
{
highest = people.get(k).getMark() ;
topPerson = k;
}
}
return people.get(topPerson).getName();
}
try this one :)
public String top()
{
int highest = 0;
int k;
for (k = 1; k < people.size();k++)
{
if (people.get(k).getMark() > people.get(highest).getMark())
{
highest = k;
}
}
return people.get(highest).getName();
}

Categories