选择、冒泡、插入排序,二分法和对数器
package arithmetic; import java.util.ArrayList; import java.util.Arrays; /** * @author hailu */ public class Sort { /** * 选择排序 */ public static void selectionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } /* * 0 ~ n-1 * 1 ~ n-1 * 2 ~ n-1 * ...~ n-1 * */ // i ~ N-1 for (int i = 0; i < arr.length - 1; i++) { // 最小值在哪个位置上 i~n-1 int minIndex = i; // i ~ N-1 上找最小值的下标 //从第二个开始,每个元素和左侧元素比较 for (int j = i + 1; j < arr.length; j++) { minIndex = arr[j] < arr[minIndex] ? j : minIndex; } swap(arr, i, minIndex); } } /** * 冒泡排序 */ public static void bubbleSort(int[] arr) { if (arr == null || arr.length < 2) { return; } // 0 ~ N-1 // 0 ~ N-2 // 0 ~ N-3 //从最后一个元素开始 for (int i = arr.length - 1; i > 0; i--) { for (int j = 0; j < i; j++) { //从第一个元素开始,右侧相邻元素比较 if (arr[j] < arr[i + 1]) { swap(arr, i, j + 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; j > 0; j--) { if (arr[j] < arr[j - 1]) { swap(arr, j, j - 1); } } } } /** * 二分法:查找有序数组是否包含某个数字 * * @param sortedArr * @param num * @return */ public static boolean exist(int[] sortedArr, int num) { if (sortedArr == null || sortedArr.length == 0) { return false; } int L = 0; int R = sortedArr.length - 1; while (L < R) { // mid = (L+R) / 2; // L 10亿 R 18亿 超出int最大值 // mid = L + (R - L) / 2 // N / 2 N >> 1 int mid = L + ((R - L) >> 1); if (sortedArr[mid] == num) { return true; } else if (sortedArr[mid] > num) { R = mid - 1; } else { L = mid + 1; } } return sortedArr[L] == num; } /** * 二分法:在arr上,找满足>=value的最左位置 * * @param arr * @param value * @return */ public static int nearestIndex(int[] arr, int value) { int L = 0; int R = arr.length - 1; int index = -1; while (L <= R) { int mid = L + ((R - L) >> 1); //这里的 >= 符号和题干对应 if (arr[mid] >= value) { //更新index index = mid; R = mid - 1; } else { L = mid + 1; } } return index; } /** * arr中,只有一种数,出现奇数次 * * @param arr */ public static void printOddTimesNum1(int[] arr) { //0^N -> N int eor = 0; for (int i = 0; i < arr.length; i++) { //异或异或满足交换律结合律,偶数次按位异或后为0 // eor=eor^arr[1]; // eor=eor^arr[2]; // eor=eor^arr[3]; eor ^= arr[i]; } System.out.println(eor); } //怎么把int数提取出最右侧的 1 ? // N&((~N)+1) //N = 0000 1101 1000 //~N= 1111 0010 0111 //~N+1= 1111 0010 1000 //N&((~N)+1)=0000 0000 1000 最右侧的 1 出现了 /** * arr中有两种数出现了奇数次,其他数出现了偶数次,找到这两种数 * * @param arr */ public static void printOddTimesNum2(int[] arr) { //找到出现奇数次的两个数 int eor = 0; for (int i = 0; i < arr.length; i++) { //偶数次最后位0 // a!=b -> eor!=0 // a ,b 存在第 n 位不相同,eor必然有一个位置上是1 // eor最后的结果是 a^b //第 n 位存在两种数 0(有奇有偶) 或 1(有奇有偶),但是 a 和 b 一定是分开的 eor ^= arr[i]; } // 提取出最右的 1 0000 0000 1000 int rightOne = eor & ((~eor) + 1); //eor' int one = 0; for (int i = 0; i < arr.length; i++) { if ((arr[i] & rightOne) != 0) { // 或者 if ((arr[i] & rightOne) == rightOne) { // rightOne 0000 0001 0000 //arr[i]&rightOne 0000 1011 0000 //(arr[i]&rightOne)!=0 代表该位有 1 // one ^= arr[i]; } } int tow = eor ^ one; System.out.println(one + " " + tow); } /** * 任意数中二进制 1 的个数 * * @param N * @return */ public static int bit1counts(int num) { //方法1:循环32次 //方法2:比循环32次要快 int count = 0; while (num != 0) { int rightOne = num & ((~num) + 1); count++; //抹掉最后一个 1 num ^= rightOne; //num为正数时可这么写: num -= rightOne } return count; } public static void main(String[] args) { // int[] arr = new int[]{5, 3, 4, 1, 2}; // int[] arr = new int[]{1, 2, 3, 4, 5}; // System.out.println(nearestIndex(arr,4)); // // selectionSort(arr); // boolean b=exist(arr,1); // printArray(arr); // // 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); //// selectionSort(arr1); //// selectionSort(arr1); //// insertionSort(arr1); //// comparator(arr2); //// if (!isEqual(arr1, arr2)) { //// succeed = false; //// printArray(arr1); //// printArray(arr2); //// break; //// } // // //Test for nearestIndex // int[] arr = generateRandomArray(maxSize, maxValue); // Arrays.sort(arr); // int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); // if (test(arr, value) != nearestIndex(arr, value)) { // printArray(arr); // System.out.println(value); // System.out.println(test(arr, value)); // System.out.println(nearestIndex(arr, value)); // succeed = false; // break; // } // } // System.out.println(succeed ? "Nice!" : "Fucking fucked!"); // int[] arr = generateRandomArray(maxSize, maxValue); // printArray(arr); // selectionSort(arr); // printArray(arr); //Test for printOddTimesNum1 // int[] arr1 = {3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1}; // printOddTimesNum1(arr1); // int[] arr2 = {4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2}; // printOddTimesNum2(arr2); System.out.println(bit1counts(9)); } // for test public static int test(int[] arr, int value) { for (int i = 0; i < arr.length; i++) { if (arr[i] >= value) { return i; } } return -1; } // for test public static boolean isEqual(int[] arr1, int[] arr2) { if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { return false; } if (arr1 == null && arr2 == null) { return true; } for (int i = 0; i < arr1.length; i++) { if (arr1[i] != arr2[i]) { return false; } } return true; } // for test public static int[] generateRandomArray(int maxSize, int maxValue) { /* * Math.random() [0,1) * Math.random()*N [0,N) * (int)(Math.random()*N) [0,N-1] * */ int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; for (int i = 0; i < arr.length; i++) { // [-? , +?] arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); } return arr; } // for test public static void comparator(int[] arr) { Arrays.sort(arr); } // for test public static int[] copyArray(int[] arr) { if (arr == null) { return null; } int[] res = new int[arr.length]; for (int i = 0; i < arr.length; i++) { res[i] = arr[i]; } return res; } public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //位运算交换数组arr[i]和arr[j]指向同一块内存时值为0 public static void swapBitOperation(int[] arr, int i, int j) { arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j]; } public static void printArray(int[] arr) { if (arr == null) { return; } for (int i = 0; i < arr.length; i++) { System.out.println(arr[i] + " "); } System.out.println(); } }
package arithmetic;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author hailu
*/
public class Sort {
/**
* 选择排序
*/
public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
/*
* 0 ~ n-1
* 1 ~ n-1
* 2 ~ n-1
* ...~ n-1
* */
// i ~ N-1
for (int i = 0; i < arr.length - 1; i++) {
// 最小值在哪个位置上 i~n-1
int minIndex = i;
// i ~ N-1 上找最小值的下标
//从第二个开始,每个元素和左侧元素比较
for (int j = i + 1; j < arr.length; j++) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
/**
* 冒泡排序
*/
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// 0 ~ N-1
// 0 ~ N-2
// 0 ~ N-3
//从最后一个元素开始
for (int i = arr.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
//从第一个元素开始,右侧相邻元素比较
if (arr[j] < arr[i + 1]) {
swap(arr, i, j + 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; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
swap(arr, j, j - 1);
}
}
}
}
/**
* 二分法:查找有序数组是否包含某个数字
*
* @param sortedArr
* @param num
* @return
*/
public static boolean exist(int[] sortedArr, int num) {
if (sortedArr == null || sortedArr.length == 0) {
return false;
}
int L = 0;
int R = sortedArr.length - 1;
while (L < R) {
// mid = (L+R) / 2;
// L 10亿 R 18亿 超出int最大值
// mid = L + (R - L) / 2
// N / 2 N >> 1
int mid = L + ((R - L) >> 1);
if (sortedArr[mid] == num) {
return true;
} else if (sortedArr[mid] > num) {
R = mid - 1;
} else {
L = mid + 1;
}
}
return sortedArr[L] == num;
}
/**
* 二分法:在arr上,找满足>=value的最左位置
*
* @param arr
* @param value
* @return
*/
public static int nearestIndex(int[] arr, int value) {
int L = 0;
int R = arr.length - 1;
int index = -1;
while (L <= R) {
int mid = L + ((R - L) >> 1);
//这里的 >= 符号和题干对应
if (arr[mid] >= value) {
//更新index
index = mid;
R = mid - 1;
} else {
L = mid + 1;
}
}
return index;
}
/**
* arr中,只有一种数,出现奇数次
*
* @param arr
*/
public static void printOddTimesNum1(int[] arr) {
//0^N -> N
int eor = 0;
for (int i = 0; i < arr.length; i++) {
//异或异或满足交换律结合律,偶数次按位异或后为0
// eor=eor^arr[1];
// eor=eor^arr[2];
// eor=eor^arr[3];
eor ^= arr[i];
}
System.out.println(eor);
}
//怎么把int数提取出最右侧的 1 ?
// N&((~N)+1)
//N = 0000 1101 1000
//~N= 1111 0010 0111
//~N+1= 1111 0010 1000
//N&((~N)+1)=0000 0000 1000 最右侧的 1 出现了
/**
* arr中有两种数出现了奇数次,其他数出现了偶数次,找到这两种数
*
* @param arr
*/
public static void printOddTimesNum2(int[] arr) {
//找到出现奇数次的两个数
int eor = 0;
for (int i = 0; i < arr.length; i++) {
//偶数次最后位0
// a!=b -> eor!=0
// a ,b 存在第 n 位不相同,eor必然有一个位置上是1
// eor最后的结果是 a^b
//第 n 位存在两种数 0(有奇有偶) 或 1(有奇有偶),但是 a 和 b 一定是分开的
eor ^= arr[i];
}
// 提取出最右的 1 0000 0000 1000
int rightOne = eor & ((~eor) + 1);
//eor'
int one = 0;
for (int i = 0; i < arr.length; i++) {
if ((arr[i] & rightOne) != 0) {
// 或者 if ((arr[i] & rightOne) == rightOne) {
// rightOne 0000 0001 0000
//arr[i]&rightOne 0000 1011 0000
//(arr[i]&rightOne)!=0 代表该位有 1
//
one ^= arr[i];
}
}
int tow = eor ^ one;
System.out.println(one + " " + tow);
}
/**
* 任意数中二进制 1 的个数
*
* @param N
* @return
*/
public static int bit1counts(int num) {
//方法1:循环32次
//方法2:比循环32次要快
int count = 0;
while (num != 0) {
int rightOne = num & ((~num) + 1);
count++;
//抹掉最后一个 1
num ^= rightOne;
//num为正数时可这么写: num -= rightOne
}
return count;
}
public static void main(String[] args) {
// int[] arr = new int[]{5, 3, 4, 1, 2};
// int[] arr = new int[]{1, 2, 3, 4, 5};
// System.out.println(nearestIndex(arr,4));
//
// selectionSort(arr);
// boolean b=exist(arr,1);
// printArray(arr);
//
// 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);
//// selectionSort(arr1);
//// selectionSort(arr1);
//// insertionSort(arr1);
//// comparator(arr2);
//// if (!isEqual(arr1, arr2)) {
//// succeed = false;
//// printArray(arr1);
//// printArray(arr2);
//// break;
//// }
//
// //Test for nearestIndex
// int[] arr = generateRandomArray(maxSize, maxValue);
// Arrays.sort(arr);
// int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
// if (test(arr, value) != nearestIndex(arr, value)) {
// printArray(arr);
// System.out.println(value);
// System.out.println(test(arr, value));
// System.out.println(nearestIndex(arr, value));
// succeed = false;
// break;
// }
// }
// System.out.println(succeed ? "Nice!" : "Fucking fucked!");
// int[] arr = generateRandomArray(maxSize, maxValue);
// printArray(arr);
// selectionSort(arr);
// printArray(arr);
//Test for printOddTimesNum1
// int[] arr1 = {3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1};
// printOddTimesNum1(arr1);
// int[] arr2 = {4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2};
// printOddTimesNum2(arr2);
System.out.println(bit1counts(9));
}
// for test
public static int test(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] >= value) {
return i;
}
}
return -1;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
/*
* Math.random() [0,1)
* Math.random()*N [0,N)
* (int)(Math.random()*N) [0,N-1]
* */
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
// [-? , +?]
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//位运算交换数组arr[i]和arr[j]指向同一块内存时值为0
public static void swapBitOperation(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] + " ");
}
System.out.println();
}
}