题目:
-
150. 逆波兰表达式求值
-
注意:The integer division should truncate toward zero, which means losing its fractional part. For example, 8.345 would be truncated to 8, and -2.7335 would be truncated to -2.
-
对于truncate to zero的处理,python3和python2是有区别的!
- int(a/b)在python3中是可以的,也可以用math.trunc(a/b),但在python2不可以。
-
当需要container的时候,总是习惯直接用数组,缺少对于复杂度的考量,尤其是直接ac之后更不会继续思考。这里就是set更快!
-
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for token in tokens:
if token not in {'+', '-', '*', '/'}: # O(1) 查找
stack.append(int(token))
else:
b = stack.pop()
a = stack.pop()
if token == '+':
stack.append(a+b)
elif token == '-':
stack.append(a-b)
elif token == '*':
stack.append(a*b)
elif token == '/':
stack.append(int(a/b))
return stack[-1]
我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。
例如:4 + 13 / 5,这就是中缀表达式,计算机从左到右去扫描的话,扫到13,还要判断13后面是什么运算法,还要比较一下优先级,然后13还和后面的5做运算,做完运算之后,还要向前回退到 4 的位置,继续做加法,你说麻不麻烦!
那么将中缀表达式,转化为后缀表达式之后:["4", "13", "5", "/", "+"] ,就不一样了,计算机可以利用栈里顺序处理,不需要考虑优先级了。也不用回退了, 所以后缀表达式对计算机来说是非常友好的。
-
239. 滑动窗口最大值(hard)
-
第一反应就是暴力解法,直接for循环,但是超时,O(n*k).
-
考虑O(n)解法:通过视频讲解知道需要用单调递减队列(monotonically decreasing queue)
-
- Q1: 为什么用队列而不是栈?
- S:因为需要在beginning的位置进行增删操作,队列可以做到O(1).
- Q2: 如下题解为什么使用deque而不是list来实现队列?
- S:在day11 blog中有总结。
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
# time O(n) + space O(k)
ans = []
queue = collections.deque() #this queue is to store index not value
left = right = 0 #tell where the current window is
while right < len(nums):
#the below while loop is
#to make sure no smaller values(compare to nums[right]) in the queue,
#to pop smaller values
while len(queue) != 0 and nums[queue[-1]] < nums[right]:
queue.pop()
queue.append(right)
#remove left value from the window
if left > queue[0]:
queue.popleft()
if right+1 >= k:
ans.append(nums[queue[0]])
left += 1
right += 1
return ans
-
347.前 K 个高频元素(medium)
-
题解1:
-
第一反应是用dict,也就是hashmap,通过出现的次数来找出对应的前k个key(也就是nums里的值)
-
trick: Get key by value in dictionary
-
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
temp = {}
for num in nums:
if num not in temp:
temp[num] = 1
else:
temp[num] += 1
ans = []
for i in range(k):
max_key_by_value = list(temp.keys())[list(temp.values()).index(max(temp.values()))]
temp[max_key_by_value] = 0
ans.append(max_key_by_value)
return ans
复杂度分析:(to be finished...)
- max() complexity: O(n)
- .index() complexity: O(n)
- get slice: O(k), where k is the length of slice. So it is 1 in this case.
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = {}
freq = [[] for i in range(len(nums) + 1)]
for num in nums:
if num not in count:
count[num] = 1
else:
count[num] += 1
print(count)
print(count.items())
for num, c in count.items():
freq[c].append(num)
print(freq)
ans = []
for i in range(len(freq)-1, 0, -1):
for num in freq[i]:
ans.append(num)
if len(ans) == k:
return ans
-
题解3: O(nlogk) + O(n) (还没搞懂,弄懂了再贴到下面。。。)
总结:
-
单调队列的思路还需仔细琢磨
-
大小顶堆的概念不熟悉,需要单独学习一下。