1.认识时间复杂度
- 常数时间的操作: 无论数据量多少,总能在固定时间内完成。
- 若某算法运算次数为 aN²+bN+c
则时间复杂度为 O(N²) 取最高指数项 且 忽略 其系数
注: O在数学上指的是上限 - 评价一个算法的好坏:先看时间复杂度的指标,然后再分析不同数据样本下实际运行的时间,也就是“常数项时间”。
2.简单排序
- 选择排序 时间复杂度 O(N²)
public class Day01_SelectionSort {
public static void selectionSort(int[] array) {
if (array == null || array.length < 2) {
return;
}
for (int i = 0; i < array.length-1; i++) { //i~N-1
int minIndex = i;
for (int j = i + 1; j < array.length; j++) {
//如果后面的数比前面的数小,就把后面的索引换成最小的索引,否则不变
minIndex = array[j] < array[minIndex] ? j : minIndex;
}
//交换索引处的数
int temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
}
public static void main(String[] args) {
int[] arr = new int[]{1, 6, 9, 8, 5, 2, 7};
selectionSort(arr);
Arrays.stream(arr).forEach(System.out::print);
}
}
- 冒泡排序 时间复杂度 O(N²)
public class Day02_BubbleSort {
public static void bubbleSort(int[] array) {
if (array == null || array.length < 2) {
return;
}
//第一次需要的冒泡的次数最多,但随着冒泡的流程走完几遍后,再交换的次数越来越少
// i是为了控制一次冒泡流程中冒泡的次数
for (int i = array.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
// int temp = array[j];
// array[j] = array[i];
// array[i] = temp;
array[j] = array[j] ^ array[j + 1];
array[j + 1] = array[j] ^ array[j + 1];
array[j] = array[j] ^ array[j + 1];
}
}
}
}
public static void main(String[] args) {
int[] arr = new int[]{1, 6, 9, 8, 5, 2, 7};
bubbleSort(arr);
Arrays.stream(arr).forEach(System.out::print);
}
}
此处分享几个两个数交换的方法
java两个数交换的方法详解
3.练习
-
一个int类型的数组,其中一个数出现奇数次,其余所有数出现偶数次,则如何找出这个数,要求时间复杂度 O(N),空间复杂度O(1)
-
一个int类型的数组,其中两 个数出现奇数次,其余所有数出现偶数次,则如何找出这个数,要求时间复杂度 O(N),空间复杂度O(1)
public class Day01Test2 {
/**
* 一个int类型的数组,其中一个数出现奇数次,其余所有数出现偶数次,则如何找出这个数,要求时间复杂度 O(N),空间复杂度O(1)
*/
public static void printOddTimesNum1(int[] arr) {
int eor = 0;
for (int cur : arr) {
eor ^= cur;
}
//比如 [1,1,6,5,7,6,5,5,5]
//运算 eor=0^1^1^6^6^7^5^5^5^5
// eor=0^0^0^7^0
// eor=7
System.out.println(eor);
}
/**
* 一个int类型的数组,其中两个数出现奇数次,其余所有数出现偶数次,则如何找出这个数,要求时间复杂度 O(N),空间复杂度O(1)
*/
public static void printOddTimesNum2(int[] arr) {
int eor = 0;
for (int cur : arr) {
eor ^= cur;
}
//比如 [1,1,6,5,7,9,6,5,5,5]
//运算 eor=0^1^1^6^6^7^5^5^5^5^9
// eor=0^0^0^7^0^9
// eor=7^9
// 因为两个数不相同 假设两个数为a b
// 则 eor=a^b !=0
// 因为eor!=0,所以eor的二进制必不全为0,所以eor的二进制至少有1一位为1
int rightOne = eor & (~eor + 1); //提取最右的1 ~eor+1 取反+1
int onlyOne = 0;
for (int cur : arr) {
if ((cur & rightOne) == 0) {
onlyOne ^= cur; //rightOne可以把a和b分开,把那一位为0的分成1组,a,b其中之一在那里,其余的在那一位为1的里
//之后把这一组进行全部异或,相同的消去,最后剩下的是a或b其中之一
}
}
System.out.println(onlyOne + " " + (eor ^ onlyOne)); //eor^onlyOne后得到的是 a^b^b=a 或 a^b^a=b
}
}
- 插入排序 时间复杂度 O(N²)
public class Day02_InsertSort {
public static void insertSort(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i; j >= 1; j--) {
if (array[j-1] > array[j]) {
int temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
}
}
Arrays.stream(array).forEach(System.out::print);
System.out.println("----第"+(i+1)+"轮---");
}
}
public static void main(String[] args) {
int[] array = new int[]{2, 1, 3, 5, 1};
insertSort(array);
}
}