这里写自定义目录标题
前言
数据结构和算法是每个程序员必不可少的一部分,算法培养思维逻辑,而数据结构提供实现思维的载体。
复杂度和简单排序算法
复杂度
1.时间复杂度
是对一个算法流程中发生的常数操作的总结,在总结出的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分为f(N),那么时间复杂度为O(f(N)。
2.空间复杂度
是对一个算法在运行过程中临时占用存储空间大小的一个量度。在常量空间中空间复杂度为S(n)=O(1),在线新空间和递归空间中空间复杂度都为 S(n)=O(n),在二维空间中空间复杂度为S(n)=O(n*m)。
简单排序算法
1.选择排序算法
从第一个数开始在其中找到最小的数与其交换位置,一直到最后交换完成,就完成了排序
//选择排序
public static void selectionSort(int[] arr){
//长度不足2的都直接返回
if (arr==null||arr.length<2){
return;
}
for (int i=0;i<arr.length-1;i++){
int minIndex=i;
//找到最小值的下标和值
for (int j=i+1;j<arr.length;j++){
minIndex=arr[j]<arr[minIndex]?j:minIndex;
}
//交换位置
swap(arr,i,minIndex);
}
}
// 交换两个数的位置
public static void swap(int[] arr,int i,int j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
2.冒泡排序算法
从开始两个数开始谁大(小)往右移动,一轮就确定了一位,以此类推就可以得到一个有序队列。
public static void bubbleSort(int[]arr){
if (arr==null||arr.length<2){
return;
}
for (int i=arr.length-1;i>0;i--){
for (int j=0;j<i;j++){
if (arr[i]>arr[i+1]){
swap(arr,i,i+1);
}
}
}
}
//交换函数
public static void swap(int[]arr,int i,int j){
arr[i]=arr[i]^arr[j];
arr[j]=arr[i]^arr[j];
arr[i]=arr[i]^arr[j];
}
交换中,异或运算中(无进位相加)
- n^0=n
- n^n=0
- a^ b=b^a
- (a^ b)^c=a ^(b ^ c)
- 一堆数异或,改变顺序,结果不变
不用其它变量交换两个数
a=a ^ b;
b=a ^ b;
a=a ^ b;
a和b值可以一样但储存的内存地址不能相同
3.插入排序算法
依次做到从0~1、0 ~2、0 ~3…0 ~n位置上有序,也就是说比较当前位置和前一位置的大小,按照排序要求比较移动(升序就把小的往前挪,降序把大的往前挪),移动完成再和前一个数比较,直到不满足条件则跳到下一组进行排序,到最后一组完成时整个数列就是有序的了。
插入排序的时间复杂度,会根据原数组的顺序而发生改变,最坏情况下为O(N^2)最好情况下为O(N)
public static void interpolationSort(int[] arr){
if (arr == null||arr.length<2){
return;
}
//0~0已经有序
for (int i=1;i<arr.length;i++){//0~i有序
for (int j=i-1;j>=0&&arr[j]>arr[j+1];j--){//当前数往前换到不能换或者到第一个位置为止
swap(arr,j,j+1);
}
}
}
public static void swap(int[]arr,int i,int j){
arr[i]=arr[i]^arr[j];
arr[j]=arr[i]^arr[j];
arr[i]=arr[i]^arr[j];
}
异或问题求解
1.数组中只存在一种数出现了奇数次,其它数出现了偶数次,如何找到这种数?
因为只有一种数出现了偶数次,根据异或运算规则,偶数次 数异或运算都为0,当到奇数次的数时,最后0 ^ 这个数等于他本身,就找到了。
public static void printOddTimesNum1(int[]arr){
int eor=0;
for (int cur:arr){
eor ^=cur;
}
System.out.println(eor);
}
2.数组中只存在两种数出现了奇数次,其它数出现了偶数次,如何找到这两种数?
当整个数组异或完后最后等于这两个数的异或,也就是这两个数的异或肯定不等于0,也就是这两个数其中位运算中某一位肯定不相同,提取出两个数异或运算后某一位为1的位置,所有的数在这个位置相同的形成一个集合,这里边一定存在这两种数中的一个,则另一个在另外一边,再将一边的数进行异或,由于只有那种数是奇数个,最后异或结果就是这种数,再将 这种数与两种数异或的结果进行异或就得到了另一种数。
public static void printOddTimesNum2(int[]arr){
int eor=0;
for (int cur:arr){
eor ^=cur;
}
//eor=a^b
//eor!=0
//eor必定有一位不为0
int rightOne=eor & (~eor +1);//提取最右侧为1的数 ~eor取反
int onlyOne=0;
for (int cur:arr){
if ((cur & rightOne)==0){
onlyOne ^=cur;
}
}
System.out.println(onlyOne+" "+(eor ^onlyOne));
}
总结
本文简单的介绍了复杂度和几种简单排序算法以及位运算的基本使用。