Java面試被經常問到的常用算法


一、冒泡排序

    原理:比較兩個相鄰的元素,較大的放在右邊

    N個數字要排序完成,總共進行N-1趟排序,每i趟的排序次數為(N-i)次

    最好時間復雜度為O(N)

    Cmax = N(N-1)/2 = O(N2)
    Mmax = 3N(N-1)/2 = O(N2)
    冒泡排序的最壞時間復雜度為O(N2)
    冒泡排序的平均時間復雜度為O(N2)

 public void bubbleSort(int[] list) {
        int temp = 0; // 用來交換的臨時數
        boolean bChange = false; // 交換標志
        // 要遍歷的次數
        for (int i = 0; i < list.length - 1; i++) {
            bChange = false;
            // 從后向前依次的比較相鄰兩個數的大小,遍歷一次后,把數組中第i小的數放在第i個位置上
            for (int j = list.length - 1; j > i; j--) {
                // 比較相鄰的元素,如果前面的數大於后面的數,則交換
                if (list[j - 1] > list[j]) {
                    temp = list[j - 1];
                    list[j - 1] = list[j];
                    list[j] = temp;
                    bChange = true;
                }
            }
            // 如果標志為false,說明本輪遍歷沒有交換,已經是有序數列,可以結束排序
            if (false == bChange)
                break;
        }
    }

二、快速排序

     通過一趟排序將要排序的數據分割成獨立的兩部分:分割點左邊都是比它小的數,右邊都是比它大的數。

     時間復雜度:最好情況(待排序列接近無序)時間復雜度為O(nlog2n),最壞情況(待排序列接近有序)時間復雜度為O(n2),平均時間復雜度為O(nlog2n)。

 

/**
 * @description: 快速排序
 * 72  6  57  88  70  42  83  73  48  85 (10個元素)
 * 首先取第一個數為基准數:72
 * 初始時,i = 0, j = 9; X = a[i] = 72
 * 這個時候由於將 a[0] 中的數保存到 X 中,相當於數組 a[0] 上挖了一個坑,現需要用其他數據把它填充
 * 從 j(后) 開始向前找一個比 X 小或者等於 X 的數。
 * 當 j=8 ,符合上述條件,此時將 a[8] 挖出來填充到上一個坑a[0]中。 a[0] = a[8]
 * 現在又形成了一個新坑 a[8] ,再次找數字填充a[8]
 * 此時要從 i(前) 往后找大於 X 的數
 * 當 i= 3 時,符合上述條件,將 a[3] 挖出來填充到 a[8]。  a[8] = a[3]
 * (此時的十個數據是 48  6  57  坑  70  42  83  73  88  85)
 * 現在是 i = 3; j = 7; X = 72
 * 重復之前的步驟,先從后往前找,再從前往后找
 * 從 j 開始往前找,當 j = 5,符合之前條件,將 a[5] 填充到 a[3]。 a[3] = a[5]
 * 再從 i 開始往后找, 當 i = 5 時, i == j 退出。
 * (此時的十個數據是 48  6  57 42  70  72  83  73  88  85)
 * @author: mhSui
 * @date: 2019-08-19
 */
public class QuickSort {
    public static int partition(int[] list, int start, int end){
        //list[start] 就是第一個坑,也就是基准數
        int key = list[start];
        while (start < end){
            //首先從后往前找小於 X 的數填充 list[start]
            while (start < end && list[end] >= key){
                end--;
            }
            list[start++] = list[end];
            //在從前往后找大於 X 的數
            while (start < end && list[start] < key){
                start++;
            }
            list[end--] = list[start];
        }
        list[start] = key;
        return start;
    }
    public static void quickSort(int[] list, int start, int end){
        int pivot=0;
        if(start < end) {
            pivot=partition(list,start,end);
            //遞歸調用
            quickSort(list,start,pivot-1);
            quickSort(list,pivot+1,end);
        }
    }
    public static void main(String[] args) {
        QuickSort quickSort = new QuickSort();
        int arr[]= {72,6,57,88,70,42,83,73,48,85};
        System.out.println("排序前:"+ Arrays.toString(arr));
        quickSort.quickSort(arr,0,arr.length-1);
        System.out.println("排序后:"+Arrays.toString(arr));
    }
}
View Code

    可以看一下Arrays.sort()底層源碼

 三、二分法

      這里我就直接貼Java里面二分查找的源碼Arrays.binarySearch()

 // Like public version, but without range checks.
    private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

四、選擇排序

     選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是:第一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然后再從  剩余的未排序元素中尋找到最小(大)元素,然后放到已排序的序列的末尾。以此類推,直到全部待排序的數據元素的個數為零。

/**
 * @description: 選擇排序
 * @author: mhSui
 * @date: 2019-08-19
 */
public class SelectSort {
    public  static void selectSort(int[] arr,int length){
        for (int i = 0;i < arr.length;i++){
            int index = i;
            int j;
            //找出最小元素下標
            for (j = i + 1;j < length; j++){
                if (arr[j] < arr[index]) {
                    index = j;
                }
            }
            int temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
        }
    }
}
View Code

五、插入排序

     每次處理就是將無序的數列中第一個元素與有序數列的元素從后到前比較,找到插入位置,將該元素插入到有序數列的適當的最終的位置上(穩定排序)。

     空間:僅需要一個輔助空間,為O(1)

     時間:對數列進行升序排列,最好情況——已經是升序了,比較次數為(n-1)次;最壞情況——已經是降序了,比較次數為(n-1)*n/2,賦值操作為(n-1)*n/2 + (n-     1)。

    平均來說插入排序算法復雜度為O(n2)。因而,插入排序不適合對於數據量比較大的排序應用。但是,如果需要排序的數據量很小,例如,量級小於千,那么插入排序還是一個不錯的選擇。 插入排序在工業級庫中也有着廣泛的應用,在STL的sort算法和stdlib的qsort算法中,都將插入排序作為快速排序的補充,用於少量元素的排序(通常為8個或以下)

/**
 * @description: 插入排序
 * @author: mhSui
 * @date: 2019-08-19
 */
public class InsertSort {

    private static void insertSort(int[] arr){
        for (int i = 0; i < arr.length; i++){
            // arr[i] 在arr[0...length-1]有序區間找到合適位置
            int temp = arr[i];
            int j = i-1;
            while(j >= 0 && arr[j] > temp){
                arr[i+1] = arr[j];
                j = j-1;
            }
            arr[j+1] = temp;
        }
    }
}

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM