(day 3)持续学习:排序算法

177 阅读2分钟

1、认识时间复杂度

指在一个算法中,执行完所需要多少次常数级操作

用O来表示,如:O(n)、O(n^2)、O(n^3)等.

由于时间复杂度不仅仅和算法本身有关,还与给定的数据有关,所以我们这边一般指的是最差情况下的时间复杂度。

当然还包含一些使用数学期望作为时间复杂度的算法,如:随机快排

1.1 常数级别操作

常数级操作是指语言中,可执行的最小指令单元。

包含: +-*/~ ^ & | >> >>> << <<<

^ (亦或)

可以按照不进行进位的加法来计算。如:1^1,二进制中 1+1=10,那么不进位就是0 1^0=1

0^0=0

1^1=0

0^n=n

n^n=0

满足交换律:a^b^c^d=d^c^b^a

满足结合律:(a^b)^(c^d)=a^b^c^d

一个整数序列中,除了x有技术个,其他数都是偶数个存在,求出x是什么数。利用上述特性,将数组内所有数都进行亦或计算,最后的结果就是x。

& (且)

判断偶数:n&1 ==0

整数n,二进制下最右边1的位置: n&(~n+1)

整数数组中,值存在a、b两个整数是奇数个,其他数都是偶数个,找出a、b的值。

将所有数进行亦或:a1^a2^a3^a4……^an = a^b = n

n&(~n+1) = x 找出最右边1的位置下标i

int p=0
for n in arr{
    if ai & n ==0{
         p=p^ai
    }
}
a=p
b=n^p
  

递归复杂度计算

子函数规模固定的递归,时间复杂度公式:T(n)=a*T(n/b)+O(n^d) 后续再推导过程

log(b,a)>d O(n^log(b,a))

log(b,a)<d O(n^d)

log(b,a)==d O(n^d * log(b,a))

2、排序算法

选择排序

O(n^2)

冒泡排序

O(n^2)

插入排序

O(n^2)

归并排序

O(n*logn)

随机快排

partion(分区)

	/**
	 * 分区 将数组中 给定的区域L-R 按照给定的num进行划分
	 * 左区为  <num
	 * 右区为  >num
	 * 中间为  =num
	 */
	public static int[] partition(int[] arr, int L, int R, int num){

		int lessIndex = L -1;
		int greatIndex = R+1;

		for (int i =L;i>lessIndex && i<greatIndex; ){
			int curNum = arr[i];

			if(curNum == num){
				i++;
				continue;
			}else if(curNum < num){
				swap(arr, ++lessIndex, i);
				i++;
			}else {
				swap(arr, --greatIndex, i);
			}
		}

		return new int[]{lessIndex, greatIndex};
	}

快排

O(n*logn)

	public static void quickSort(int arr[]){

		quickSort(arr, 0, arr.length -1, randomIndex(0, arr.length -1));

	}

	public static void quickSort(int[] arr, int L, int R, int num){

		if(L>=R){
			return;
		}

		int[] result = partition(arr, L, R, num);
		int lessI = result[0], greatI = result[1];

		quickSort(arr, L, lessI, randomIndex(L, lessI));

		quickSort(arr, greatI, R, randomIndex(greatI, R));

	}

堆排序

O(n*logn)

大根堆

完全二叉树的每一个父节点,比他的子节点的值都大。

小根堆

完全二叉树的每一个父节点,比他的子节点的值都小。