选择、冒泡、插入排序,二分法和对数器

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++) {
// 最小值在哪个位置上 in-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();
}
}


原文地址:https://www.cnblogs.com/yanghailu/p/12772148.html