这两个词是编写算法时需要考虑的,在实际的场景中,可能老板就跟你说他要实现一个什么功能,让你实现一个O(n)的算法,此时我们是这个表情??
一个算法中需要考虑到的有两点,一个是执行的速度,另外一个则是执行占得资源。
距离子来说查询数据库,然后将查到的数据进行排序
我们的实现:先获取所有数据,然后从内存中筛选,选择一个冒泡排序(O(n^2))
路人A的实现:利用查询语句从数据库获取筛选后的数据,选择了快速排序(O(nlogn))
可以明显的比较到路人A使用的算法仅需要占小部分的内存,而我们是把所有数据保存到内存中了。
同样的数据进行排序,路人A的算法随着数据规模的增长趋势是nlogn,而我们的是n^2,那么谁的算法更好已经显而易见
时间复杂度:算法的时间复杂度不是通过时间来衡量,而是通过分析基本操作的次数和输入规模的趋势关系。例如我们的循环次数。比如一个简单的等比求和:
int start=1,n=100;
int sum=0;
for(int i=start;i<=n;i++) //将循环视作整体 执行次数n次
{
sum+=i;
}
//求和公式 只需要执行一次 无论问题规模多大都是常数
sum=(1+n)*n/2;
//这个谁的速度快可想而知吧
常见的时间复杂度有一下几个:
-
常数阶O(1)
-
对数阶O(logN)
-
线性阶O(n)
-
线性对数阶O(nlogN)
-
平方阶O(n²)
-
立方阶O(n³)
-
K次方阶O(n^k)
-
指数阶(2^n)
空间复杂度:空间复杂度衡量程序运行过程中需要额外占据的内存空间大小。
例如求一个数字组的换序 假如字符数组为abcde 要求从第split之前的开始移动到后面
public class HelloWorld {
public static void main(String []args) {
int split = 3;
char[] c=new char[]{'a','b','c','d','e'};
char[] temp=new char[c.length];
System.arraycopy(c, 0, temp, 0,temp.length);
for(int i =0;i<temp.length;i++)
{
if(i<c.length-split) //后面需要串的个数
{
c[i]=temp[i+split];
}
else
{
c[i]=temp[i-(c.length-split)];
}
}
for(int i=0;i<c.length;i++)
{
System.out.println(c[i]);
}
}
}
第一种方法完全的开辟了一个新的数组 规模大小是一致的。所以空间复杂度为O(n)
public class HelloWorld {
public static void main(String []args) {
int split = 3;
char[] c=new char[]{'a','b','c','d','e'};
char temp;
for(int i =0;i<c.length-split;i++) //需要循环的次数
{
temp = c[c.length-1]; //保存当前最后一位 因为会被覆盖
for(int j=c.length-1;j>0;j--) //每次循环都后移一位
{
c[j]=c[j-1];
}
c[0]=temp;
}
for(int i=0;i<c.length;i++)
{
System.out.println(c[i]);
}
}
}
第二个方法只用了一个变量并且固定不变,所以空间复杂度变为O(1),但是时间复杂度却增加了。
在算法的编写中,通常可以二者互换,通过牺牲时间而降低空间使用,或者是通过空间牺牲而降低时间开销。
根据业务场景的需求,肯能会更加偏向一方,而我们这个移位的算法还有更加巧妙的解法,大可以作为一个思考。