LeetCode-Sort Colors-排序

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.


Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:
You are not suppose to use the library's sort function for this problem.



/*		最差时间分析 	平均时间复杂度 	稳定度 	空间复杂度
*/冒泡排序 	O(n2) 		O(n2) 		稳定 		O(1)
for(int i=0;i<nums.length;i++)
{
	for(int j=0;j<nums.length-i-1;j++)
	{
		if(nums[j]>nums[j+1])
		{
			nums[j]+=nums[j+1];
			nums[j+1]=nums[j]-nums[j+1];
			nums[j]=nums[j]-nums[j+1];
		}
	}
		        	
}

/*		最差时间分析 	平均时间复杂度 	稳定度 	空间复杂度
*/基本插入排序 	O(n2) 		O(n2) 		稳定 		O(1)
for(int i=1;i<nums.length;i++)
{
	int temp=nums[i];//暂时保存该值,否则移动数组时会将该处的值覆盖
	int j=i-1;//将数组标记i的小端作为有序区
	while(j>-1&&nums[j]>temp)//如果j的标号未越界,而且j所指示的元素仍旧大于被i标记的元素
	{
		nums[j+1]=nums[j];//则将j标记的元素向右移动一格,因为i标记的元素已被temp保存,所以不用担心丢失
		j--;//j减一,比较i更左侧元素与i所指示元素的大小关系
	}
	nums[j+1]=temp;//因为j--语句在元素移动语句之后,所以跳出循环时j所指示位置比上一轮移动位置要偏左一格,所以此处使用j+1来标记将temp移回的的位置
}

/*记得之前总结过插入排序,有兴趣的可以看看---插入排序。
		 * 如果在最复杂的情况下,所要排序的整个数列是逆序的,当第 i-1 趟需要将 第 i 个元素插入前面的 0~ i -1 个元素的序列当中的时候,它总是会从第 i -1 个元素开始,逐个比较每个元素的大小,直到找到相应的位置。
		 * 这个算法中丝毫没有考虑当要插入第 i 个元素时前面的 0~i-1 序列是有序的这个特点。今天要总结的这个算法就充分的利用了这一点。
		 * 
		 * 二分插入排序法
		 * 	最差时间分析 	平均时间复杂度 	稳定度 	空间复杂度
			O(n2) 		O(n2) 		稳定 		O(1)
		 */
		for(int i=1;i<nums.length;i++)
        {
			int temp=nums[i];//暂时保存该值,否则移动数组时会将该处的值覆盖
			int left=0,right=i-1;//标记有序区边界
			int j=i-1;
			while(left<=right)
			{
				if(nums[(right+left)/2]<temp)
				{
					left=(right+left)/2+1;
				}else{
					right=(right+left)/2-1;
				}
			}
			
			while(j>=left)
			{
				nums[j+1]=nums[j];
				j--;
			}
			nums[left]=temp;
        }

/*选择排序的思想非常直接,不是要排序么?那好,我就从所有序列中先找到最小的,然后放到第一个位置。
		 * 之后再看剩余元素中最小的,放到第二个位置……以此类推,就可以完成整个的排序工作了。
		 * 可以很清楚的发现,选择排序是固定位置,找元素。相比于插入排序的固定元素找位置,是两种思维方式。
		 * 从选择排序的思想或者是上面的代码中,我们都不难看出,寻找最小的元素需要一个循环的过程,而排序又是需要一个循环的过程。
		 * 因此显而易见,这个算法的时间复杂度也是O(n*n)的。这就意味值在n比较小的情况下,算法可以保证一定的速度,
		 * 当n足够大时,算法的效率会降低。并且随着n的增大,算法的时间增长很快。因此使用时需要特别注意。
		 */
		for(int i=0;i<nums.length;i++)
        {
        	for(int j=i+1;j<nums.length;j++)
        	{
        		if(nums[i]>nums[j])
        		{
        			nums[j]+=nums[i];
        			nums[i]=nums[j]-nums[i];
        			nums[j]=nums[j]-nums[i];
        		}
        	}
        }
		
		for(int i=0;i<nums.length;i++)
        {
			int min=nums[i];//假定每一轮中的首个元素是最小的
			int index=i;
			
        	for(int j=i+1;j<nums.length;j++)
        	{
        		if(min>nums[j])
        		{
        			index=j;
        			min=nums[j];
        		}
        	}
        	if(index!=i){
        		nums[index]=nums[i];
        		nums[i]=min;
        	}
        	
        }


/* 算法先将要排序的一组数按某个增量d分成若干组(增量d即组数),每组中记录的下标相差d.<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.3999996185303px;">对每组中全部元素进行排序</span>
		 * 缩小增量d,重复上述过程
		 * 当增量减到1时,整个要排序的数被分成一组,排序完成。
		 * 一般的初次增量d取序列的一半为增量,以后每次减半,直到增量为1
		 * 
		 * 由于会在增量d间交换元素,所以可能会打破原有序列顺序,故希尔排序为非稳定排序
		 */
		int step=nums.length/2;//初始化步长为数组长度的一半,取整数
		int temp=0;
		while(step>=1)//当增量大于等于1时循环
		{
			for(int i=0;i<step;i++){//调整每一组的起始下标
				for(int j=i;//j按照step即增量步进,对被j选中的元素进行插入排序
					j<nums.length;
						j+=step)
				{
					temp=nums[j];
					int k=0;
					for(k=j-step;k>-1&&nums[k]>temp;k-=step){	
						nums[k+step]=nums[k];
					}
					nums[k+step]=temp;
				}
			}
			step/=2;//增量变为原来的一半
		}


import java.util.Arrays;

public class Solution {
	/*
	 * 快速排序(Quicksort)是对冒泡排序的一种改进。 
	 * 快速排序由C. A. R. Hoare在1962年提出。
	 * 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,
	 * 其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此
	 * 方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,
	 * 以此达到整个数据变成有序序列。
	 * 
	 * 每一层排序,指示性index必须相遇
	 * 判断二者不等时,才可以交换(跳跃式交换,所以不稳定)
	 */
	public void sortColors(int[] nums) {
		sort(nums, 0, nums.length - 1);
		System.out.println(Arrays.toString(nums));
	}

	void sort(int[] num, int left, int right) {

		int l = left, h = right;
		int key = num[left];
		while (l < h) {
			while (l < h) {

				if (num[h] < key) {
					num[l] = num[h];
					num[h] = key;// 给nums[h]赋值的先不写
					break;
				}
				h--;
			}

			while (l < h) {

				if (num[l] > key) {
					num[h] = num[l];
					num[l] = key;// 给nums[h]赋值的先不写
					break;
				}
				l++;
			}

		}

		if (l > left) {
			sort(num, left, l - 1);
		}
		if (h < right) {
			sort(num, h + 1, right);
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值