java复杂度_01.Java-时间复杂度

时间复杂度

1、时间频度

时间复杂度通常是衡量算法的优劣的,衡量算法的时间严格来讲是很难衡量的,由于不同的机器性能不用环境都会造成不同的执行时间。算法的执行时间和语句的执行次数成正比,因此通过计算执行测试来推断执行时间。算法中语句执行次数称为语句频度或时间频度,记为T(n),n是问题的规模,T是Time,即时间频度。

2、时间复杂度

n不断变化时,T(n)也在不断变化,为了考察两者变化时呈现什么规律,可以使用时间复杂度来计算。

通常操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),存在一个正常数c使得f(n) * c >= T(n)恒成立。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。

简言之,只要计算一下语句的执行次数和n之间的关就可以了,去除系数部分,低阶项目部分,就是时间复杂度的值了。

3、 时间复杂度的计算

3.1 给定任意长度数组,读取数组第一个元素的值

无论数组长度n为多少,代码执行一次。因此,时间复杂度为O(1)。

//无论数组的长度n为多少,

public void firstEle(int[] arr){

return arr[0] ;//代码只执行一次。

}

3.2 循环n次,输出hello world

随着n的增大,打印函数逐渐增多。打印代码执行的次数是n,因此时间复杂度为O(n)。

for(int i = 0 ; i < n ; i ++){

//执行一次。

System.out.println("hello world") ;

}

3.3 打印99乘法表

打印99正方乘法表,打印语句输出9 * 9 = 81次。

打印语句执行次数:$$n * n = n2$$,因此时间复杂度是$$O(n2)$$

for(int i = 1 ; i <= n ; i ++){

for(int j = 1 ; j <= n ; j ++){

//打印语句的执行次数n * n次。

System.out.print(j + " x " + i + "=" + (i * j));

}

}

3.4 打印正三角的99乘法表

正三角形状的99表格打印语句的执行次数为:

\[1 + 2 + 3 + ... + n = (n + 1) \dfrac{n}{2} = \dfrac{n^2}{2} + \dfrac{n}{2}

\]

去掉系数部分和低阶部分,时间复杂度为仍然为$$O(n^2)$$

for(int i = 1 ; i <= n ; i ++){

for(int j = 1 ; j <= i ; j ++){

//打印语句的执行次数n * n次。

System.out.print(j + " x " + i + "=" + (i * j));

}

}

3.5 冒泡排序

冒泡排序是经典的排序算法是每次比较相邻的两个元素进行对调,进行多轮,直到数列有序。

xpc_java_pro_001.png

对于5个元素的冒泡排序来说,共需要比较4 + 3 + 2 + 1次比较。因此时间复杂度为:

\[n - 1 + n - 2 + ... 1 = \dfrac{(n-1)}{2}n = \dfrac{n^2}{2} - \dfrac{n}{2}

\]

因此时间复杂度为:$$O(n^2)$$,这是冒泡排序最坏的情况下的时间复杂度。

int[] arr = ... ;

//外层比较n-1次

for(int i = 0 ; i < arr.length - 1 ; i ++){

//比较n-1-i次

for(int j = 0 ; j < arr.length -1 - i ; j ++){

int temp = arr[j] ;

if(arr[j] > arr[j + 1]){

arr[j] = arr[j + 1] ;

arr[j + 1] = temp ;

}

}

}

冒泡排序可以进行优化,在最好的情况下,复杂度为O(n),思路如下:

设置标志位flag=1,表示整个数列已经有序,就不需要再排序了,在里层循环中,如果发现没有进行过数据交换,就说明数列已经有序。

在最好情况下,就是数列本身已经有序,只需要执行外层的n-1次循环即可,因此复杂度为O(n)。

int[] arr = ... ;

//外层比较n-1次

for(int i = 0 ; i < arr.length - 1 ; i ++){

boolean flag = true ;

//比较n-1-i次

for(int j = 0 ; j < arr.length -1 - i ; j ++){

int temp = arr[j] ;

if(arr[j] > arr[j + 1]){

//发生交换,就设置标志位为false,即数列无序。

flag = false ;

arr[j] = arr[j + 1] ;

arr[j + 1] = temp ;

}

}

//判断如果是数列有序,则终止循环。

if(flag){

break ;

}

}

3.6 折半查找

折半查找也叫二分查找,是高效的查找方式,前提条件是数列需要时有序数列。图例如下:

xpc_java_pro_002.png

xpc_java_pro_003.png

代码如下:

//有序数组

int[] arr = ... ;

int min = arr[0] ;

int max = arr[0] ;

int mid = arr[arr.length/2] ;

//目标元素

int targ = 3 ;

for(int min = 0 , max = arr.length - 1 ; min <= max ; ){

int mid = (min + max) / 2 ;

//命中了

if(arr[mid] == targ){

return mid ;

}

//落在右侧范围

else if(arr[mid] < targ){

min = mid + 1 ;

}

//落在左侧范围

else{

max = mid - 1 ;

}

}

折半查找的最坏时间复杂度为:以2为底,n的对数。

\[O(log_2 n )

\]

3.7 hashmap

哈希map是java中最重要的集合之一,设计非常巧妙,使用通过数组+链表方式组合实现,哈希的目的是让对象在空间内尽可能分散。那么HashMap的时间复杂度是多少呢?

如果hashmap的每个桶内的元素个数最多不会超过一个常数C,当增加元素时,不断增加桶的数量,而保证每个桶内的元素量固定,因此就可以保证最快的查询速度,则时间复杂度就是$$O(C*n^2)$$,去掉系数部分就是

\[ O(n^0) = O(1)

\]

如果在最坏的情况下就是所有元素进入同一个桶,导致给桶内的链条非常长,则检索数据时,时间复杂度为:

\[ O(n)

\]

3.8 矩阵的乘积

矩阵我们按照阶数为n的两个方阵进行计算,矩阵的乘法运算法则为:

\[\left|

\begin{matrix}

a_{11} & a_{12} \\

a_{21} & a_{22}

\end{matrix}

\right|

*

\left|

\begin{matrix}

b_{11} & b_{12} \\

b_{21} & b_{22}

\end{matrix}

\right|

=

\left|

\begin{matrix}

a_{11} * b_{11}+a_{12} *b_{21} &a_{11} * b_{12}+a_{12} *b_{22} \\

a_{21} * b_{11}+a_{22} *b_{21} &a_{21} * b_{12}+a_{22} *b_{22}

\end{matrix}

\right|

\]

例如:

\[\left|

\begin{matrix}

0 & 1 \\

1 & 1 \\

\end{matrix}

\right|

*

\left|

\begin{matrix}

1 & 2 \\

3 & 4 \\

\end{matrix}

\right|

=

\left|

\begin{matrix}

0*1+1*3 & 0*2+1*4 \\

1*1+1*3 & 1*2+1*4 \\

\end{matrix}

\right|

=

\left|

\begin{matrix}

3 &4 \\

4 & 6 \\

\end{matrix}

\right|

\]

方阵乘法的代码如下:

//方阵使用二位数组表示

int[][] a = ... ;

int[][] b = ... ;

//结果矩阵

int[][] r = ... ;

//[思路]

//从结果矩阵出发,结果矩阵也是一个阶数为n的方阵,但是每个对应的元素

//循环n次计算累加和得到。

//循环行数

for(int i = 0 ; i < a.length ; i ++){

//循环列的个数,这里仍然是m.length是因为方阵

for(int j = 0 ; j < b.length ; j ++){

for(int k = 0 ; k < a.length ; k ++){

r[i][j] = r[i][j] + a[i][k] * b[k][j] ;

}

}

}

方阵的矩阵乘法的计算次数为$$n3$$,因此时间复杂度为$$O(n3)$$。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值