Leetcode每日一題:480. 滑動視窗中位數
技術標籤:leetcode練習leetcode演算法python
目錄
問題描述
中位數是有序序列最中間的那個數。如果序列的大小是偶數,則沒有最中間的數;此時中位數是最中間的兩個數的平均數。
例如:
[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]。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/sliding-window-median
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
思路分析及程式碼實現
這道題我一開始的做法就是暴力解,首先將視窗定在一開始前k個數,然後排序求出中位數並新增到ans中,然後右邊界+1,左邊界+1,更新視窗,再重複上面操作
import math
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
n = len(nums)
ans = []
window = nums[:k]
while right < n:
window = nums[left:right+1]
window.sort()
if k % 2 != 0:
mid = (k-1) // 2
ans.append(window[mid])
else:
mid1 = (k-1) // 2
mid2 = math.ceil((k-1) / 2)
ans.append((window[mid1] + window[mid2]) / 2)
right += 1
left += 1
return ans
看到這個時間複雜度,我一陣。。。。。
看了一下題解中的做法,發現很多使用二分來做的,然後學到了一個二分的模組bisect
第二種方法就是隻用一個視窗,然後每次求出中位數後,刪除視窗中的i值,並用二分的方法新增j
import bisect
import math
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
n = len(nums)
ans = []
window = nums[:k]
window.sort()
if k % 2 != 0:
mid = (k - 1) // 2
ans.append(window[mid])
else:
mid1 = (k - 1) // 2
mid2 = math.ceil((k - 1) / 2)
ans.append((window[mid1] + window[mid2]) / 2)
for i, j in zip(nums[:-k], nums[k:]):
window.remove(i)
bisect.insort_left(window, j)
if k % 2 != 0:
mid = (k-1) // 2
ans.append(window[mid])
else:
mid1 = (k-1) // 2
mid2 = math.ceil((k-1) / 2)
ans.append((window[mid1] + window[mid2]) / 2)
return ans
然後時間提高了一點。。。。。。