1. 程式人生 > 其它 >資料結構與演算法基礎01—— 常見基本排序、二分法與異或運算

資料結構與演算法基礎01—— 常見基本排序、二分法與異或運算

常見基本排序

選擇排序

基本思路:從第一位開始標記,每次選出最小數字與標記位交換

程式碼實現:

    private static void selectSort(int[] arr) {
        if(arr == null || arr.length < 2){
            return;
        }
        for (int i = 0; i < arr.length-1; i++) {
            int index = i;
            for (int j = i + 1; j < arr.length; j++) {
                
if(arr[j] < arr[index]){ index = j; } } swap(arr, i ,index); } }
View Code

氣泡排序

基本思路:每次比較相鄰兩個數大小,每次迴圈選出當輪最大/小數字,每次迴圈次數環比減一

程式碼實現:

    private static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            
return; } for (int end = arr.length-1; end >0; end--) { for (int start = 0; start < end; start++) { if(arr[start]>arr[start+1]){ swap(arr, start, start+1); } } } }
View Code

插入排序

基本思路:保證前面有序的情況下,依次把後面數字插入到指定位置繼續保證有序

程式碼實現:

    private static void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0 && arr[j]<arr[j-1]; j--) {
                swap(arr,j,j-1);
            }
        }
    }
View Code

二分法

基本思路:根據左右邊界計算中間位置,中間值和目標值比較,如果中間值小於目標值,左邊界等於中間位置+1,如果中間值大於目標值,右邊界等於中間位置-1。

在一個有序陣列中,找某個數是否存在

    private static boolean isExist(int[] arr, int num) {
        if(arr == null || arr.length <2){
            return false;
        }
        int L = 0;
        int R = arr.length-1;
        int mid = 0;
        while (L < R){
            mid = L + ((R-L) >> 1);
            if(arr[mid] == num){
                return true;
            }else if(arr[mid] < num){
                L = mid + 1;
            }else{
                R = mid - 1;
            }
        }
        return arr[L] == num;
    }
View Code

在一個有序陣列中,找>=某個數最左側的位置

    private static int leftmostPosition(int[] arr, int num) {
        int L = 0;
        int R = arr.length-1;
        int mid = 0;
        int index = -1;
        while (L <= R){
            mid = L + ((R-L) >> 1);
            if(arr[mid] >= num){
                index = mid;
                R = mid - 1;
            }else{
                L = mid + 1;
            }
        }
        return index;
    }
View Code

在一個有序陣列中,找<=某個數最右側的位置

    private static int rightmostPosition(int[] arr, int num) {
        int L = 0;
        int R = arr.length-1;
        int mid = 0;
        int index = -1;
        while (L <= R){
            mid = L + ((R-L) >> 1);
            if(arr[mid] <= num){
                index = mid;
                L = mid + 1;
            }else{
                R = mid - 1;
            }
        }
        return index;
    }
View Code

相鄰兩數不等,區域性最小值問題

    private static int localMinimum(int[] arr){
        if(arr == null || arr.length<=1){
            return -1;
        }
        if(arr[0] < arr[1]){
            return 0;
        }
        if(arr[arr.length - 1] < arr[arr.length - 2]){
            return arr.length - 1;
        }
        int L = 1;
        int R = arr.length - 2;
        int mid = 0;
        while (L < R){
            mid = L + ((R - L) >> 1);
            if(arr[mid] > arr[mid-1]){
                R = mid - 1;
            }else if(arr[mid] > arr[mid+1]){
                L = mid + 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
View Code

異或運算

基本規則:相同則0,不同則1

不用額外變數交換兩個數

    private static void swap(int[] arr, int a, int b){
        arr[a] = arr[a] ^ arr[b];
        arr[b] = arr[a] ^ arr[b];
        arr[a] = arr[a] ^ arr[b];
    }
View Code

一個數組中有一種數出現奇數次,其他數都出現了偶數次,怎麼找到並列印這種數

    private static int getNum(int[] arr){
        if(arr == null || 0 == arr.length){
            return -1;
        }
        int num = 0;
        for (int i = 0; i < arr.length; i++) {
            num ^= arr[i];
        }
        return num;
    }
View Code

一個數組中有兩種數出現奇數次,其他數都出現了偶數次,怎麼找到並列印這兩種數

    private static void printNums(int[] arr){
        int num = 0;
        for (int i = 0; i < arr.length; i++) {
            num ^= arr[i]; // 最終結果是兩種數:a^b
        }
        // a^b不等於0,所以在某個位置,一個數是0,一個數是1
        // 找出最右位置的1,然後取該位置為0的數字進行異或就可以找出其中一個數
        int farRightOne = num & ((~num)+1);

        int onlyOne = 0;
        for (int i = 0; i < arr.length; i++) {
            if((arr[i] & farRightOne) != 0){
                onlyOne ^= arr[i];
            }
        }
        System.out.println(onlyOne + " ^ " + (num ^ onlyOne));
    }
View Code

數出二進位制1的個數

    private static int getNumberOfOne(int num) {
        int count = 0;
        while (num != 0 ){
             num &= num  - 1;
             count++;
        }
        return count;
    }
View Code