算法初级入门

算法复杂度

  • O(1):常量阶,运行时间为常量
  • O(logn):对数阶,如二分搜索算法
  • O(n):线性阶,如n个数内找最大值
  • O(nlogn):对数阶,如快速排序算法
  • O(n^2):平方阶,如选择排序,冒泡排序
  • O(n^3):立方阶,如两个n阶矩阵的乘法运算
  • O(2^n):指数阶,如n个元素集合的所有子集的算法
  • O(n!):阶乘阶,如n个元素全部排列的算法

排序

常见排序总结

冒泡

  • 基本思想:遍历数组,每次从头开始两两比较。

  • 过程:

    • 第一趟从头到尾,两两比较,大的遇到小的进行交换,直到数组结尾;
    • 第二趟从头到数组长度减一(沉底数不去比较),两两比较,大的遇到小的进行交换;
    • ....
private static int[] myBubbleSort(int[] a) {
    for (int i = 0; i < a.length - 1; i++) {
        for (int j = 0; j < a.length - 1 - i; j++) {
            int tmp;
            if (a[j] > a[j + 1]) {
                tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;
            }
        }
    }
    return a;
}
//注意边界情况

选择

基本思想:在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;如此向后遍历

private static int[] myChooseSort(int[]  a) {
    for (int i = 0; i < a.length; i++) {
        //首先假定当前是最小的数
        int minindex = i;
        for (int j = i+1; j < a.length; j++) {
            //如果假设的最小的数大于正在遍历的数则交换
            if(a[minindex] > a[j] ){
                minindex = j;
            }
        } 
        int tmp = a[i];
        a[i] = a[minindex];
        a[minindex] = tmp;
    }
    return a;
}

插入

基本思想:从第一位开始认为第一位已经排好序;滑到第二位和第一位比较,如果第一位大,交换,则认为第一二位已经排好序;滑到第三位和前面比较,如果第二位大,交换,如果第一位小,不交换;....  以此类推直到最后一位。

private static int[] myInsertSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
            // int tmp = arr[j];
            // arr[j] = arr[j + 1];
            // arr[j + 1] = tmp;
            arr[j] = arr[j] ^ arr[j+1];
            arr[j+1] = arr[j] ^ arr[j+1];
            arr[j] = arr[j] ^ arr[j+1];
        }
    }
    return arr;
}

最差  需要从小到大  得到从大到小  O(n^2)     最好  需要从小到大 得到从小到大   O(n)
复杂度一律按最差复杂度

归并

基本思想:主要采用分治(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)策略;先将数组分成左右两大部分,再继续递归实现左右的排序完成,最后从左右数组头部开始同时移动比较,将数据放入新的数组。

    public static void myMergeSort(int[] arr , int L ,int R) {
        if(L==R){
            return ;
        }
        int mid = (L+R)/2;
        myMergeSort(arr, 0, mid);
        myMergeSort(arr, mid+1, R);
        merge(arr, L, mid , R);
    }
    public static void merge(int[] arr, int l, int m, int r) {
		int[] help = new int[r - l + 1];
		int i = 0;
		int p1 = l;
		int p2 = m + 1;
		while (p1 <= m && p2 <= r) {
			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
		}
		while (p1 <= m) {
			help[i++] = arr[p1++];
		}
		while (p2 <= r) {
			help[i++] = arr[p2++];
		}
		for (i = 0; i < help.length; i++) {
			arr[l + i] = help[i];
		}
	}

对数器的概念和使用

  1. 有一个你想要测的方法a,
  2. 实现一个绝对正确但是复杂度不好的方法b,
  3. 实现一个随机样本产生器
  4. 实现比对的方法
  5. 把方法a和方法b比对很多次来验证方法a是否正确。
  6. 如果有一个样本使得比对出错,打印样本分析是哪个方法出错
  7. 当样本数量很多时比对测试依然正确,可以确定方法a已经正确。

 剖析递归行为和递归行为时间复杂度的估算
一个递归行为的例子    master公式的使用
T(N) = a*T(N/b) + O(N^d)
1) log(b,a) > d -> 复杂度为O(N^log(b,a))
2) log(b,a) = d -> 复杂度为O(N^d * logN)
3) log(b,a) < d -> 复杂度为O(N^d)
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值