代码随想录系列
上题
一、第一题
给你一个整数数组 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
"""
思路
- 单调栈。。。。
- 遍历列表nums,未达到窗口长度时,不断入队出队,保留最大值,存放在re=[]里,所以,当i==k时,re里仅有一个元素
- re存储的是当前窗口的元素,并且从左到右递减,窗口最大值直接取re[0]即可
- 所以每入队一个元素,nums[i],需要把re里小于nums[i]的元素全部删除,最终re[i]一定是整个窗口里的最小值
- re[0] == nums[i],则re[0]出队
- 窗口移动时,如果re里存在窗口最左边的元素需要把该元素从re移除
# 窗口移动一次移除num[i-1],若num[i-1]在re内存在,则一定是re内当前的最大值,因为num[i-1]已经经过三次轮换,re最多存放窗口长度数量的元素
if re[0] == nums[i - k]:
re.pop(0)
代码
class Solution:
"""
给你一个整数数组 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
"""
def maxSlidingWindow(self, nums, k):
if not nums and k == 0:
return
re = []
result = []
# 窗口未形成
for i in range(k):
# 单调栈,re内小于nums[i]的均删除,再把nums[i]加入队列尾,保证从左到右递减,最大值则直接从队列头取出
while re and re[-1] < nums[i]:
re.pop()
re.append(nums[i])
result.append(re[0])
# 窗口已形成
for i in range(k, len(nums)):
# 窗口移动一次移除num[i-1],若num[i-1]在re内存在,则一定是re内当前的最大值,因为num[i-1]已经经过三次轮换,re最多存放窗口长度数量的元素
if re[0] == nums[i - k]:
re.pop(0)
while re and re[-1] < nums[i]:
re.pop()
re.append(nums[i])
result.append(re[0])
return result
if __name__ == '__main__':
test = Solution()
nums = [[1, 3, -1, -3, 5, 3, 6, 7], [1]]
k = [3, 1]
for i in range(len(nums)):
print(test.maxSlidingWindow(nums[i], k[i]))
二、第二题
给你一个整数数组 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 个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
思路
对堆的使用还是很陌生的,当了一把调库高手。。。。好好复习二叉树
- 用字典统计每个元素的数量
- 遍历字典,然后分成k堆,当堆的数量=k+1时,则把数量最小的对弹出,遍历结束剩下的k个堆即为所求
代码
import heapq
class Solution:
"""
给你一个整数数组 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 个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
"""
def topKFrequent(self, nums, k):
re = {}
for i in nums:
re[i] = re.get(i, 0) + 1
por = []
result = []
for key,valus in re.items():
heapq.heappush(por, (valus, key))
if len(por) > k:
heapq.heappop(por)
for i in por:
result.append(i[1])
return result
if __name__ == '__main__':
nums = [[1, 1, 1, 2, 2, 3], [1]]
k = [2, 1]
test = Solution()
for i in range(len(nums)):
print(test.topKFrequent(nums[i], k[i]))
总结
现在你的气质里,藏着你写过的BUG,挠过的头和掉过的头发