为何LeetCode代码总是比别人花费时间多?(关于list、set等时间复杂度)

做了不少LeetCode题了,发现总是时间花费多,当然一部分原因肯定跟服务器负载有关,但是还有一个重要原因:

不了解list、set等相关操作的时间复杂度!

去面试时也写了垃圾代码,别人一问Insert复杂度多少?你这个代码复杂度是O(n)吗?一下原形毕露。

比如,定义了一个list,使用insert操作时间复杂度为O(n),虽然显得代码简单,但是实际上耗费时间很多

def wrong(self,listIn):
    # 错误示范,O(n)
    listIn.insert(len(listIn)+1,"abc")

def right(self,listIn):
    # O(1)的正确方法
    listIn.append("abc")

这个实例不好,不能说明问题,谁能用append去用insert啊,只是想说复杂度很不一样,有时候同一个问题,换一种思路(或者说改变部分数据结构)时间消耗迅速减少!后文给一个好点的例子


总结下常用的时间复杂度:

listO(n)pop(i),insert(i,item),contains (in),reverse()
O(1)pop(),append(item)

单独拿一行来说明,在执行in操作时:

如:if "a" in list1: #判断"a"是否在list1里,复杂度O(n)

       if "a" in set1:#判断“a"是否在set1中,复杂度O(1)

in操作在list中复杂度线性,在set和dict数据结构中复杂度为O(1),所以如果发现list操作时代码效率低,不妨改成set,会快很多

比如pop(-1)和pop()在运行是一致的,但是pop(i)的最坏情况是O(n)所以归为O(n)

特别地,sort()方法是O(n log n)


来一道具体的题体验一下,LeetCode第150题--根据逆波兰表示法,求表达式的值。有效的运算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

  • 整数除法只保留整数部分。
  • 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9

示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6

示例 3:

输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

简单点说,我们平常做的是中序表达,比如1+2,符号在中间,换成后序表达就是逆波兰,12+

以下是代码,后序表达很简单,不说了。主要是我的思路是在原list堆栈上进行修改,别人是新建一个栈进行存取,方法出现了差异,主要在我的代码需要使用pop(i),而别人的只需要pop()+append(),就出现时间复杂度上的差异,虽然这道题提交时时间不会差异太大,但如果测试集很大的话就会出现很大差异了!

# 我做的
def evalRPN(self, tokens):
	stack = tokens
	i = 0
	while i < len(stack):
		if stack[i] == '+':
			stack [i-2] = int(stack[i-2]) + int(stack[i-1])
			stack.pop(i-1)  #多次Pop(i)操作,时间复杂度高
			stack.pop(i-1)
			i = i-2
		elif stack[i] == '-':
			stack[i - 2] = int(stack[i - 2]) - int(stack[i - 1])
			stack.pop(i - 1)
			stack.pop(i - 1)
			i = i - 2
		elif stack[i] == '*':
			stack[i - 2] = int(stack[i - 2]) * int(stack[i - 1])
			stack.pop(i - 1)
			stack.pop(i-1)
			i = i - 2
		elif stack[i] == '/':
			stack[i - 2] = int(int(stack[i - 2]) / int(stack[i - 1]))
			stack.pop(i - 1)
			stack.pop(i-1)
			i = i - 2
		else:
			i+=1
	return stack[0]
# 别人的
stack = []
for i in tokens:
	try:
		i = int(i)
	except:
		# print("--",stack)
		s1 = stack.pop()    #稍微改变了下思路,就只使用pop()了
		s2 = stack.pop()
		if i == "*":a = s1*s2
		elif i == "/":a = int(s2/s1)
		elif i == "+":a = s1+s2
		elif i == "-":a = s2-s1
		stack.append(a)
	else:
		stack.append(i)
return int(stack[0])

仅以此文警醒多用pop,append少用insert,如果涉及到in,不妨转换为set

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值