最近开发中看见这样的一个需求,给车系建议指导价,也就是取最小值和最大值。竟然有人写了一个冒泡排序.....
我们都知道Java类库中提供的排序都是经过优化的排序算法,顺序表也就是用的是快排,而且这个快排是三相求和取平均值算法,让拿到的值也就是轴,尽可能均匀的划分,也就是轴的左边和右边尽可能的数量平均,达到快排的最好效果。而对于链表官方库也是采用的归并排序。于链表呢,比如快排,两个指针分别网后往前走,而没有前驱指针的单向链表,无法完成这样的操作,当然了可以采用快慢指针的方式,在提交leetcode的时候,发现快排是会超时的。分而治之,分别拍好前后两个部分,然后合并两个有序链表,在合适不过,并且由于链表自带属性,合并链表还无需0(n)额外的空间,因此归并排序成为链表排序的首选。
但是这里我们大学学过数据结构的都知道快排、归并排序最好的性能也就是O(nlgn),而这里我们不需要排序,只是需要找出最大值、最小值,用两个变量遍历一下也可以找到这个Max,Min,这时效率是O(n),但是这也不是好的解决办法。
其实我们很容易想到堆这种数据结构。我们可以构造最大堆和最小堆也就是0(lgn)的复杂度。。。
private static int left(int i)
{
return i<<1+1;
}
private static int right(int i)
{
return i<<1+2;
}
private static<T extends Comparable<? super T>>void swap(T[] arr,int i,int j)
{
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/*
* 构造最大堆
*/
private static<T extends Comparable<? super T>> void maxHeap(T[] arr,int i)
{
int l = left(i);
int r = right(i);
int largest;
if( l < heapSize && arr[i].compareTo(arr[l]) < 0)
largest = l;
else
largest = i;
if(r < heapSize && arr[largest].compareTo(arr[r]) < 0)
largest = r;
if(largest != i)
{
swap(arr,i,largest);
maxHeap(arr,largest);
}
}
/*
* 维持最大堆
* arr 要进行建堆的数组
*/
private static<T extends Comparable<? super T>> void buildMaxHeap(T[] arr)
{
heapSize = arr.length;
for(int i = arr.length/2; i > -1; i--)
{
maxHeap(arr,i);
}
}
虽然都可以实现业务需求,但是不同种的使用真的差别是非常非常大的,尤其数据量大的时候。。。 作为一个程序员还是要好好学习数据结构、算法,理解其优缺点。