• [Swift]LeetCode480. 滑动窗口中位数 | Sliding Window Median


    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/10805204.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

    Examples: 

    [2,3,4] , the median is 3

    [2,3], the median is (2 + 3) / 2 = 2.5

    Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array.

    For example,
    Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

    Window position                Median
    ---------------               -----
    [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
    

    Therefore, return the median sliding window as [1,-1,-1,3,5,6].

    Note: 
    You may assume k is always valid, ie: k is always smaller than input array's size for non-empty array.


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

    例如:

    [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 始终小于输入的非空数组的元素个数.


    408ms

     1 class Solution {
     2     func medianSlidingWindow(_ nums: [Int], _ k: Int) -> [Double] {
     3         guard nums.count >= k else {
     4             return []
     5         }
     6         
     7         var result = [Double]()
     8         result.reserveCapacity(nums.count - k + 1)
     9         var window = nums[0..<k].sorted()
    10         for i in 0..<(nums.count - k + 1) {
    11             if i > 0 {
    12                 window.insertOrdered(nums[i - 1 + k])
    13             }
    14             result.append(window.median)
    15             window.remove(nums[i])
    16         }
    17         
    18         return result
    19     }
    20 }
    21 
    22 extension Array where Element == Int {
    23     var median: Double {
    24         return (Double(self[(count - 1) / 2]) + Double(self[(count) / 2])) / 2
    25     }
    26     
    27     mutating func insertOrdered(_ val: Int) {
    28         for i in 0..<count {
    29             if self[i] > val {
    30                 self.insert(val, at: i)
    31                 return
    32             }
    33         }
    34         append(val)
    35     }
    36     
    37     mutating func remove(_ val: Int) {
    38         for i in 0..<count {
    39             if self[i] == val {
    40                 self.remove(at: i)
    41                 return
    42             }
    43         }
    44     }
    45 }

    Runtime: 492 ms
    Memory Usage: 20.3 MB
     1 class Solution {
     2     func medianSlidingWindow(_ nums: [Int], _ k: Int) -> [Double] {
     3         var k = k
     4         var res:[Double] = [Double]()
     5         var record:[(Int,Int)] = [(Int,Int)]()
     6         for i in 0..<k
     7         {
     8             record.append((nums[i],i))
     9         }
    10         record.sort(by: cmp)
    11         update(&res, &record, &k)
    12         for i in k..<nums.count
    13         {
    14             record.remove(at: beforePos(&record, i - k))
    15             record.insert((nums[i],i), at: binPos(&record, nums[i]))
    16             update(&res, &record, &k)
    17         }
    18         return res
    19     }
    20     
    21     func cmp(_ a:(Int,Int),_ b:(Int,Int)) -> Bool
    22     {
    23         if a.0 == b.0 {return a.1 < b.1}
    24         return a.0 < b.0
    25     }
    26     
    27     func binPos(_ record:inout [(Int,Int)],_ target:Int) -> Int
    28     {
    29         var left:Int = 0
    30         var right:Int = record.count
    31         while(left < right)
    32         {
    33             let middle:Int = left + (right - left) / 2
    34             if record[ middle].0 == target
    35             {
    36                 return middle
    37             }
    38             else if record[ middle].0 < target
    39             {
    40                 left = middle + 1
    41             }
    42             else
    43             {
    44                 right = middle
    45             }
    46         }
    47         return left
    48     }
    49     
    50     func beforePos(_ record:inout [(Int,Int)],_ j:Int) -> Int
    51     {
    52         for i in 0..<record.count
    53         {
    54             if record[i].1 == j
    55             {
    56                 return i
    57             }
    58         }
    59         return 0
    60     }
    61     
    62     func update(_ res:inout [Double],_ record:inout [(Int,Int)],_ k:inout Int )
    63     {
    64         if k % 2 == 1
    65         {
    66             res.append(Double(record[ record.count / 2].0))
    67         }
    68         else
    69         {
    70             res.append(Double(record[ record.count / 2].0) * 1.0 / 2 + Double(record[ record.count/2-1].0) * 1.0 / 2)
    71         }
    72     }
    73 }

    636ms

      1 class Solution {
      2     var maxHeap = Heap<Int>(sort: >)
      3 var minHeap = Heap<Int>(sort: <)
      4 
      5 func medianSlidingWindow(_ nums: [Int], _ k: Int) -> [Double] {
      6     var res = [Double]()
      7     
      8     for (index, value) in nums.enumerated() {
      9         if maxHeap.isEmpty || value <= maxHeap.peek()! {
     10             maxHeap.insert(value)
     11         } else {
     12             minHeap.insert(value)
     13         }
     14         
     15         balance()
     16         
     17         let removeTarget = index - k
     18         if removeTarget >= 0 {
     19             if nums[removeTarget] > maxHeap.peek()! {
     20                 minHeap.remove(node: nums[removeTarget])
     21             } else {
     22                 maxHeap.remove(node: nums[removeTarget])
     23             }
     24         }
     25         
     26         balance()
     27         
     28         if index >= k - 1 {
     29             if k % 2 == 0 {
     30                 res.append((Double(minHeap.peek()!) + Double(maxHeap.peek()!)) / 2)
     31             } else {
     32                 res.append(Double(maxHeap.peek()!))
     33             }
     34         }
     35     }
     36     
     37     return res
     38 }
     39 
     40 func balance() {
     41     while maxHeap.count < minHeap.count {
     42         maxHeap.insert(minHeap.remove()!)
     43     }
     44     
     45     while minHeap.count < maxHeap.count - 1 {
     46         minHeap.insert(maxHeap.remove()!)
     47     }
     48   }
     49 }
     50 
     51 
     52 ////// swfit heap:
     53 public struct Heap<T> {
     54     /** The array that stores the heap's nodes. */
     55     var nodes = [T]()
     56     
     57     /**
     58      * Determines how to compare two nodes in the heap.
     59      * Use '>' for a max-heap or '<' for a min-heap,
     60      * or provide a comparing method if the heap is made
     61      * of custom elements, for example tuples.
     62      */
     63     private var orderCriteria: (T, T) -> Bool
     64     
     65     /**
     66      * Creates an empty heap.
     67      * The sort function determines whether this is a min-heap or max-heap.
     68      * For comparable data types, > makes a max-heap, < makes a min-heap.
     69      */
     70     public init(sort: @escaping (T, T) -> Bool) {
     71         orderCriteria = sort
     72     }
     73     
     74     /**
     75      * Creates a heap from an array. The order of the array does not matter;
     76      * the elements are inserted into the heap in the order determined by the
     77      * sort function. For comparable data types, '>' makes a max-heap,
     78      * '<' makes a min-heap.
     79      */
     80     public init(array: [T], sort: @escaping (T, T) -> Bool) {
     81         orderCriteria = sort
     82         configureHeap(from: array)
     83     }
     84     
     85     /**
     86      * Configures the max-heap or min-heap from an array, in a bottom-up manner.
     87      * Performance: This runs pretty much in O(n).
     88      */
     89     private mutating func configureHeap(from array: [T]) {
     90         nodes = array
     91         for i in stride(from: (nodes.count / 2 - 1), through: 0, by: -1) {
     92             shiftDown(i)
     93         }
     94     }
     95     
     96     public var isEmpty: Bool {
     97         return nodes.isEmpty
     98     }
     99     
    100     public var count: Int {
    101         return nodes.count
    102     }
    103     
    104     /**
    105      * Returns the index of the parent of the element at index i.
    106      * The element at index 0 is the root of the tree and has no parent.
    107      */
    108     @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int {
    109         return (i - 1) / 2
    110     }
    111     
    112     /**
    113      * Returns the index of the left child of the element at index i.
    114      * Note that this index can be greater than the heap size, in which case
    115      * there is no left child.
    116      */
    117     @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int {
    118         return 2 * i + 1
    119     }
    120     
    121     /**
    122      * Returns the index of the right child of the element at index i.
    123      * Note that this index can be greater than the heap size, in which case
    124      * there is no right child.
    125      */
    126     @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int {
    127         return 2 * i + 2
    128     }
    129     
    130     /**
    131      * Returns the maximum value in the heap (for a max-heap) or the minimum
    132      * value (for a min-heap).
    133      */
    134     public func peek() -> T? {
    135         return nodes.first
    136     }
    137     
    138     /**
    139      * Adds a new value to the heap. This reorders the heap so that the max-heap
    140      * or min-heap property still holds. Performance: O(log n).
    141      */
    142     public mutating func insert(_ value: T) {
    143         nodes.append(value)
    144         shiftUp(nodes.count - 1)
    145     }
    146     
    147     /**
    148      * Adds a sequence of values to the heap. This reorders the heap so that
    149      * the max-heap or min-heap property still holds. Performance: O(log n).
    150      */
    151     public mutating func insert<S: Sequence>(_ sequence: S) where S.Iterator.Element == T {
    152         for value in sequence {
    153             insert(value)
    154         }
    155     }
    156     
    157     /**
    158      * Allows you to change an element. This reorders the heap so that
    159      * the max-heap or min-heap property still holds.
    160      */
    161     public mutating func replace(index i: Int, value: T) {
    162         guard i < nodes.count else { return }
    163         
    164         remove(at: i)
    165         insert(value)
    166     }
    167     
    168     /**
    169      * Removes the root node from the heap. For a max-heap, this is the maximum
    170      * value; for a min-heap it is the minimum value. Performance: O(log n).
    171      */
    172     @discardableResult public mutating func remove() -> T? {
    173         guard !nodes.isEmpty else { return nil }
    174         
    175         if nodes.count == 1 {
    176             return nodes.removeLast()
    177         } else {
    178             // Use the last node to replace the first one, then fix the heap by
    179             // shifting this new first node into its proper position.
    180             let value = nodes[0]
    181             nodes[0] = nodes.removeLast()
    182             shiftDown(0)
    183             return value
    184         }
    185     }
    186     
    187     /**
    188      * Removes an arbitrary node from the heap. Performance: O(log n).
    189      * Note that you need to know the node's index.
    190      */
    191     @discardableResult public mutating func remove(at index: Int) -> T? {
    192         guard index < nodes.count else { return nil }
    193         
    194         let size = nodes.count - 1
    195         if index != size {
    196             nodes.swapAt(index, size)
    197             shiftDown(from: index, until: size)
    198             shiftUp(index)
    199         }
    200         return nodes.removeLast()
    201     }
    202     
    203     /**
    204      * Takes a child node and looks at its parents; if a parent is not larger
    205      * (max-heap) or not smaller (min-heap) than the child, we exchange them.
    206      */
    207     internal mutating func shiftUp(_ index: Int) {
    208         var childIndex = index
    209         let child = nodes[childIndex]
    210         var parentIndex = self.parentIndex(ofIndex: childIndex)
    211         
    212         while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) {
    213             nodes[childIndex] = nodes[parentIndex]
    214             childIndex = parentIndex
    215             parentIndex = self.parentIndex(ofIndex: childIndex)
    216         }
    217         
    218         nodes[childIndex] = child
    219     }
    220     
    221     /**
    222      * Looks at a parent node and makes sure it is still larger (max-heap) or
    223      * smaller (min-heap) than its childeren.
    224      */
    225     internal mutating func shiftDown(from index: Int, until endIndex: Int) {
    226         let leftChildIndex = self.leftChildIndex(ofIndex: index)
    227         let rightChildIndex = leftChildIndex + 1
    228         
    229         // Figure out which comes first if we order them by the sort function:
    230         // the parent, the left child, or the right child. If the parent comes
    231         // first, we're done. If not, that element is out-of-place and we make
    232         // it "float down" the tree until the heap property is restored.
    233         var first = index
    234         if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) {
    235             first = leftChildIndex
    236         }
    237         if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) {
    238             first = rightChildIndex
    239         }
    240         if first == index { return }
    241         
    242         nodes.swapAt(index, first)
    243         shiftDown(from: first, until: endIndex)
    244     }
    245     
    246     internal mutating func shiftDown(_ index: Int) {
    247         shiftDown(from: index, until: nodes.count)
    248     }
    249 }
    250 
    251 // MARK: - Searching
    252 
    253 extension Heap where T: Equatable {
    254     /** Get the index of a node in the heap. Performance: O(n). */
    255     public func index(of node: T) -> Int? {
    256         return nodes.index(where: { $0 == node })
    257     }
    258     
    259     /** Removes the first occurrence of a node from the heap. Performance: O(n log n). */
    260     @discardableResult public mutating func remove(node: T) -> T? {
    261         if let index = index(of: node) {
    262             return remove(at: index)
    263         }
    264         return nil
    265     }
    266 }
  • 相关阅读:
    程序性能优化1
    在archlinux上搭建twitter storm cluster
    .Net 跨平台可移植类库PCL可用于任何平台包括Mono
    .NET面向对象特性之封装
    哈夫曼(Huffman)编码
    高质量视频学习网站
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1071 潜伏者
  • 原文地址:https://www.cnblogs.com/strengthen/p/10805204.html
Copyright © 2020-2023  润新知