a^a=0;
a^0=a;
交换a和b
a=a^b;
b=a^b;
a=a^b;
但必须满足是位置不同的(同一内存位置自己异或结果为0);
public static void swap(int[] arr , int a , int b){
if(a == b ){
return;
}
arr[a] = arr[a] ^ arr[b];
arr[b] = arr[a] ^ arr[b];
arr[a] = arr[a] ^ arr[b];
}
题目:
1)数组中一种数出现了奇数次,其他的出现了偶数次,找出出现奇数次的这个数(时间复杂度O(N) 空间复杂度:O(1))
思路:出现偶数次的数自己和自己异或后为0,异或满足结合律和交换律,所有元素异或即可的到结果
public class main{
public static int process(int[] arr){
int res = 0;
for(int i : arr){
res ^= i;
}
return res;
}
}
2)数组中两种数出现了奇数次,其他的出现了偶数次,找出出现奇数次的这个数(时间复杂度O(N) 空间复杂度:O(1))
思路:设a和b是出现奇数次的两个数,a不等于b,即a和b必有一位数不一样,所有元素异或之后的结果就是res = a^b不为0,当res有一位为1时,则说明这一位a和b不相等,则可将原数组分为两类,该位为1和为0的,将其中一类的全部元素进行异或,可得出其中一个奇数次的数记作res',再将其与res进行异或,得出另一个数。
补充:提取出一个数最右边的1的位置
int rightOne = res & (~res +1 );
举例: res: 1 0 1 0 1 1 1 1 0 0
~res: 0 1 0 1 0 0 0 0 1 1
~res+1: 0 1 0 1 0 0 0 1 0 0
res & (~res+1)= 0 0 0 0 0 0 1 0 0
结果:
public class Main{
public static void process(int[] arr){
int res = 0;
for(int curNmu : arr){
res ^= curNum;
}//得到a^b
int rightOne = res &(~res + 1);//提取出最右边的1
int onlyOne = 0;//准备得出res'
for(int cur : arr){
if((cur & rightOne )==1){//为0为1都可
onlyOne ^= cur;
}//得出res'
}
System.out.println(onlyOne + " " + (onlyOne ^ res));
}
}
每次只交换一次
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 swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
相邻两个数比较,交换,最大的往右排,相对小的往左排
举例子:
public static void bubbleSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for (int e = arr.length -1; e > 0 ; e--){ //0~e
for(int i = 0; i < e; i++){
if(arr[i] > arr[i + 1]){
swap(arr, i , i+1);
}
}
}
}
给定一个数组,做到0~0,0~1,0~2,… ,0~N-1位置有序,实现整体排序
代码:
public static void insertionSort(int[] arr){
if (arr = null || arr.length < 2){
return;
}
//0~0有序
//0~i想有序
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);
}//从后往前看,当前数往左换到不能换,停止
}
思路:遍历,时间复杂度O(N) , 二分法
经典二分:
总结:优化流程的标准1.数据状况 2.问题标准
同一个问题可能有多个方法,例如方法a,是我们想测试的方法,方法b是好实现,但时间复杂度不好的方法。所以采用对数器的方法,使用随机样本产生器,用方法a和b产生res1和res2,比较结果进行分析调整。
比如:
public static void main(String[] args){
int testTime = 500000; //测试次数
int maxSize = 100;//最大长度
int maxValue = 100;//最大值
boolean succeed = true;
for (int i = 0; i< testTime; i++){
int[] arr1 = generateRandomArray(maxSize, maxValue);//产生一个随机数组
int[] arr2 = copyArray(arr1);
insertionSort(arr1);//插入排序
comparator(arr2);//对数器方法排序
if(!isEqual(arr1, arr2)){//每个位置的值是否一样
//打印arr1
//打印arr2
succeed = false;
break;
}
}
System.out.println(succeed? "Nice!" : "No!");
}