算法复杂度主要从时间、空间两个角度评价:
- 时间:假设运行时间固定,统计算法运行的「计算操作的数量」,以代表算法运行所需时间;
 - 空间:统计在最差情况下,算法运行所需使用的「最大空间」
 
常见种类
 根据从小到大排列,常见算法 时间 复杂度主要有:
 O(1) < O(logN) < O(N) < O(NlogN) < O(N2) < O(2N) < O(N!)
 
 O(1):
 1)运行次数与N大小呈常数关系:
int algorithm(int N) {
    int a = 1;
    int b = 2;
    int x = a * b + N;
    return 1;
}
 
2)以下代码,无论 a 取多大,都与输入数据大小 N 无关:
int algorithm(int N) {
    int count = 0;
    int a = 10000;
    for (int i = 0; i < a; i++) {
        count++;
    }
    return count;
}
 
O(N):
1)阶乘(N !=1×2×3×…×N):
int algorithm(int N){
    if(N==2)
    	return 3;
    else
    	return algorithm(N-1)*4;
}
 
2)对于以下代码,虽然是两层循环,但第二层与 N大小无关,因此整体仍与 N呈线性关系:
int algorithm(int N) {
    int count = 0;
    int a = 10000;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < a; j++) {
            count++;
        }
    }
    return count;
}
 
O(N2):
1)两层循环相互独立,都与 N 呈线性关系:
int algorithm(int N) {
    int count = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            count++;
        }
    }
    return count;
}
 
2)冒泡排序(冒泡排序的总体时间复杂度为 O(N2))
 算法思路:
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
 - 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
 - 针对所有的元素重复以上的步骤,除了最后一个;
 
代码实现:
int[] bubbleSort(int[] nums) {
    int N = nums.length;
    for (int i = 0; i < N - 1; i++) {
        for (int j = 0; j < N - 1 - i; j++) {
            if (nums[j] > nums[j + 1]) {
            //交换数据
                int tmp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = tmp;
            }
        }
    }
    return nums;
}
 
O(2N):
 算法中,指数阶常出现于递归,代码如下:
int algorithm(int N) {
    if (N <= 0) 
        return 1;
    int count_1 = algorithm(N - 1);
    int count_2 = algorithm(N - 1);
    return count_1 + count_2;
}
 
O(N!) :
 阶乘阶对应数学上常见的 “全排列” 。即给定 N 个互不重复的元素,求其所有可能的排列方案,则方案数量为:N (N - 1) × (N - 2) × … × 2 × 1 =N !
 阶乘常使用递归实现,算法原理:第一层分裂出 N个,第二层分裂出 N - 1个,…… ,直至到第 N 层时终止并回溯。
int algorithm(int N) {
    if (N <= 0) return 1;    
        int count = 0;    
    for (int i = 0; i < N; i++) {        
        count += algorithm(N - 1);    
    }    
    return count;
}
 
O(logN) :
 对数阶与指数阶相反,指数阶为 “每轮分裂出两倍的情况” ,而对数阶是 “每轮排除一半的情况” 。对数阶常出现于「二分法」、「分治」等算法中,体现着 “一分为二” 或 “一分为多” 的算法思想。
设循环次数为 m ,则输入数据大小 N 与 2 m呈线性关系,两边同时取 log2对数,则得到循环次数 m与 log2N呈线性关系,即时间复杂度为 O(logN)。
int algorithm(int N) {
    int count = 0;
    float i = N;
    while (i > 1) {
        i = i / 2;
        count++;
    }
    return count;
}
 











