【数据结构与算法学习笔记】一、排序算法
一、排序算法
1. 异或运算^
二进制中相同为1,不同为0,可以理解为无进位相加
性质:
- 0 ^ N = N 、N ^ N = 0
- 交换律:a ^ b = b ^ a
- 结合律:a ^ b ^ c = a ^ (b ^ c) 运算顺序不影响结果
交换两个数(swap)
注意:只能在保证每个数都不一样的情况下使用,否则会把数字变成0(任何数异或自己等于0)
if (arr[i] == arr[j]){return;} //保证两个数不一样
public static void swap(int arr[], int i, int j){
arr[i] = arr[i] ^ arr[j]; // a = 甲 ^ 乙
arr[j] = arr[i] ^ arr[j]; //b = 甲 ^ 乙 ^ 乙 = 甲
arr[i] = arr[i] ^ arr[j]; //a = 甲 ^ 乙 ^ 甲 = 乙
}
异或例题:找出数组中出现奇数次的数
1、数组中有一个数出现了奇数次,其他出现了偶数次
public static int FindOddTimesNum1(int[] arr){
int oddNum = 0;
for (cur : arr){
oddNum ^= cur; //全部异或,得到结果
}
return oddNum;
}
2、数组中有两个数出现了奇数次,其他出现了偶数次
public static int FindOddTimesNum2(int[] arr){
int oddNum = 0;
for(cur : arr){
oddNum ^= cur;
}
//重复上一步,得到oddNum = a ^ b
//因为两个数不一样,所以其中必有一位是1
//提取出1的位置
int pos = oddNum & (~oddNum + 1)
//例 oddNum = 1001
//~oddNum = 0110
//~oddNum + 1 = 0111
//oodNum & (~oddNum + 1) = 0001
//这样提取出来就是最右边是1的一位还是1,其他位置上都为0
int oddNum2 = 0;
for(cur : arr){
if((cur & pos) == 0){ //因为pos其他位都是0,&结果一定是0不用管,如果结果=0那么说明这个数在这个1位置上也是0,可以改写成 (cur & pos) == pos
oddNum2 ^= cur;
}
System.out.println(oddNum2 + " " + (oddNum ^ oddNum2))
}
}
2. 简单排序
- 选择排序
public static void selectionSort(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;
}
swap(arr,i,minIndex); //交换
}
}
- 冒泡排序
public static void BubbleSort(int[] arr){
//去掉不合适的数组
if (arr == null || arr.length < 2){return;}
for (int len = arr.length - 1; len > 0; len--){ //每次循环确定最后一个值,i的循环最大值前移一位
for (int i = 0; i < len; i++){
if (arr[i] > arr[i + 1]){ //前一个比后一个大,往上冒泡
swap(arr,i,i+1); //交换
}
}
}
}
- 插入排序
public static void InsertionSort(int[] arr){
//去掉不合适的数组
if (arr == null || arr.length < 2){return;}
for(int i