其他分享
首页 > 其他分享> > 选择排序、冒泡排序、位运算、奇数频次数字问题

选择排序、冒泡排序、位运算、奇数频次数字问题

作者:互联网

选择排序

时间复杂度 \(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