1. 程式人生 > >牛客網演算法初級班(一)

牛客網演算法初級班(一)

一、認識時間複雜度

  • 常數時間的操作:一個操作如果和資料量沒有關係,每次都 固定時間內完成的操作,叫做常數操作。

  • 時間複雜度為一個演算法流程中,常數運算元量的指標。常用O(讀作big O)來表示。具體來說,在常數運算元量的表示式中, 只要高階項,不要低階項,也不要高階項的係數,剩下的部分如果記為f(N),那麼時間複雜度為O(f(N))。

  • 評價一個演算法流程的好壞,看時間複雜度的指標,然後再分析不同資料樣本下的實際執行時間,也就是常數項時間。

二、一個簡單的理解時間複雜度的例子

例子:一個有序陣列A,另一個無序陣列B,請列印B中的所有不在A中的數,A數 組長度為N,B陣列長度為M。演算法流程1
:對於陣列B中的每一個數,都在A中通過遍歷的方式找一下;

// a有序, b無序
public static void  square(int[] a, int[] b){
    boolean flag = false;
    for (int i = 0; i < b.length; i++) {
        for (int j = 0; j < a.length; j++) {
            // 如果b中的元素在a中存在,跳出迴圈,不列印該元素
            if (b[i] == a[j]){
                flag = true;
                break;
            }
        }
        if (!flag)
            System.out.print(b[i] + "   ");
        flag = false;
    }
    System.out.println();
}

分析:時間複雜度O(N^{2}),空間複雜度O(1)演算法流程2:對於陣列B中的每一個數,都在A中通過二分的方式找一下;

public static void binary(int[] a, int[] b){
        boolean flag = false;
        for (int i = 0; i < b.length; i++) {
            int left = 0, right = a.length - 1;
            flag = false;
            while (left <= right){

                int mid = left + (right - left) / 2;

                if (a[mid] == b[i]){
                    flag = true;
                    break;
                }

                if (a[mid] < b[i])
                    left = mid + 1;
                else if (a[mid] > b[i])
                    right = mid - 1;


            }
            if (!flag)
                System.out.print(b[i] + "  ");
        }
        System.out.println();
}

分析:時間複雜度O(N*logN),空間複雜度O(1)演算法流程3:先把陣列B排序,然後用類似外排的方式列印所有在A中出現的數;

// a有序, b無序
public static void sort(int[] a, int[] b){
    Arrays.sort(b);
    int i = 0, j = 0;
    while (i < b.length && j < a.length){
        if (b[i] < a[j])
            System.out.print(b[i++] + " ");
        else if(b[i] > a[j])
            j++;
        else
            i++;
    }
    if (i < b.length && j == a.length && b[i] == a[j-1])
        i++;
    while (i < b.length){
        System.out.print(b[i] + " ");
        i++;
    }
    System.out.println();
}

三、對數器的概念和使用 

  • 0,有一個你想要測的方法a(比如,氣泡排序演算法)

public static void bubbleSort(int[] arr){
    if (arr == null || arr.length < 2)
        return;
    for (int end = arr.length - 1; end > 0; end --){
        for (int i = 0; i < end; i++){
            if (arr[i] > arr[i+1])
                swap(arr, i, i+1);
        }
    }
}
  • 1,實現一個絕對正確但是複雜度不好的方法b,

// 在排序演算法中,直接呼叫Arrays.sort(arr);
public static void comparator(int[] arr) {
        Arrays.sort(arr);
}
  • 2,實現一個隨機樣本產生器

 public static int[] generateRandomArray(int maxSize, int maxValue) {
        // 陣列長度: [0, size]
        // Math.random() [0, 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;
}
  • 3,實現比對的方法

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 boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
}
  • 4,把方法a和方法b比對很多次來驗證方法a是否正確,並列印樣本分析是哪個方法出錯。

public static void main(String[] args) {
    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);
        bubbleSort(arr1);
        comparator(arr2);
        if (!isEqual(arr1, arr2)) {
            succeed = false;
            System.out.println("#########################################################");
            System.out.println("my array : ");
            printArray(arr1);
            printArray(arr2);
            System.out.println("right array : ");
            System.out.println("#########################################################");
            break;
        }
    }
    System.out.println(succeed ? "Nice!" : "Fucking fucked!");

    int[] arr = generateRandomArray(maxSize, maxValue);
    printArray(arr);
    selectSort(arr);
    printArray(arr);
}