当两个时间复杂度一样时,直接跑程序对比
一、选择排序
算法思想:第一趟从n个元素的数据序列中选出关键字最小/大的元素并放在最前/后位置,下一趟从n-1个元素中选出最小/大的元素并放在最前/后位置。以此类推,经过n-1趟完成排序。
public static void seletionSort(int arr[])
{
if(arr == null || arr.length<2)
{
return;
}
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[j]<arr[minIndex]?j:minIndex;
if(arr[j]<arr[minIndex])
{
minIndex=j;
}
}
swap(arr,i,minIndex);
}
}
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];
}
时间复杂度为O(N²)
二、冒泡排序
1、将序列中的第一个元素和第二个元素进行比较,若前者大于后者,则将第一个元素与第二个元素进行位置交换,否则不交换
2、将第2个元素与第3个元素进行比较,同样若前者大于后者,则将第2个元素与第3个元素进行位置交换,否则不交换。
3、以此类推,直到将第n-1个元素与第n个元素进行比较为止。此过程称为第1趟冒泡排序,进过第21趟冒泡排序后,将长度为n的序列中最大的元素置于序列的尾部,即第n个位置上。
4、之后再进行第2趟…第n-1趟排序。冒泡排序完成。
public static void bubbleSort(int arr[])
{
if(arr == null || arr.length<2)
{
return;
}
// for(int i=0;i<arr.length-1;i++)
// {
// for(int j=0;j<arr.length-i-1;j++)
// {
// if(arr[j]<arr[j+1])
// {
// swap(arr,j,j+1);
// }
// }
// }
for(int i=arr.length-1;i>0;i--)
{
for(int j=0;j<i;j++)
{
if(arr[j]<arr[j+1])
{
swap(arr,j,j+1);
}
}
}
}
三、异或
理解为不进位相加
最重要的几个性质:
0^N=N
N^N=0
交换律
结合律
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];
}
该代码实现交换的原理就是上面几条性质:
假设a[i]=甲,a[j]=乙,则a[i]=甲^乙 ,a[j]=甲^乙^乙=甲 a[i]=甲^乙^甲=乙,故完成了交换。
思考题:
1.一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种
2.一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数要求时间复杂度为O(N)
public static void solution1(int arr[])
{
int eor = 0;
for(int cur: arr)
{
eor ^= cur;
}
System.out.println(eor);
}
public static void solution2(int arr[])
{
int eor1 = 0,eor2 = 0;
for(int curNum : arr)
{
eor1 ^= curNum;
}
// eor1 = a^b
// eor1 != 0;
// eor1 必有一个位置上是1(二进制想法)
int rightOne = eor1&(~eor1+1); //提取出最右侧的1
for(int cur : arr)
{
if((cur & rightOne) == 0) //思考000010000和其他数相与
{
eor2 ^= cur;
}
}
System.out.println(eor2+" "+(eor1^eor2));
}
四、插入排序
根据文件记录的关键字值得递增或者递减关系将文件记录的次序进行重新排列的过程。
或者是:将一个按值无序的数据序列转换成为一个按值有序的数据序列的过程
public static void insertionSort(int[] arr)
{
if(arr == null || arr.length <=2)
{
return;
}
//0-0是有序的
for(int i=1;i<arr.length;i++)
{
for(int j=i-1;j>=0 && arr[j]>arr[j+1];j--)
{
swap(arr,j,j+1);
}
}
}
五、二分法
1.在一个有序数组中,找某个数是否存在
2.在一个有序数组中,找>=某个数最左侧的位置
3.局部最小值问题(无序)