JAVA数据结构与算法(时间复杂度分析、空间复杂度分析)

个人简介

  • 大家好,我是翰慧腾。一名正在努力学JAVA的大一小白,本文章为初学的笔记,希望各位多多指教。💙
  • 欢迎点赞+收藏+留言💜
  • 一个人想要创业,先要学会打工🧡

算法的时间复杂度分析:

1.事后分析估算方法:就是用我们之前学的计时方法来计算程序执行所花费的时间。

程序输出100个数所花费是时间:

public class Demo_ {
	public static void main(String[] args) {
		long start=System.currentTimeMillis();
		for(int i=0;i<100;i++) {
			System.out.println(i);
		}
		long end=System.currentTimeMillis();
		System.out.println(end-start);//得出程序输出100个数所花费的时间
	}
}

2.事前分析估计方法:算法采用的策略和方案、编译产生的代码质量、问题的输入规模、机器执行指令的速度都会影响程序运行的时间。其中我们可以干预的是算法的策略方案和问题的输入规模,其余两个是我们程序员无法控制的。此时的时间复杂度就是一个执行次数与输入规模的函数,而函数类型就与实际情况有关了。

结论:随着输入规模的增加,算法的常数操作可以忽略不计 

结论:随着输入规模的增大,与最高次项相乘的常数可以忽略 

结论:最高次项的指数大的,随着n的增长,结构变化非常快。(类似高中学的指数型函数,爆炸性增长函数)。

结论:算法函数中n最高次幂越小,算法效率越高。 

在算法函数中,跟在后面的常数通常是可以忽略的,最高次幂的常数因子可以忽略;算法函数中最高次幂越小,算法效率越高。 

算法时间复杂度的表示方法:大O记法

定义:在执行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随着n的变化情况并确定T(n)的量级,算法的时间复杂度就是算法的时间量度,记作:T(n)=O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间杂度,其中f(n)是问题规模n的某个函数。执行次数=执行时间

大O记法的规则:1.用常数1取代运行时间中的所有加法常数

                                2.在修改后的运行次数中,只保留高阶项

                                3.如果最高阶项存在,且常数因子不为1,则去除与这个项相乘的常数

常见的大O阶:

  • 线性阶:
public class Demo_ {
	public static void main(String[] args) {
		int n=100;
		for(int i=0;i<=n;i++) {
			System.out.println(i);
		}
	}
}

上述循环体中的代码需要执行n次,循环的时间复杂度为O(n)

  • 平方阶:
public class Demo_ {
	public static void main(String[] args) {
		int n=100;
		int sum=0;
		for(int i=0;i<=n;i++) {
			for(int j=0;j<=n;j++) {
				sum+=i;
			}
		}
		System.out.println(sum);
	}
}

在程序中,外层循环执行一次,内层循环就要执行n次。内部循环体就要执行n*n次。那么这段代码的时间复杂度是O(n^2).立方阶同上

  • 对数阶:
public class Demo_ {
public static void main(String[] args) {
	int n=100;
	int i=1;
	while(i<=100) {
		i*=2;
	}

i每次进到循环体内都会乘以2,假设循环体执行了x次,则就有x个2相乘。由于是2^x=n。x=log(2)n。这个循环的时间复杂度为O(log(n))。

常数阶:常数阶通常是不涉及到循环的,操作次数与n无关。通常时间复杂度记为O(1)。

上述的复杂程度从低到高为:O(1)<O(log n)<O(n)<O(n log n)<O(n^2)<O(n^3).越复杂耗费的时间就越高。

函数调用的时间复杂度分析

public class Demo_ {
public static void main(String[] args) {
	int n=100;
	for(int i=0;i<n;i++) {
		show(i);
	}
	
}
 static void show(int i) {
	// TODO 自动生成的方法存根
	System.out.println(i);
}
}

在main方法内,有一个for循环,循环体内调用了show方法,由于show方法只有一行代码,所以show方法的时间复杂度为O(1),那么main方法的时间复杂度就是O(n)。

public class Demo_ {
public static void main(String[] args) {
	int n=100;
	for(int i=0;i<n;i++) {
		show(i);
	}
	
}
 static void show(int i) {
	// TODO 自动生成的方法存根
	for(int j=0;j<i;j++) {
		System.out.println(i);
	}
}
}

在main方法内,有一个for循环,循环体内调用了show方法,而show方法是一个for循环,所以show方法的时间复杂度为O(n),那么main方法的时间复杂度就是O(n^2)。

public class Demo_ {
public static void main(String[] args) {
	int n=100;
	show(n);
	for(int i=0;i<n;i++) {
		show(i);
	}
	for(int i=0;i<n;i++) {
		for(int j=0;j<n;j++) {
			System.out.println(j);
		}
	}
}
 static void show(int i) {
	// TODO 自动生成的方法存根
	for(int j=0;j<i;j++) {
		System.out.println(i);
	}
}
}

在show方法中,有一个for循环,所以show方法的时间复杂度为O(n)。在main方法中,show(n)这行代码执行的次数为n;for循环体内调用了show方法,所以其执行次数为n^2,同样第二个for循环也执行次数为n^2,那么main方法总共执行次数为2n^2+n。根据该记法的规则,最终main方法的时间复杂度为O(n^2)。

空间复杂度分析

Java中常用内存占用

  •  计算机访问内存的方式都是一次一个字节
  • 一个引用需要8个字节表示,eg:Date date=new Date();则date这个变量需要占用8个字节来表示
  • 创建一个对象,比如说new Date(),除了Date对象内部存储的数据,该对象本身也有内存开销,每个对象的自身开销是16字节,用来保存头信息
  • 一般内存的使用,如果不够8个字节,都会自动填充为8个字节。意思就是如果你创建了一个对象需要20字节,但由于不是以8位为单位,会自动填充为24字节。
    • Java中数组被限定为对象,他们一般会因为记录长度而需要额外的内存,一个原始数据类型和数组一般需要24字节的头信息(16个是自己对象的开销,4字节用于保存长度以及4个填充字节)再加上需要保存信息所需要内存

案例:对指定的数组元素进行反转

解法一;

public static int[]  reverse(int []arr) {
	int n=arr.length;//申请4个字节
	int temp;//申请4个字节
	for(int start=0,end=n-1;start<=end;start++,end--) {
		temp=arr[start];
		arr[start]=arr[end];
		arr[end]=temp;
	}
	return arr;
}

该解法与数组长度无关,都是占用相同的内存。空间复杂度记为:O(1)

解法二:

public static int[]  reverse(int []arr) {
	int n=arr.length;//申请4个字节
	int[] temp=new int[n];//申请n*4个字节+数组自身头信息开销24字节
	for(int i=n-1;i>=0;i--) {
		temp[n-i-1]=arr[i];
	
	}
	return temp;
}

空间复杂度:O(4n+28),经过规则后可记为O(n)。

声明:以上图片来源于黑马程序员,内容为黑马程序员网课笔记

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨四点半sec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值