"排序算法"帖

由一次腾讯校招面试题,引发的排序算法整理(不全,仅供自己参考)。

算法题内容如下:

************************************************************************************************************

春节期间小明使用微信收到很多个红包,非常开心.在查看领红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额.写出具体算法思路和代码实现,要求算法尽可能高效。给定一个红包的金额数组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,  45,  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--;
		}
	}
}	 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值