4、力扣刷题心得(三)排序总结

这一节介绍一下排序的一些高级算法。

(1) 归并排序(时间复杂度 O(N*logN))

归并排序算法的核心就是 将两个有序数组归并成一个。

如何得到两个有序数组呢?就用到了递归的概念。将整个数组分为两个数组,对两个数组分别进行排序,就得到了两个有序数组,怎么排序呢?再将其分成两个数组。。。。。。

缺点:他需要在存储器中有另一个大小等于被排序的数据项数目的数组,如果初始数组几乎占满了整个存储空间,则归并排序不能工作。

// 递归函数中尽量少定义数组和变量,这样会增加效率,这个程序没有考虑到,读者可自行修改。
class Solution {
    public int[] InsertionSort(int[] nums, int startNode, int endNode) {
    	if (endNode - startNode == 0) {
    		return new int[]{nums[startNode]};
    	}
    	int mid = (startNode + endNode) / 2;
    	int[] left = InsertionSort(nums, startNode, mid);
    	int[] right = InsertionSort(nums, mid + 1, endNode);
    	return SortGui(left, right);
    }
    // 两个有序数组合并成一个有序数组
    public int[] SortGui(int[] A, int[] B) {
    	int[] temp = new int[A.length + B.length];
    	int pointA = 0;
    	int pointB = 0;
    	int pointC = 0;
    	while (pointA < A.length && pointB < B.length) {
    		if (A[pointA] < B[pointB])
    			temp[pointC++] = A[pointA++];
    		else if (A[pointA] >= B[pointB])
    			temp[pointC++] = B[pointB++];
    	}

		while (pointA < A.length)
			temp[pointC++] = A[pointA++];
		while (pointB < B.length)
			temp[pointC++] = B[pointB++];
    		
    	return temp;
	}
    public static void main (String[] args) {
    	int[] nums = {2,3,1,34,2,5,7,4};
    	Solution aSolution = new Solution();
    	int[] temp = aSolution.InsertionSort(nums, 0, nums.length - 1);
    	System.out.println(Arrays.toString(temp));
    }
}

(2) 希尔排序

希尔排序是插入排序的一种又称“缩小增量排序”,是插入排序算法的一种更高效的改进版本。

什么叫缩小增量排序呢?比如给定一个数组,要对它进行4-增量排序,即对1,5,9,13。。。。;2,6,10,14。。。;3,7,11,15。。。等等对这几组分别进行排序;然后再对它进行1-增量排序,方法一样,这就是缩小增量排序。

进行n-增量排序,那其中的n是如何决定的呢?一般使用 h = h * 3 + 1。比如数组大小为100,则n的取值为40,13,4,1。就是将h=1代入迭代,然后找到小于100的迭代值。

时间复杂度:希尔排序不像快速排序和其他时间复杂度为O(N*logN)的排序算法那么快,因此对非常大的文件排序,他不是最优的选择。但是,希尔排序比选择排序和插入排序这种时间复杂度为O(N^2)的排序算法要快得多,并且他非常容易实现。

import java.util.Arrays;

class Solution {
	public int[] ShellSort(int[] nums) {
		int n = 1;
		int temp;
		int in;
		while (nums.length > 3 * n + 1)
			n = 3 * n + 1;
		
		while (n > 0) {
			for (int i = 0; i < n; i++) {
				for (int j = n + i; j < nums.length; j = j + n) {
					in = j;
					temp = nums[in];
					while (in > n - 1 && nums[in - n] >= temp) {
						nums[in] = nums[in - n];
						in = in - n;
					}
					nums[in] = temp;
				}
			}
			n = (n - 1) / 3;
		}
		
		return nums;
	}

    public static void main (String[] args) {
    	int[] nums = {2,3,1,34,1,5,7,4};
		Solution aSolution = new Solution();
		int[] temp = aSolution.ShellSort(nums);
		System.out.println(Arrays.toString(nums));
    }
}

(3) 快速排序(最快的排序算法,时间复杂度O(N*logN) )

快速排序算法本质上通过把一个数组划分为两个子数组,然后递归地调用自身为每一个子数组进行快速排序来实现的。可能到这有小朋友就要问了,这不就是归并排序吗?相似但也不完全相似,归并是划分成两个有序数组,这个是通过一个枢纽(可以理解为阈值)来分开成两个数组。在以上基础上算法还需要对一些小数组(三个元素及以下)进行单独排序

划分方法:取数组的首尾和中间,寻找这三个数的中位数,作为枢纽(阈值(当然还可以有其他方法做枢纽)。

import java.util.Arrays;
class Solution {
	static int[] nums;
	public void FastSort(int startNode, int endNode) {
		int threshold;
		int mid = (startNode + endNode) / 2;
		int thIndex;
		median(startNode, endNode);
		if (endNode - startNode <= 2) {
			return;
		}
		// 注意mid是在求阈值时的,两个数组的分界线可不是他,应该是thIndex
		threshold = nums[mid];
		thIndex=divide(startNode, endNode, threshold);
		FastSort(startNode, thIndex - 1);
		FastSort(thIndex + 1, endNode);
	}
	
	public int divide(int start, int end, int th) {
		end--;
		start++;
		while (start < end) {
			while (nums[start] < th) {
				start++;
			}
			while (end > 0 && nums[end] > th) {
				end--;
			}
			swap(start, end);
			start++;
			end--;
		}
		// 注意要返回分界线的坐标哦
		return end;
	}
	
	public void median(int start, int end) {
		int mid = (start + end) / 2;
		if (nums[start] > nums[mid]) {
			swap(mid, start);
		}
		if (nums[mid] > nums[end]) {
			swap(mid, end);
		}
		if (nums[start] > nums[mid]) {
			swap(mid, start);
		}
	}
	public void swap(int a, int b) {
		int temp;
		temp = nums[a];
		nums[a] = nums[b];
		nums[b] = temp;
	}
	public void set(int[] n) {
		this.nums = n;
	}
    public static void main (String[] args) {
    	int[] nums = {2,3,4,1,23,4,5,1,23};
		Solution aSolution = new Solution();
		aSolution.set(nums);
		aSolution.FastSort(0,nums.length - 1);
		System.out.println(Arrays.toString(aSolution.nums));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值