由一次腾讯校招面试题,引发的排序算法整理(不全,仅供自己参考)。
算法题内容如下:
************************************************************************************************************
春节期间小明使用微信收到很多个红包,非常开心.在查看领红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额.写出具体算法思路和代码实现,要求算法尽可能高效。给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。
************************************************************************************************************
题目思路:
很明显是这一个排序算法,只要排序后,数组中间那个就是所要求的的值。既然要求是尽可能高效,首选就是"快排"--快速排序算法。
快排思路:
对于给定的数组,从中选一个元素作为比较对象,一般选择最左或最右的元素,选左边为升序排,选右边反之。
排序的目的就是为了让左侧的值比右侧的值小,那么就可以取一个基准值。这个基准值我们可以把它当做是一个序列的左侧,将这个基准值从右往左进行查找,这个时候右侧的起始值实际上是原数组的右侧值,我们设这个下标为right,找到一个比基准值大的值和基准值进行交换。每对比一次我们让right自增一。同时将right 的值代替基准值所在的下标。同理这个时候在从左侧向右侧开始查找,设这个下标为left,找到一个比基准值小的值和基准值进行交换,每对比一次我们让left自减一,同时将left的值代替基准值所在的下标,直至基准值左侧的值都比它小,基准值右侧的值都比它大。
原数组为array[]: [5 , 2, 3, 1, 6, 4, 7, 8, 0, 9] index:0; left:0; right:9
从右边开始找比5小的,交换后为[ 0, 2, 3, 1, 6, 4, 7, 8, 5, 9] index:8; left:0; right:8
从左边开始找比5大的,交换后为[ 0, 2, 3, 1, 5, 4, 7, 8, 6, 9] index:4; left:4; right:8
再从右开始找比5小的,交换后为[ 0, 2, 3, 1, 4, 5, 7, 8, 6, 9] index:5; left:4; right:5
这时5左边的已经比5小,5右边的都比5大,只需要使用递归,把[0, 2, 3, 1, 4]和[7, 8, 6, 9] 部分继续执行述排序步骤,最终得到的就是排序好的数组。
快速排序:
//快速排序
public static void quickSort(int[] array, int start, int end) {
int i = start, j = end;
int target = array[start];
while (i < j) {
while (i < j && target <= array[j]){
j--;
}
if (i < j) {
int temp = array[j];
array[j] = array[i];
array[i] = temp;
}
while (i < j && array[i] <= target){
i++;
}
if (i < j) {
int temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
if (i - 1 > start){
quickSort(array, start, i - 1);
}
if (j + 1 < end){
quickSort(array,j + 1, end);
}
}
说到快排就不得不说其他几个排序算法:
冒泡排序:
//冒泡排序
public static void bubbleSort(int a[]){
for(int i=0;i<a.length-1;i++){
//遍历n-1遍就够了
for(int j=0;j<a.length-i-1;j++){
//每次比较当前元素和下一个元素,每遍历一遍少比较一个元素,所以循环结束条件为n-i-1
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
选择排序:
分析:
从数组中找到最小的元素,和第一个位置的元素互换。
从第二个位置开始,找到最小的元素,和第二个位置的元素互换。
........
直到选出array.length-1个较小元素,剩下的最大的元素自动排在最后一位。
//选择排序
public static void selectionSort(int arr[]){
for(int i=0; i<arr.length-1; i++) {
int minPos = i;
for (int j = i; j < arr.length; j++) {
if (arr[j] < arr[minPos]) {
minPos = j;//找出当前最小元素的位置
}
}
if(arr[minPos]!=arr[i]) {
int temp = arr[minPos];
arr[minPos] = arr[i];
arr[i] = temp;
}
}
}
插入排序:
分析:
正常:从第一个元素开始,若当前元素i小于有序数组中的元素j,则从该元素开始将有序数组依次后移一位,并将当前元素i放置到该元素j位置。(插入)
简易:从有序数组最后一个元素开始,若当前元素i小于该元素j,则交换当前元素和该元素。
//插入排序
public static void insertionSort(int[] arr){
int pos,temp;
for(int i=1;i<arr.length;i++){
pos = i;
while(pos!=0&&arr[pos]<arr[pos-1]){
temp = arr[pos];
arr[pos] = arr[pos-1];
arr[pos-1] = temp;
pos--;
}
}
}