leetcode_480. 滑动窗口中位数

举报
悲恋花丶无心之人 发表于 2021/02/05 00:39:48 2021/02/05
【摘要】 目录 一、题目内容 二、解题思路 三、代码 一、题目内容 中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。 例如: [2,3,4],中位数是 3 [2,3],中位数是 (2 + 3) / 2 = 2.5 给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 ...

目录

一、题目内容

二、解题思路

三、代码


一、题目内容

中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。

例如:

[2,3,4],中位数是 3
[2,3],中位数是 (2 + 3) / 2 = 2.5
给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

示例:

给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。

窗口位置                      中位数
---------------               -----
[1  3  -1] -3  5  3  6  7       1
 1 [3  -1  -3] 5  3  6  7      -1
 1  3 [-1  -3  5] 3  6  7      -1
 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]      6
 因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]。

提示:

你可以假设 k 始终有效,即:k 始终小于输入的非空数组的元素个数。
与真实值误差在 10 ^ -5 以内的答案将被视作正确答案。

二、解题思路

1.暴力法:每次取k个数,排序后得到中位数;

2.二分插入排序和二分查找法,维护一个长度为k的滑动窗口,每次移动都需要进行二分插入排序算法插入右端的元素,然后利用二分查找将左端的数pop出去,然后得到中位数。可以利用bisect求解更快。

三、代码


  
  1. class Solution:
  2. def medianSlidingWindow(self, nums: list, k: int) -> list:
  3. ans = []
  4. for i in range(len(nums) - k + 1):
  5. tmp = sorted(nums[i:i+k])
  6. if k % 2 == 0:
  7. center = (tmp[k // 2] + tmp[k // 2 - 1]) / 2
  8. else:
  9. center = tmp[k // 2]
  10. ans.append(center)
  11. return ans
  12. def medianSlidingWindow1(self, nums, k: int):
  13. def find_index_in_list(a, x, left=0, right=None):
  14. if right is None:
  15. right = len(a)
  16. while left < right:
  17. mid = (left + right) // 2
  18. if a[mid] < x:
  19. left = mid + 1
  20. else:
  21. right = mid
  22. return left
  23. def insert_x_in_list(a, x, left=0, right=None):
  24. if right is None:
  25. right = len(a)
  26. while left < right:
  27. mid = (left + right) // 2
  28. if a[mid] < x:
  29. left = mid + 1
  30. else:
  31. right = mid
  32. a.append(0)
  33. if len(a) == 1:
  34. a[0] = x
  35. else:
  36. i = len(a) - 2
  37. if i >= left:
  38. a[left + 1:i + 2] = a[left:i + 1]
  39. a[left] = x
  40. ans = []
  41. tmp = []
  42. left, right = 0, k - 1
  43. for right in range(len(nums)):
  44. insert_x_in_list(tmp, nums[right])
  45. while len(tmp) > k:
  46. tmp.pop(find_index_in_list(tmp, nums[left]))
  47. left += 1
  48. if len(tmp) == k:
  49. if k % 2 == 0:
  50. ans.append((tmp[(k + 1) // 2 - 1] + tmp[(k + 1) // 2]) / 2)
  51. else:
  52. ans.append(tmp[(k + 1) // 2 - 1])
  53. return ans
  54. def medianSlidingWindow2(self, nums, k: int):
  55. import bisect
  56. ans = []
  57. tmp = []
  58. left, right = 0, k - 1
  59. for right in range(len(nums)):
  60. bisect.insort(tmp, nums[right]) # 利用二分查找算法来在有序序列中插入元素
  61. while len(tmp) > k:
  62. tmp.pop(bisect.bisect_left(tmp, nums[left])) # 利用二分查找算法来在有序序列中查找元素
  63. left += 1
  64. if len(tmp) == k:
  65. if k % 2 == 0:
  66. ans.append((tmp[(k + 1) // 2 - 1] + tmp[(k + 1) // 2]) / 2)
  67. else:
  68. ans.append(tmp[(k + 1) // 2 - 1])
  69. return ans
  70. if __name__ == '__main__':
  71. s = Solution()
  72. nums = [1, 3, -1, -3, 5, 3, 6, 7]
  73. k = 3
  74. ans = s.medianSlidingWindow1(nums, k)
  75. print(ans)

 

文章来源: nickhuang1996.blog.csdn.net,作者:悲恋花丶无心之人,版权归原作者所有,如需转载,请联系作者。

原文链接:nickhuang1996.blog.csdn.net/article/details/113607012

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。