荷兰国旗问题,快速排序,随机快速排序

荷兰国旗问题

  • 问题描述

      荷兰国旗问题
      给定一个数组arr,和一个数num,请把小于num的数放在数组的 左边,
      等于num的数放在数组的中间,
      大于num的数放在数组的 右边。	
      要求额外空间复杂度O(1),时间复杂度O(N)
    
  • 此处引出快速排序思想,解法,假设两个指针分别指向arr数组的第一个元素和最后一个元素,将第一个元素与num相比较,如果第一个元素小于num,则该元素与第一个指针所指元素交换(即第一个元素与第一个元素交换,不变),接着指针一向前移动,num与第二个元素比较如果等于不变,如果大于则与第二个指针所指元素交换,但此时的num所比较的在数组中的位置不发生改变,如果小于num则与第一个指针所指元素交换,依次类推,知道num比较的位置与第二个指针所指位置相同结束比较

/**
 * 荷兰国旗问题
 * 
 * 给定一个数组arr,和一个数num,请把小于num的数放在数组的 左边,
 * 等于num的数放在数组的中间,
 * 大于num的数放在数组的 右边。	
 * 要求额外空间复杂度O(1),时间复杂度O(N)
 *
 */
	public static int[] partition(int[] arr, int L, int R, int num) {
		//假设的第一个指针位置
		int less = L-1;
		//假设的第二个指针位置
		int more = R+1;
		//元素num所比较的位置
		int index = L;
		while(index<more) {
			
			if(arr[index]<num) {
				//less++;
				//元素num>数组元素时的情况
				swap(arr,++less,index++);
				
			}else if(arr[index]>num) {
				//more--;
				//当大于num时,由于右半边界的数未知,所以保持数组不变
				swap(arr,--more,index);
				
			}else {
				//相等的情况
				index++;
			}
		}
		//返回交换后的边界
		return new int[] {less+1,more-1};
	}
	//交换函数
	public static void swap(int[] arr,int L,int R) {
		int t = arr[L];
		arr[L] = arr[R];
		arr[R] = t;
	}

快速排序

  • 理解:此处用的快速排序的方法是用数组的最后一个元素作为划分,将小于该元素的划分到左边,大于该元素的划分到右边等于该元素的划分到中间,具体过程和上述的荷兰国旗问题的思路相同,用递归进行整体的排列.
  • 时间复杂度:最坏情况,所划分的元素为最大或者最小,只有最左边和最右边有元素,此时时间复杂度为O(N^2). 最好的情况:选定元素的大小是数组的中间元素左右元素个数相同,此时时间复杂度为O(nlogn)
//快速排序
public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		quickSort(arr, 0, arr.length - 1);
	}

	public static void quickSort(int[] arr, int l, int r) {
		if (l < r) {
			int[] p = partition(arr, l, r);
			//再次取出最后的元素,返回值得下标-1是取出与之前元素不同的下标
			quickSort(arr, l, p[0] - 1);
			//与上述同理
			quickSort(arr, p[1] + 1, r);
		}
	}

	public static int[] partition(int[] arr, int l, int r) {
		int less = l - 1;
		//此处拿出最后一个元素进行比较,暂时不对他进行交换
		int more = r;
		while (l < more) {
			if (arr[l] < arr[r]) {
				swap(arr, ++less, l++);
			} else if (arr[l] > arr[r]) {
				swap(arr, --more, l);
			} else {
				l++;
			}
		}
		//将未交换的最后一个元素交换
		swap(arr, more, r);
		//返回交换后数组中间与最后一个元素相同的那部分元素的区间下标
		return new int[] { less + 1, more };
	}
	//交换函数
	public static void swap(int[] arr, int L, int R) {
		int t = arr[L];
		arr[L] = arr[R];
		arr[R] = t;
	}

随机快速排序

  • 为了减少快速排序的时间复杂度,改进的快速排序的算法,就是采用随机取数,随机从数组中拿取元素,拿到每个元素的概率是相同的,此处算出的算法的时间复杂度的数学期望是O(nlogn)
  • 代码基本与上述相同,就是将上述的取最后一个元素进行比较的情况改变为取随机数,取出一个随机数,与数组中的最后一个元素交换
public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		quickSort(arr, 0, arr.length - 1);
	}

	public static void quickSort(int[] arr, int l, int r) {
		if (l < r) {
			swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
			int[] p = partition(arr, l, r);
			quickSort(arr, l, p[0] - 1);
			quickSort(arr, p[1] + 1, r);
		}
	}

	public static int[] partition(int[] arr, int l, int r) {
		int less = l - 1;
		int more = r;
		while (l < more) {
			if (arr[l] < arr[r]) {
				swap(arr, ++less, l++);
			} else if (arr[l] > arr[r]) {
				swap(arr, --more, l);
			} else {
				l++;
			}
		}
		swap(arr, more, r);
		return new int[] { less + 1, more };
	}



	//交换函数
	public static void swap(int[] arr, int L, int R) {
		int t = arr[L];
		arr[L] = arr[R];
		arr[R] = t;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值