All Downloads are FREE. Search and download functionalities are using the official Maven repository.

g0201_0300.s0295_find_median_from_data_stream.MedianFinder.dart Maven / Gradle / Ivy

There is a newer version: 1.8
Show newest version
// #Hard #Top_100_Liked_Questions #Sorting #Two_Pointers #Design #Heap_Priority_Queue #Data_Stream
// #Big_O_Time_O(n*log_n)_Space_O(n) #2024_10_09_Time_602_ms_(100.00%)_Space_228.5_MB_(62.50%)

class MedianFinder {
  PriorityQueue small = PriorityQueue((a, b) =>b.compareTo(a));
  PriorityQueue large = PriorityQueue();
  bool even = true;

  double findMedian() =>
  even ?(small.first +large.first)/2.0:small.first.toDouble();

  void addNum(int num) {
    if (even) {
      large.add(num);
      small.add(large.removeFirst());
    } else {
      small.add(num);
      large.add(small.removeFirst());
    }
    even = !even;
  }
}

// Priority Queue if not using package:collection/collection.dart
class PriorityQueue> {
  PriorityQueue([int Function(E, E)?comparison])
          :comparison =comparison ??Comparable.compare;

  final List _queue = [];
  final Comparator comparison;
  bool get
  isEmpty =>_queue.isEmpty;
  int get
  length =>_queue.length;
  E get
  first =>_queue.first;

  void add(E value) {
    _queue.add(value);
    var child = length - 1;
    var parent = _parentOf(child);
    while (child > 0 && child == _higherPriority(child, parent)) {
      _swapElements(child, parent);
      child = parent;
      parent = _parentOf(child);
    }
  }

  E removeFirst() {
    if (isEmpty) throw StateError('No element');
    _swapElements(0, length - 1);
    final firstElement =_queue.removeLast();
    var parentIndex = 0;
    while (true) {
      final leftIndex =_leftChildOf(parentIndex);
      final rightIndex =_rightChildOf(parentIndex);
      var chosen = _higherPriority(leftIndex, parentIndex);
      chosen = _higherPriority(rightIndex, chosen);
      if (chosen == parentIndex) break;
      _swapElements(parentIndex, chosen);
      parentIndex = chosen;
    }
    return firstElement;
  }

  int _leftChildOf(int parentIndex) =>2*parentIndex +1;

  int _rightChildOf(int parentIndex) =>2*parentIndex +2;

  int _parentOf(int childIndex) =>(childIndex -1)~/2;

  int _higherPriority(int index1, int index2) {
    if (index1 >= length) return index2;
    final value1 =_queue[index1];
    final value2 =_queue[index2];
    return comparison(value1, value2).isNegative ? index1 : index2;
  }

  void _swapElements(int index1, int index2) {
    final temp =_queue[index1];
    _queue[index1] = _queue[index2];
    _queue[index2] = temp;
  }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = MedianFinder();
 * obj.addNum(num);
 * double param2 = obj.findMedian();
 */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy