3

I'm just practicing some MIT java assignments. But, I'm not sure how to find the second largest number. http://ocw.csail.mit.edu/f/13

  public class Marathon {
    public static void main(String[] arguments) {
        String[] names = { "Elena", "Thomas", "Hamilton", "Suzie", "Phil",
                "Matt", "Alex", "Emma", "John", "James", "Jane", "Emily",
                "Daniel", "Neda", "Aaron", "Kate" };

        int[] times = { 341, 273, 278, 329, 445, 402, 388, 275, 243, 334, 412,
                393, 299, 343, 317, 265 };

        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i] + ": " + times[i]);
        }

        System.out.println();
        System.out.println("Largest Timing " + Largest(times));
        System.out.println();

    }

    public static int Largest(int[] times) {
        int maxValue = times[0];

        for (int i = 1; i < times.length; i++) {
            if (times[i] > maxValue) {
                maxValue = times[i];
            }
        }
        return maxValue;
    }

}
6
  • 1
    Sort the array largest to smallest and subscript the 2nd element? Commented Nov 13, 2012 at 1:17
  • 4
    Or just have two running maxValues, one greater than the other. Commented Nov 13, 2012 at 1:18
  • Will give them a try. Thank You Commented Nov 13, 2012 at 1:21
  • 1
    @alex, Sorting an array is overkill for finding min/max. The linear solution is pretty trivial. Commented Nov 13, 2012 at 1:21
  • Yep, sorting is overkill. See my answer. Commented Nov 13, 2012 at 1:23

11 Answers 11

7

Instead of resorting to sorting the array, you can simply do the following:

  • Keep a largestValue and a secondLargestValue
  • Loop through the entire array once, for each element:
    • Check to see if the current element is greater than largestValue:
      • If so, assign largestValue to secondLargestValue, then assign the current element to largestValue (think of it as shifting everything down by 1)
      • If not, check to see if the current element is greater than secondLargestValue
        • If so, assign the current element to secondLargestValue
        • If not, do nothing.

O(n) run time

O(1) space requirement

Sign up to request clarification or add additional context in comments.

4 Comments

wow, how do you guys come up with such logic... I feel so stupid lol. I need to keep practicing.
Minor bug, see comment dasblinkin's post.
@HotLicks I'm not seeing the bug :<
There is a minor glitch here, if the largest number is duplicated, both largest and second largest will be same value. To fix this modify the check like "currentElement > secondLargestValue && currentElement != largestValue"
3

Sorting the array simply to find an order statistics is too wasteful. You can find the second largest element by following an algorithm that resembles the one that you already have, with an additional variable representing the second largest number.

Currently, the next element could be larger than the max or equal to/smaller than the max, hence a single if is sufficient:

if (times[i] > maxValue) {
    maxValue = times[i];
}

With two variables to consider, the next element could be

  • Greater than the max - the max becomes second largest, and the next element becomes the max
  • Smaller than the max but greater than the second largest - the next element becomes second largest.

A special care must be taken about the initial state. Look at the first two items, and assign the larger one to the max and the smaller to the second largest; start looping at the element number three, if there is one.

Here is how you can code it:

if (times[i] > maxValue) {
    secondLargest = maxValue;
    maxValue = times[i];
} else if (times[i] > secondLargest) {
    secondLargest = times[i];
}

6 Comments

Actually, this algorithm (as "coded") breaks down if you have multiple identical "largest" values. The "secondLargest" variable will end up the same as "largest", rather than reflecting the true second-largest. To do it right the second test needs to check for SMALLER than largest in addition to being LARGER than second-largest.
@HotLicks, That's not necessarily a bug. This problem deals with rankings (see the original problem linked), not with finding the next smallest unique value. In fact, even a mathematically correct "second max" algorithm would probably return the same result if we're dealing with a list, and not a set.
@Kiyura -- I would argue that if an algorithm reports a "second largest" value that is the same as the "largest" value, it's broken. "Second largest" means that the value is smaller than "largest".
@HotLicks In the context of this problem where all numbers are distinct there is no need to deal with ties. If the logic to deal with ties is desired, an extra if would be necessary.
In the context of this problem there's no need to write much code, beyond "int largest = 445; int secondLargest = 412;`.
|
2

Generally speaking:

Have two values -- "largest" and "notQuite".

Initialize both to -9999 or whatever.

Scan through your list. If the number is larger than "largest", set "largest" to that number. But before you do that, copy the old "largest" value to "notQuite".

If, on the other hand, the number is smaller than "largest" but is larger than "notQuite", set "notQuite" to that number.

When you're done examining all the numbers, "notQuite" contains the second-largest.

And note that, as you fill in the above numbers, you can also keep a "largestIndex" and "notQuiteIndex" and fill those in with the corresponding array index values, so you can identify the "winning" value. Unfortunately, though, if there are multiple identical "largest" or "secondLargest" values the simple index scheme doesn't work and you need to keep a list of some sort.

6 Comments

It's better to have a sentinel check for unset running values, or at least set them to Integer.MIN_VALUE.
@Kiyura -- Yep. For many cases simply initializing to -1 will suffice. Depends on the nature of your data. The odd case would be a list that consisted entirely of MIN_VALUE entries, in which case the sentinel would be needed, as there would be no "second largest".
Why would that case need special treatment? If the list consists entirely of MIN_VALUE, and that's what you initialize your max and secondMax to, they will both be correct at the end.
Depends on your definition of "second largest". Can they be the same??
In this problem, they correspond to rankings (specifically, times people get in a competition), so yes. In fact, they should be if multiple indices have the max value. i.e., "Depends on the nature of your data" ;)
|
2
private static int secLargest(int[] numbers) {
        int maxVal = 0;
        int nextMaxVal = 0;
        for (int i = 0; i < numbers.length; i++) {
            if (numbers[i] > maxVal) {
                nextMaxVal = maxVal;
                maxVal = numbers[i];

            }
            if (numbers[i] < maxVal) {
                nextMaxVal = maxVal;
                maxVal = numbers[i];

            }
        }
        return nextMaxVal;

    }

Comments

1
    private void secondLargest(int arr[]){

    int maxOne=arr[0];
    int maxTwo=arr[1];

    for(int i=0;i<arr.length;i++){

        if(arr[i]>maxOne){

            maxTwo=maxOne;
            maxOne=arr[i];
        }else if (arr[i]>maxTwo) {

            maxTwo=arr[i];
        }

    }

    System.out.println(maxOne);
    System.out.println(maxTwo);
}

Comments

0
int largest=time[0];
int secondLargest=largest;
for(int i=0;i<time.length;i++){
    if(time[i]>largest){
        secondLargest=largest;
        largest=time[i];
    }
    else if(secondLargest<time[i] && time[i]<largest || secondLargest>=largest)
        secondLargest=time[i];
}
return secondLargest;

Comments

0
public void findMax(int a[]) {
    int large = Integer.MIN_VALUE;
    int secondLarge = Integer.MIN_VALUE;
    for (int i = 0; i < a.length; i++) {
        if (large < a[i]) {
            secondLarge = large;
            large = a[i];
        } else if (a[i] > secondLarge) {
            if (a[i] != large) {
                secondLarge = a[i];
            }
        }
    }
    System.out.println("Large number " + large + " Second Large  number " + secondLarge);
}

The above code has been tested with integer arrays having duplicate entries, negative values. Largest number and second largest number are retrieved in one pass. This code only fails if array only contains multiple copy of same number like {8,8,8,8} or having only one number.

Comments

0

It will also extract second largest number if largest number occours two times as well as in a single for loop.

import java.util.*;
public class SecondLargestInArray
{
    public static void main(String[] args)
    {
        int arr[] = {99,14,46,47,86,92,52,48,36,66,85,92};
        int largest = arr[0];
        int secondLargest = arr[0];
        System.out.println("The given array is:" );
        for (int i = 0; i < arr.length; i++)
        {
            System.out.print(arr[i]+"\t");
        }

        for (int i = 0; i < arr.length; i++)
        {
            if (arr[i] > largest)
            {
                secondLargest = largest;
                largest = arr[i];
            }
            else if((arr[i]<largest && arr[i]>secondLargest) || largest==secondLargest)
            {
                secondLargest=arr[i];
            }
        }
        System.out.println("\nLargest number is:" + largest);
        System.out.println("\nSecond largest number is:" + secondLargest);
    }
}

Comments

0

Find the second largest element in the given array:

public static void findSecondMax(){
        int[] arr = {3, 2, 20, 4, 1, 9, 6, 3, 8};

        int max = 0;
        int secondMax = 0;

        for(int i =0; i< arr.length; i++) {

            if(max < arr[i]) max = arr[i];

            if((max > arr[i]) && (secondMax < arr[i])) secondMax = arr[i];

        }

        System.out.println(secondMax);
    }

Comments

0
public static void main (String args[]) {
    int [] arr = {1,4,3,10,4,8,20,5,33};
    int largest = 0;
    int secondLargest = 0;
    for (int x : arr) {
        if (x > largest) {
            secondLargest = largest;
            largest = x;
        }
        else if (x > secondLargest) {
            secondLargest = x;
        }
    }
    System.out.println("secondLargest:"+secondLargest);
}

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

Updated : Changed to Java.

class Main {
  public static void main(String[] args) {
    int a = Integer.MIN_VALUE;
    int b = Integer.MIN_VALUE;
    int[] arr = {44,6,43,8,9,-10,4,15,3,-30,23};

    for(int i=0; i < arr.length; i++){ 
        if( arr[i] > a || arr[i] > b ){
          if( a < b ) {
            a = arr[i];
          } else {
            b = arr[i];
          }
        }
    }  
    int secondLargest = a < b ? a : b;
    System.out.println(secondLargest);
  }
}

3 Comments

This answer not provide any help to OP, he is asking about JAVA not PHP.
As you have mentioned, your answer is in PHP. Please take the time to convert it to Java as requested by OP.
@Conscript Now it has been updated please upvote it as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.