我正在编写一个测验程序,要求我对一些数字进行排序并打印相应的字符串。
为此,我创建了一个类Song
,并获取了该类对象的数组。我必须在变量qi
的基础上进行排序。问题在于,根据判断,我的解决方案需要花费太多时间并且效率不高。我之前尝试使用ArrayList
个对象并切换到数组思维,可以在一定程度上优化它,但它没有任何帮助。
如何进一步优化?
我的代码:
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;
}
}
答案 0 :(得分:3)
就Big-O复杂性而言,您的解决方案是最佳的。如果你使用数组或ArrayList没关系,在两种情况下排序都需要O(nlogn)。
您可以在小范围内进行优化,例如避免在compare
方法中创建新的丢弃对象。但从总体上看,这将对绩效产生微不足道的影响。
因此,您确定您对该任务的一般方法是否正确?我的意思是,你真的需要对列表进行排序吗?例如,如果任务只是找到最小qi
,则可以不对整个列表进行排序。这可以推广到n
最小qi
这样:
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();
}
}
在这里,我们假设歌曲列表非常大,n
小于列表中的歌曲数量。正如您所看到的,您不必对整个列表进行排序,只需线性迭代一次列表就足够了,并且只对输出集进行排序。
Comparator
与您在自己的代码中使用的相同,但如果您“手动”进行比较,则可以不使用new Long
public int compare(Song s1, Song s2) {
if (s1.qi < s2.qi) return -1;
if (s1.qi > s2.qi) return 1;
return 0;
}
答案 1 :(得分:0)
您还可以使用TreeMap
,密钥为qi
,值为Song class
的对象。因此它将在创建时进行排序。如果排序是您的主要目的,那么请转到TreeSet
,如果需要经常获取数据,那么ArrayList
是不错的选择。
修改强>
具有预定ArrayList
的 max size
更快,因为它减少了增量重新分配的数量。因此,如果您知道最多歌曲数量,那么这将更快。