简体   繁体   中英

Two smallest numbers in a set

I am trying to find the two smallest numbers in a set WITHOUT USING ARRAYS. Here is the code:

Scanner in = new Scanner(System.in);

int N = in.nextInt();
int min = in.nextInt();


for(int i = 1; i < N; i++){
    int a = in.nextInt();

    if(a < min){            
        min = a;
    }
}

System.out.println(min);

It find the smallest number but there is nothing about the second smallest number.

How do I do that?

Please, note that I am a complete beginner to Java so easy explanation and help will be much appreciated)

It´s very very easy:

Scanner in= new Scanner(System.in);

    int N = in.nextInt();
    int min,min2 = Integer.MAX_VALUE,Integer.MAX_VALUE;


    for(int i = 0; i < N; i++){

        int a = in.nextInt();

        if( a < min){

            min = a;
            min2 = min;
        }
        else if( a < min2){

            min2 = a;
        }

    }


    System.out.println(min);
    System.out.println(min2);

It is about one condition you have to add:

Scanner in = new Scanner(System.in);

int N = in.nextInt();
int min = Integer.MAX_VALUE;
int secondMin = Integer.MAX_VALUE;

for(int i = 0; i < N; i++){
    int a = in.nextInt();

    if(a < min){
        secondMin = min; // the current minimum must be the second smallest
        min = a; // allocates the new minimum
    }

    else if (a < secondMin) {
        secondMin = a; // if we did not get a new minimum, it may still be the second smallest number
    }
}

System.out.println(min);
System.out.println(secondMin);

General hint: You should call the close method of your Scanner , preferably in a try-with-ressources block:

try(Scanner in = new Scanner(System.in)) {
    // other code here
}

That way the stream gets closed, which you should do, if you open a stream.

Solution 1:

The easiest way, that uses your existing code, would be also tracking the second smallest number:

Scanner in = new Scanner(System.in);

int N = in.nextInt();
int min = in.nextInt();
int sMin = Integer.MAX_VALUE;

for(int i = 1; i < N; i++){
    int a = in.nextInt();

    if(a < min){
        sMin = min;
        min = a;
    } else if(a < sMin) {
        sMin = a;
    }
}

System.out.println(min);
System.out.println(sMin);

Explanation 1:

The two cases, that can occure with a new Value are:

  1. The new value is smaller than min and sMin . Then you have to set the value of min into smin and afterwards set min to the new min value.
  2. The new value is larger than min and smaller than sMin . Then you only have to set the value of sMin to the new value.
  3. Both min-values are smaller. Then nothing is to do.

Solution 2:

Another, more generic approach would be using a PriorityQueue :

int N = in.nextInt();
PriorityQueue<Integer> minQueue = new PriorityQueue<>();
for(int i = 0; i < N; i++) {
    int value = in.nextInt();
    minQueue.add(value);
}
int minValue = minQueue.poll();
int secondMinValue = minQueue.poll();

This way you can get the n smallest numbers given by using a loop in which you call the poll() method. ( n may be a number < N ).


Explanation 2:

The Priority Queue is a datastructure, that internally orders the given elements by the natural order. In the case of Integers this order is given by < , > and = . So when calling poll() you remove the smallest element, that the PriorityQueue has yet encountered.

Try this:

Scanner in = new Scanner(System.in);

int n = in.nextInt();
int min2 = in.nextInt();
int min1 = min2;

for(int i = 1; i < n; i++){
    int a = in.nextInt();

    if( a < min2){
        if(a < min1){
            min2 = min1;
            min1 = a;
        }
        else{
            min2 = a;
        }
    }
}

System.out.println(min1 + " " + min2);

This problem can be solved in multiple ways, and the first step in choosing the right solution is to decide what is the most important for you:

  1. Space efficiency , that is, use the minimum possible amount of storage. ThreeFx does this, (s)he only uses constant additional space for the variables N , a , min , and secondMin . "Constant space" means that the amount of data that you store does not depend on how many numbers you are going to read from the stream. In contrast, Tarlen uses linear space, storing all the numbers read from the stream. This means that the amount of space required is directly proportional to N instead of being constant.
  2. Time efficiency , that is, perform as few computations as possible. I believe that ThreeFx's solution is one of the most efficient from this point of view. Tarlen's solution will be a bit slower, because managing the priority queue might require more comparisons.
  3. Extensibility , that is, how easily you could adapt your code when the requirements change slightly. Say that your boss makes you solve the problem that you just posted, to find the two smallest numbers. The next day, he wants the first three, and so on, until the end of the week. You get tired of changing your code every day, so you write a general solution, that will work for any number of elements that he asks for. This is where Tarlen's solution is better.
  4. Readability , that is, how short and easy to understand your code is. I will introduce my own solution here, which is based on a simple idea: put all the numbers in a list, sort it, and take out the first two numbers. Note that this is quite wasteful when it comes to resources: the space is linear (I am storing N numbers), and the time efficiency is O(N log N) at best. Here is my code:
List<Integer> list = new ArrayList<Integer>(); 
for (int i = 0; i < N; i++) list.add(in.nextInt()); 
Collections.sort(list); 
System.out.println(list.get(0));
System.out.println(list.get(1));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM