认识O(N log N)的排序

1、master公式的使用

T ( N ) = a ∗ T ( N / b ) + O ( N d ) T(N) = a * T(N / b) + O(N ^ d)\\ T(N)=aT(N/b)+O(Nd)

T(N):母问题的规模
T(N/b):子问题的规模
a:调用次数
O(N^d):除去子问题,剩下操作的时间复杂度

  1. logb a > d --> 复杂度为O(Nlogb a)

  2. logb a = d --> 复杂度为O(Nd * log N)

  3. logb a < d --> 复杂度为O(Nd)

2、归并排序(时间:O(N log N) 空间:O(N): 没有浪费比较行为)
#include<stdio.h>
int a[10] = {4,3,6,2,1,5,7,10,9,8};
void marge(int arr[], int l, int mid, int r){
	int b[r - l + 1];
	int i = 0;
	int p1 = l;
	int p2 = mid + 1;
	while(p1 <= mid && p2 <= r){
		b[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
	}
	while(p1 <= mid){
		b[i++] = arr[p1++]; 
	}
	while(p2 <= r){
		b[i++] = arr[p2++];
	}
	for(int j = 0; j < i; j++){
		arr[l + j] = b[j];
	}
}
void process(int arr[], int l, int r){
	if(l == r){
		return;
	}
	int mid = l + r >> 1;
	process(arr, l, mid);
	process(arr, mid + 1, r);
	marge(arr, l, mid, r); 
}

int main(){
	process(a, 0, 9);
	for(int i = 0; i < 10; i++){
		printf("%d    ", a[i]);
	} 
	return 0;
}
3、小和问题 与 逆序对问题。

小和问题因为要先放右侧的子数组,所以丧失了归并排序的稳定性。

#include<stdio.h>
int a[5] = {1,2,3,4,5};
int marge(int arr[], int l, int mid, int r){
	int b[r - l + 1];
	int i = 0;
	int p1 = l;
	int p2 = mid + 1;
	int res = 0;
	while(p1 <= mid && p2 <= r){
        //就加了这么一条语句
		res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
		b[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
	}
	while(p1 <= mid){
		b[i++] = arr[p1++]; 
	}
	while(p2 <= r){
		b[i++] = arr[p2++];
	}
	for(int j = 0; j < i; j++){
		arr[l + j] = b[j];
	}
	return res;
}
int process(int arr[], int l, int r){
	if(l == r){
		return 0;
	}
	int mid = l + r >> 1;
	return process(arr, l, mid) + process(arr, mid + 1, r) + marge(arr, l, mid, r); 
}

int main(){
	int x = process(a, 0, 4);
	printf("%d\n", x);
	for(int i = 0; i < 5; i++){
		printf("%d    ", a[i]);
	} 
	return 0;
}
4、荷兰国旗问题(时间复杂度O(N log N) 空间复杂度O(1))

给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,等于num的数放在数组的中间, 大于num的数放在数组的右边。

思路:

  1. arr[i] < numarr[i]和 小区下一个交换,小区范围右扩一位,i++
  2. arr[i] == numi++
  3. arr[i] > numarr[i] 和大区前一个交换,大区范围左扩一位,i原地不变

循环停止条件:当 i 包含在大区范围内

5、快速排序(最差O(log N2),平均O(N log N)
1、1.0版本

先把最后一个数x提出来,剩余的数把小于x放左边,大于x放右边,递归

2、2.0版本

先把最后一个数x提出来,剩余的数把小于x放左边,等于x的放中间,大于x放右边,递归

#include<stdio.h> 
int arr[5] = {4,2,1,3,5};
int lr[2];
void swap(int arr[], int l, int r){
	int temp;
	temp = arr[l];
	arr[l] = arr[r];
	arr[r] = temp;
}
void parttion(int arr[], int l, int r){
	//小于区的左边界 
	int p1 = l - 1;
	//大于区的右边界,最后一个数是划分值 
	int p2 = r;
	int p = l;
	while(p < p2){
		if(arr[p] < arr[r]){
			swap(arr, p++, ++p1);
		}else if(arr[p] > arr[r]){
			swap(arr, p, --p2);
		}else{
			p++;
		}
	}
	swap(arr, r, p2); 
	lr[0] = p1;
	lr[1] = p2 + 1;
}

void process(int arr[], int l, int r){
	if(l < r){
		parttion(arr, l, r);
		process(arr, l, lr[0]);
	    process(arr, lr[1],r);
	}
}

int main(){
	process(arr, 0, 4);
	for(int i = 0; i < 5; i++){
		printf("%d    ", arr[i]);
	} 
	return 0;
} 
3、3.0版本

随机选出一个数与最后一个数交换,用这个数来做,这样概率就相等了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值