2

I was writing a program for a quiz which requires me to sort some numbers and print the corresponding string.

For this, I created a class Song, and took an array of the objects of this class. I have to sort on the basis of variable qi. The problem is that according to the judge, my solution takes too much time and is not efficient enough. I earlier tried with an ArrayList of objects and switched to array thinking that could optimize it to an extent but it was of no help.

How can I optimize it further?

My Code:

   class Song{
    long fi;
    long qi;
    String si;

    public Song(long fi,String si, long qi){
        this.fi = fi;
        this.si = si;
        this.qi = qi;
    }
}

      public class Zipf {
    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
        long fi;
        long qi;
        String si;
        int noOfSongs = scan.nextInt();
        int selection = scan.nextInt();
        List<Song> list=new ArrayList<Song>(); // all songs
        TreeSet<Song> set = new TreeSet<Song>(new treeComparator());
        for(int i=0; i< noOfSongs;i++)
        {
            fi=(scan.nextLong());
            si=(scan.next());
            qi=(fi*(i+1));
            list.add(new Song(fi,si,qi));//adding all songs to list
        }
        for(int i=0; i< selection;i++)
        {
            set.add(list.get(i));//adding no of songs to be selected into set

        }

        Song min = set.first();
        for (int i = selection; i < list.size(); i++) {
            Song song = list.get(i);
            if (song.qi > min.qi) {
                set.remove(min);
                set.add(song);
                min = set.first();
            }
        }
     Iterator<Song> iterator = set.descendingIterator();

                //Displaying the Tree set data
                for(int i=0;i<selection;i++){
                    System.out.println(iterator.next().si);
                }   

    }


}
class treeComparator implements Comparator<Song>{

    @Override
    public int compare(Song o1, Song o2) {
          if (o1.qi <= o2.qi) return -1;
            if (o1.qi > o2.qi) return 1;
            return 0;
    }
}   
12
  • 3
    Did your judge complain especially about the sort? Here my only point would be to not create Long objects and use Long.compare(song1.qi, song2.qi) instead. Maybe there is something else in the code you did not post? Commented Dec 25, 2013 at 9:19
  • I tried using Long.compare, but my eclipse showed error. Rest all in my code is just scanning the input and printing based on this sorting. Commented Dec 25, 2013 at 9:30
  • How many songs are there to judge/sort? Commented Dec 25, 2013 at 9:54
  • Maximum limit is 50000. Commented Dec 25, 2013 at 10:02
  • What is the exact wording of the quiz question? Commented Dec 25, 2013 at 10:03

2 Answers 2

3

In terms of Big-O complexity, your solution is optimal. It doesn't matter if you're using an array or an ArrayList, sorting takes O(nlogn) in both cases.

You could optimize in the small, such as avoiding creating new throw-away objects in your compare method. But in the big picture this will have a marginal effect on performance.

Thus, are you sure that your general approach to the task is correct? I mean, do you really need to sort the list? For instance, if the task is just to find the minimum qi, you could do without sorting the whole list. This can be generalized to the n smallest qi's like this:

List<Song> list; // all songs
int n; // provided by user

TreeSet<Song> set = new TreeSet<Song>(new Comparator() ...);
for (int i = 0; i < n; i++) {
    set.add(list.get(i));
}

Song max = set.last();
for (int i = n; i < list.size(); i++) {
    Song song = list.get(i);
    if (song.qi < max.qi) {
        set.remove(max);
        set.add(song);
        max = set.last();
    }
}

Here, we assume that the list of songs is very big and that n is smaller than the number of songs in the list. As you can see, you don't have to sort the whole list, it's sufficient to iterate over the list linearly once, and only keep the output set sorted.

The Comparator is the same that you used in your own code, but you can do without the new Long if you do the comparison "manually"

public int compare(Song s1, Song s2) {
    if (s1.qi < s2.qi) return -1;
    if (s1.qi > s2.qi) return 1;
    return 0;
} 
Sign up to request clarification or add additional context in comments.

10 Comments

Thank you for your answer. I found no other working way of comparing two long. Using long.compare gave error in eclipse. I do need to sort the elements! I have to print n number of elements in decreasing order. N is taked from user input.
Comparison by subtracting brings overflow risk.
Your edited code is a great help. I will follow this and try again. Thanks a lot.
@assylias Very good point, I got rid of the subtraction. Thanks.
@assylias Cool - I actually looked for that method in the API docs, but it wasn't there... but now I see it's because it was added in 1.7 and I looked at 1.6 (I don't like the look and feel of more recent API docs and I figured that the method, if anything, would have been there since early versions.)
|
0

You can also use a TreeMap with key as qi and value as the object of Song class. So that it will be sorted at time of creation. If sorting is your main purpose then go for TreeSet and if it requires to fetch data often then ArrayList is the good choice.

EDIT

ArrayList with predetermined max size is more faster as it reduces the amount of incremental reallocation. So if you know max number of songs then this will be more faster.

4 Comments

I need to sort on basis of qi and print si for the n (user input) sorted objects. Will using this be more efficient?
can please add here which operation is going to happen for more number of time sorting or printing.
The data structure storing the objects only needs to be sorted once and then on the basis of that, first n sorted object's si is to be printed. I hope I didn't misunderstand your question.
Yes, thats what I wanted to know. So the best choice would be to use ArrayList.

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.