LeetCode(No239)
任务要求:
学习队列思想及堆排序思想,并完成leetcode上的“返回滑动窗口中的最大值(239)”
加粗样式
关于队列,恰好我最近在看的《用python解决数据结构和算法问题》到了这一章节的内容,于是也对队列有了初步的了解,仅限于队列和双端队列。
双端队列与队列不同的时,队列仅可以首进尾出,双端队列首尾都可以添加或删除元素。同时,在python中,队列多用list列表这一数据存储结构来实现。
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
示例:
输入: 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
思路:既然是学习队列,那就肯定用队列的思想来解决。
先用for语句遍历nums数组,同时进行队列操作,队列规则如下:
将遍历到的元素nums[i]与队列尾端数据比较,当nums[i]小于队列尾端最后一个数的时候,nums[i]添加到队列中去,否则就将队列尾端最后一个数删去,直到nums[i]小于队列尾数为止。
这解决了求出当前窗口最大值的问题,那么,如何实现“滑动”呢?
将遍历到的位置与k-1对比,如果队列头超出滑动窗口范围,则删除队列头。
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
ans = []
deque = []
for i in range(len(nums)):
while len(deque) > 0 and nums[deque[-1]] < nums[i]:
deque.pop()
deque.append(i)
if i >= deque[0] + k:
deque.pop(0)
if i >= k - 1:
ans.append(nums[deque[0]])
return ans
结果:
xiaoyu
关于哈希和链表的学习总结:
对于哈希,简而言之,在python中就是字典的实现。字典中“键值”的定义与哈希表中索引地址与映射值的对应一样。其核心是理解所谓的哈希函数(散列函数)。即如何构建一个确定的映射,它能把关键字映射到一个唯一的存储位置。这种映射应该是我们可以进行计算的。已知关键字,我们应该能算出其地址;反之,已知地址,我们可以检索到对应的关键字。一旦建立起这种关系,那么给定关键字,就能直接利用这个映射(即所谓的哈希函数)直接算出其地址并寻址。这可大大缩减确定关键字存储位置所花的时间。
而链表就不一样了,哈希表是一种数据结构,而链表则是数据存储结构。也就是说,哈希表可以用链表来实现。链表是具备很多“节点”(这里的节点是将每个地址具象化了),每个“节点”都能储存数据,而“链”就意味着连通,每个“节点”都存在一个指针指向了下一个节点。链接域next用来存放下一个节点的位置。
在我看来,链表和字典同为数据存储结构,其不同之处就在于,链表是可以不连续的,其依靠指针的变化可以实现数据地址的变化,相比较灵活一些。而字典可以通过键来寻找值,相比目标更明确。
字典:需要进行频繁的搜索时优先考虑;
链表:对象数量是动态的且搜索不是优先选项时,需要经常增减节点的情况优先考虑;