1. 认识事件复杂度和简单排序算法
常数操作:一个操作如果和样本的数据量无关,每次都是固定时间内完成的操,称为常数操作,加减乘除均为常数操作
1.1时间复杂度(big O)
- 为一个算法流程中,常数操作数量的一个指标。常用O(读作big O,最差的时间复杂度)来表示。具体来说,想要对一个算法流程非常熟悉,然后去写出这个算法流程中,发生了多少次常数操作,进而总结出常数操作数量的表达式。在表达式中,只要高阶项,不要低阶项,且忽略高阶项的系数。
- θ平均时间复杂度
- Ω最优时间复杂度
- 评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。
1.2 选择排序、冒泡排序细节与复杂度分析
时间复杂度O(N^2),额外空间复杂度O(1)
1.2.1 选择排序
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
- 数据规模越小越好。时间复杂度为O(N^2),优点是不占用额外空间
import java.util.Arrays;
public class Code01_SelectionSort {
public int[] selectionSort(int[] arr){
if(arr == null||arr.length<2){
return arr;
}
for (int i = 0; i < arr.length-1; i++) {
//i~N-1
int minIndex = i;
for (int j = i+1; j < arr.length; j++) {
//i~N-1上找最小值的下标
minIndex = arr[minIndex]>arr[j]?j:minIndex;
}
swap(arr,i,minIndex);//交换i位置与最小值位置的值。
}
return arr;
}
public void swap(int[] arr,int i,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
Code01_SelectionSort code01_selectionSort = new Code01_SelectionSort();
int[] arr = new int[]{
10,9,1,3,2,4};
int[] arrNew = code01_selectionSort.selectionSort(arr);
System.out.println(Arrays.toString(arrNew));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
1.2.2 冒泡排序
算法思想:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
性能总结:
- 可以实现稳定性,但不一定具有稳定性。时间复杂度为O(N^2),空间复杂度为O(1)
- 当数据为正序时,最快。此时已经为正序。当数据为逆序时,最慢,直接逆序输出即可。
public class Code02_BubbleSort {
public int[] bubbleSort(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = i+1; j < arr.length; j++) {
if(arr[i]>arr[j]){
//比较相邻元素,若前面的数大于后一个,则交换。
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
return arr;
}
public static void main(String[] args) {
int[] arr = new int[]{
5,6,1,2,4,3,9};
System.out.println(Arrays.toString(