参考温文献 代码随想录
一、逆波兰表达式求值
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["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
问题分析:把数字添加到栈中,然后遇到运算符的话,就需要出栈2个元素,第一个出栈的位于运算符的后面,第二个出栈的,位于运算符的前面,特别注意的是,当运算符遇到 / 时,需要注意,如果2个数相乘大于0,则可以正常计算,否则小于零,说明为异号,先算它们的绝对值,然后在添加一个符号。
class Solution(object): def evalRPN(self, tokens): """ :type tokens: List[str] :rtype: int """ stack = [] for c in tokens: if c not in ["+", "-", "/", "*"]: stack.append(c) else: if len(stack) > 1: a = int(stack.pop()) # 获取栈中的最后一个元素 b = int(stack.pop()) # 获取站中的导数第二元素 tmp = 0 if c == "*": tmp = a * b stack.append(tmp) elif c == "+": tmp = a + b stack.append(tmp) elif c == "/": if a * b > 0: stack.append(b // a) else: stack.append(-(abs(b) // abs(a) )) else: tmp = b - a stack.append(tmp) return int(stack[0])
二、滑动窗口最大值
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1 输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
问题分析:
感觉是不是一个窗口为k的大小移动,然后求每个窗口的最大值就行了?结果是超时了,为什么呢?因为一个for循环就是一个n,然后求最大值就是一个k,所以时间复杂度为n * k所以通过不了,那么我们该如何去存储这个最大值呢,数组、栈、队列、优先队列、单调栈、单调队列,乳如果使用的是数组,会超时的,然后使用栈、队列它们只是进入和出口不一样,无法满足我们的要求,使用优先队列(大根堆、小根堆)的话,这样确实能够存储最大值,但是你如在接下来的元素中找到最大的值呢(意思是你如何规定出口和进口规则呢?),然后我本题使用的是单调队列,出口就是保留的最大值(当前窗口),那我们该如何保留当前窗口的最大值呢?这就要考虑到如何进口的规则了?题目要求的是当前窗口的最大值,那么我们把元素入队的时候,判断队尾元素比入队元素要小,那么我们是不是直接可以把队尾元素出队,为什么呢?因为我们要保留会是最大值的元素。
from collections import deque class Solution(object): def maxSlidingWindow(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ d = deque() # 这个只一个单调栈,什么叫做单调队列呢,就是升序要么是降序,这里我们降序,出口维护的是最大值 ans = [] # 结果集 for i in range(k): # 我们先维持前k个元素的最大值 while len(d) != 0 and d[-1] < nums[i]: # 队列不能为空,然后维持d的第一个元素始终为最大值,加进队列里的元素如果比队列末尾的数要打,那么就要移除,因为我们要围护整个队列中可能会是最大的数 d.pop() d.append(nums[i]) ans.append(d[0]) # 收集结果 for i in range(k, len(nums)): # 为什么从k开始循环呢,因为我们上面以及判断了第一窗口的最大值,所以我们要从它的后面一个元素开始移动 while len(d) != 0 and d[-1] < nums[i]: # 队列不能为空,然后维持d的第一个元素始终为最大值, d.pop() if len(d) != 0 and d[0] == nums[i - k]: # 为什么要判断与队列中出口元素相同时才删除呢,因为当i - k 代表的是前k个元素的前一个元素,就被退掉的那个元素,是否和最大值相等,因为收集的是最大值, d.popleft() d.append(nums[i]) ans.append(d[0]) return ans
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 105
k
的取值范围是[1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前
k
个高频元素的集合是唯一的
class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ di = {} for i in nums: if i not in di: di[i] = 0 else: di[i] += 1 sorted_items = sorted(di.items(), key=lambda x: x[1], reverse = True) ans = [i[0] for i in sorted_items[:k]] return ans