选择排序、冒泡排序、位运算、奇数频次数字问题
作者:互联网
选择排序
时间复杂度 \(O(N^2)\),空间复杂度 \(O(1)\)。
public class Code01_SeclectionSort {
public static void selectionSort(int[] arr) {
if (arr == null ||arr.length < 2)
return;
for (int i = 0; i < arr.length - 1; i++) { // scan the whole array
int minIndex = 1;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex])
minIndex = j;
}
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 main(String[] argv) {
int[] arr = {5, 4, 3, 2, 1};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}
}
冒泡排序
时间复杂度 \(O(N^2)\),空间复杂度 \(O(1)\)。
public class Code02_BubbleSort {
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
for (int j = arr.length - 1; j > 0; j--) {
for (int i = 0; i < j; i++) {
if (arr[i] > arr[i+1])
swap(arr, i, i+1);
}
}
}
// swap arr[i] and arr[j] 位运算的精彩演绎(不建议这么写)
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,不同为;2)不进位相加
关于异或运算 ^ :
0 ^ N = N;
N ^ N = 0;
且异或运算满足交换律和结合律
假设有 a=甲, b=乙
a = a^b = 甲^乙
b = a^b = (甲^乙)^乙 = 甲^(乙^乙) = 甲^0 = 甲
a = a^b = (甲^乙)^甲 = (甲^甲)^乙 = 0^乙 = 乙
a与b的值交换成功
a与b值可以一样,但是a和b不能指向同一内存区域,否则会被洗成0
这种抖机灵方式实现了原地交换两个变量,不需要额外内存
本来不推荐这样做,但是这个示例有利于理解异或操作
*/
}
public static void main(String[] argv) {
int[] arr = {5, 4, 3, 2, 1};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}
奇数频次数字问题
找到数组中出现技术次的唯一或唯二的数,位运算的精妙展示
public class Code07_evenTimesOddTimes {
/*
找到数组中出现奇数次的唯一的那个数
*/
public static void printOddTimesNum1(int[] arr) {
int eor = 0;
for (int cur :arr) {
eor ^= cur;
}
System.out.println(eor);
}
/*
找到数组中出现奇数次的唯二的那两个数
*/
public static void printOddTimesNum2(int[] arr) {
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^=arr[i];
} // eor = a ^ b
// a与b不同,则eor必有一位为1
int rightOne = eor & (~eor + 1); // NOTE 这是常用的取最右侧1二进制序列的方法
// 一个数与上自己的取反加一,就是得到自己最右非零位的序列
int onlyOne = 0; //eor'
for (int cur : arr) {
if ((cur & rightOne) != 0) {
onlyOne ^= cur;
}
}
System.out.println(onlyOne + "" + (eor ^ onlyOne));
}
public static void main(String[] argv) {
int[] arr1 = {1, 2, 3, 4, 1, 2, 3, 4, 5};
printOddTimesNum1(arr1);
int[] arr2 = {1, 2, 3, 4, 6, 1, 2, 3, 4, 5};
printOddTimesNum2(arr2);
}
}
插入排序
时间复杂度 \(O(N^2)\),(与之前方法不同,插入排序复杂度还与数据原始排列有关,这里只考虑最坏)
空间复杂度 \(O(1)\)。
import java.util.Arrays;
/*
插入 排序
*/
public class Code03_InsertionSort {
public static void insertionSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
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);
}
}
}
// swap arr[i] and arr[j]
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] argv) {
int[] arr = {5, 4, 3, 2, 1};
insertionSort(arr);
System.out.println(Arrays.toString(arr));
}
}
标签:arr,奇数,int,void,冒泡排序,频次,eor,static,public 来源: https://www.cnblogs.com/ockone/p/16460402.html