时间复杂度和空间复杂度

本文探讨了时间复杂度和空间复杂度之间的关系,通过数组和链表的例子解释了它们的区别。在代码优化时,需要根据具体需求平衡二者。文中还介绍了两道面试题的解法,一个是通过开辟额外空间快速判断数组中重复数字,另一个是在不额外开辟空间的情况下解决相同问题。优化时间效率通常涉及建立哈希表,而优化空间效率则需减少内存开销并利用原始数据空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间复杂度和空间复杂度是对立的关系,也就是只能保证其一,以空间换时间或者以时间换空间。
比如数组和链表就是很好的例子,数组在使用前需要开辟足够大的空间,防止数据量大的情况,空间效率低,但数组开辟的是内存中一块连续的空间,在取数据时,只要按顺序依次往后取即可,时间效率高。
而,链表不是在创建的时候一次性开辟内存的,而是每添加一个节点,开辟一次内存,没有空闲的内存,空间效率高,但由于链表开辟的内存不是连续的,它是依靠指针去寻下一个节点的,所以取数据时,寻址的时间效率低。

在优化代码的时候,我们要看需要改进哪个方面,是内存有限制,还是时间有限制,以一换一。
面试题3:找出数组中重复的数。
描述:给定一个长度为n的数组,数组中的数全部都在0~n-1。输出重复的数字。
解法1:(扫描到每个数时,以O(1)的时间判断它是否重复)

public class Main
{
 	public static void main(String args[])
 	{
  		int[] a = {2,3,1,0,2,5,3};
  		int[] read = new int[a.length]; //开辟了一个同等大小的数组
  		for(int i=0;i<a.length;i++)
  		{
   			int index = a[i];
   			if(read[index]==0) read[index]++;
   			else if(read[index]==1) System.out.print(index+" ");
  		}
 	}
}

上面的代码开辟了同等大小的数组read[],空间效率为O(n)
但没扫描到一个数,如果read[]中以该数为索引的位置==1,说明该数是重复的,输出,以时间效率O(1)即可对扫描到的数进行判断。

如果本题限制不让开辟新内存,只能在原数组上操作,也就是空间效率为O(1)的解法
解法2:
n个不大于n的数,排序后若没有重复,那数组第x为一定是x。
那么可以这样操作,从索引0开始扫描数组,若索引为x的位置的元素不是x,而是y,那么就把y换到索引y的位置(放到它本来改在的位置),但若索引y上本来就是y(在换之前判断),那么本次扫描到的y一定是重复的多余的,就把它输出。

public class Main
{
 	public static void main(String args[])
 	{
  		int[] a = {2,3,1,0,2,5,3};
  		int x = 0;
  		while(x<a.length)
  		{
   			int index = a[x];
   			if(index!=x) //本应该x==a[x]
   			{
    				if(a[index]==index)
    				{
     					System.out.print(a[x]+" ");
     					x++;
    				}
    				else
    				{
     					int t = a[x];
     					a[x] = a[index];
     					a[index] = t;  
    				}
   			}
   			else x++; //x==a[x],跳过
  		}
 	}
}

对于一般改进时间效率的,都是选择开辟内存,建立哈希表等,把搜索过的状态,过去的情况记录下来,下次再搜到相同情况,就可以直接从表中读取,以节省时间。对于改进空间效率就需要思考思考了,尽量少开辟空间,尽量在原始数据内存空间上操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值