算法

175 阅读1分钟

什么是算法

  1. 有限性 (某些局限条件)
  2. 确定性 (不会产生二义性)
  3. 可行性
  4. 输入
  5. 输出

线性查找法

public static <E> int search(E[] data, E target) {
	for (int i = 0; i < data.length; i++) {
    	if (data[i].equals(target)) {
        	return i;
        }
    }
    return -1;
}

循环不变量

在循环过程中保持不变的逻辑, 即 -> data[0...i-1]中没有找到目标

for (int i = 0; i < data.length; i++) {
		/*
			循环体: 维持循环不变量
        
        	*/
    	if (data[i].equals(target)) {
        	return i;
        }
    }

复杂度分析:表示算法的性能

public static <E> int search (E[] data, E target) {//通常看最差的情况来判断一个算法的复杂度
	for  (int i = 0; i < data.length; i++) {   //算法运行的上界
    	if (data[i].equals(target))  { 		   //n = data.length
        	retuern i;
        }
    }
    return -1;
}						    //O(n)

假如算法需要运行 T = c1 * n + c2 行逻辑代码
则该算法的复杂度为 O(n)     常数不重要
			 复杂度描述的是随着数据规模n的增大,
            		 算法性能的变化趋势
T1 = 1000nT2 = 2n^2
复杂度O(n)O(n2)
对比O(n) < O(n2)
一定存在某一临界点n0,当n >= n0, T1 < T2

常见算法复杂度

一个n*n的二维数组, 明确 n 所代表的含义

//这是一个复杂度为O(n^2)的算法, n 代表二维数组的某一个维度为n
for (int i = 0; i < n; i++) {
	for(int j = 0; j < n; j++) {
    	//循环到A[i][j]
    }
}
//遍历一个a*a的二维数组, 复杂度为O(n)的算法, n代表二维数组中总元素数量
for(int x = 0; x < a; x++) {
	for(int y = 0; y <a; y++) {
    	//循环到A[x][y]
    }
}

 数字n 的二进制位数  
while (n) {  
	n %2//n的二进制中的一位
    n /= 2
}
时间复杂度为O(logn)  (实际为以2为底,n为值的log函数, 但是在复杂度分析中常数不重要,所以认为复杂度为O(logn), 这类算法不关注对数函数中的 底 是多少,统称这类算法的复杂度为logn
被称为对数级别的复杂度)
看一个 算法的复杂度不能简单的去数循环的个数,而应该根据判断的逻辑来定义
数字n 的所有公约数

//该算法复杂度为O(n)
for (int i =0; i <= n; i++) {
	if (n % i == 0) {
    	//i是n的一个约数
    }
}

//另外一个思路是,实际上当 i * i  <= n时,应该已经把 n 的所有公约数都得到了
该算法的时间复杂度为O(√n)
for () {
	if(int i = 0; i * i <= n; i++) {
    	//i和n/i是n的两个公约数
    }
}
长度为n的二进制数字   O(2^n)
长度为n 的数组的所有排序 O(n!)
复杂度 O(n!) > O(2^n),当n>2时, n! > 2^n

数字n 是否是偶数
return n % 2 ==0    //复杂度为O(1)

复杂度排序

O(1) < O(㏒n) < O(√n) < O(n) < O(n* ㏒n) < O(n²) < O(2^n) < O(n!)