গ মধ্যে মিডল অ্যালগোরিদম ঘূর্ণায়মান


114

আমি বর্তমানে সিতে রোলিং মিডিয়ান ফিল্টার (রোলিং গড় ফিল্টারটির সাথে সমতুল্য) বাস্তবায়নের জন্য একটি অ্যালগরিদমে কাজ করছি আমার সাহিত্যের সন্ধান থেকে, এটি করার দুটি যুক্তিসঙ্গত উপায় রয়েছে বলে মনে হয়। প্রথমটি হ'ল মানগুলির প্রাথমিক উইন্ডোটিকে বাছাই করা, তারপরে নতুন মান সন্নিবেশ করার জন্য বাইনারি অনুসন্ধান করা এবং প্রতিটি পুনরাবৃত্তিতে বিদ্যমান একটিকে সরিয়ে ফেলা।

দ্বিতীয় (হার্ডল এবং স্টেইগার, 1995, জেআরএসএস-সি, অ্যালগরিদম 296) একটি ডাবল-এন্ড হিপ স্ট্রাকচার তৈরি করে, যার এক প্রান্তে ম্যাকশিপ, অন্যদিকে মিনহিপ এবং মাঝখানে মিডিয়ান রয়েছে। এটি ও (এন লগ এন) এর পরিবর্তে রৈখিক-সময় অ্যালগোরিদম লাভ করে।

এখানে আমার সমস্যাটি রয়েছে: প্রাক্তনটি প্রয়োগ করা কার্যক্ষম, তবে আমার এটি কয়েক মিলিয়ন সময়ের সিরিজে চালানো দরকার, তাই দক্ষতা অনেকটাই গুরুত্বপূর্ণ। দ্বিতীয়টি কার্যকর করা খুব কঠিন প্রমাণিত হচ্ছে। আমি আর এর স্ট্যাটাস প্যাকেজের জন্য কোডের ট্রুনমেড.সি ফাইলটিতে কোড পেয়েছি, তবে এটি বরং অনিবার্য।

লিনিয়ার টাইম রোলিং মিডিয়ান অ্যালগরিদমের জন্য কেউ কি লিখিত সি প্রয়োগকরণ সম্পর্কে জানেন?

সম্পাদনা করুন: ট্রানমেড.সি কোডের লিঙ্ক http://google.com/codesearch/p?hl=en&sa=N&cd=1&ct=rc#mYw3h_Lb_e0/R-2.2.0/src/library/stats/src/Trunmed.c


সবেমাত্র চলমান গড় বাস্তবায়ন করা হয়েছে ... মিডিয়ান মুভিং কিছুটা জটিল চলন্ত মিডিয়ানকে গুগল করার চেষ্টা করুন।
ম্যাট

গুগল এবং গুগল কোড অনুসন্ধান করার চেষ্টা করা হয়েছে। এটি ট্রুঁড কোডের এসজিআই পোর্টের (আমি যা বলতে পারি) থেকে ট্রুনমেড. কোড এবং অন্য ভাষায় একটি প্রয়োগকরণ চালু করে। এছাড়াও, আমি উদ্ধৃত জেআরএসএস অ্যালগরিদমটি সম্ভবত জার্নালের সিরিজের একমাত্র যার জন্য মূল কোড সংরক্ষণাগারভুক্ত ছিল না।
এডাব্লুবি

প্রতিটি টাইম সিরিজে আপনার সংখ্যা কত? এমনকি তাদের মিলিয়ন সহ, যদি আপনার কেবল কয়েক হাজার সংখ্যা থাকে তবে এটি চালাতে এক বা দুই মিনিটের বেশি সময় নিতে পারে না (যদি আপনার কোডটি দক্ষতার সাথে লেখা থাকে)।
দানা দ্য সনে

16
দুটি গাদা সমাধান লিনিয়ার কেমন? এটি ও (এন লগ কে) যেখানে কে উইন্ডো আকারের কারণ হিপগুলির মোছা হ'ল ও (লগ কে)।
ইয়ারছু

3
কিছু বাস্তবায়ন এবং তুলনা: github.com/suomela/median-filter
Jukka Suomela

উত্তর:


28

আমি src/library/stats/src/Trunmed.cস্ট্যান্ড্যালোন সি ++ ক্লাস / সি সাব্রোটিনেও অনুরূপ কিছু চেয়েছিলাম বলে আমি কয়েকবার আর এর দিকে চেয়েছি। মনে রাখবেন যে এটি আসলে একটিতে দুটি বাস্তবায়ন, দেখুন src/library/stats/man/runmed.Rd(সহায়তা ফাইলের উত্স) যা বলেছে

\details{
  Apart from the end values, the result \code{y = runmed(x, k)} simply has
  \code{y[j] = median(x[(j-k2):(j+k2)])} (k = 2*k2+1), computed very
  efficiently.

  The two algorithms are internally entirely different:
  \describe{
    \item{"Turlach"}{is the Härdle-Steiger
      algorithm (see Ref.) as implemented by Berwin Turlach.
      A tree algorithm is used, ensuring performance \eqn{O(n \log
        k)}{O(n * log(k))} where \code{n <- length(x)} which is
      asymptotically optimal.}
    \item{"Stuetzle"}{is the (older) Stuetzle-Friedman implementation
      which makes use of median \emph{updating} when one observation
      enters and one leaves the smoothing window.  While this performs as
      \eqn{O(n \times k)}{O(n * k)} which is slower asymptotically, it is
      considerably faster for small \eqn{k} or \eqn{n}.}
  }
}

আরও স্ট্যান্ডেলোন ফ্যাশনে এটি পুনরায় ব্যবহৃত দেখতে ভাল লাগবে। আপনি কি স্বেচ্ছাসেবক? আমি কিছু বি বিট সাহায্য করতে পারেন।

সম্পাদনা 1 : উপরের ট্রুনমেড.সি. এর পুরানো সংস্করণটির লিঙ্কটি ছাড়াও এখানে বর্তমান এসভিএন কপি রয়েছে

  • Srunmed.c (স্টুয়েজল সংস্করণের জন্য)
  • Trunmed.c (টারলাচ সংস্করণের জন্য)
  • runmed.R আর এই ফাংশন কল করার জন্য

2 সম্পাদনা করুন : রায়ান তিবশিরানীর দ্রুত মিডিয়ান বেনিংয়ে কিছু সি এবং ফোর্টরান কোড রয়েছে যা উইন্ডোযুক্ত পদ্ধতির জন্য উপযুক্ত প্রারম্ভিক পয়েন্ট হতে পারে।


ধন্যবাদ ডার্ক একবার আমি একটি পরিষ্কার সমাধান পেয়েছি, আমি এটি জিপিএল এর অধীনে ছেড়ে দেওয়ার পরিকল্পনা করছি। আমি আর আর পাইথন ইন্টারফেসও সেট করতে আগ্রহী।
এডাব্লুবি

9
@ এডব্লিউবি এই ধারণাটি দিয়ে কী ঘটেছিল? আপনি কি নিজের সমাধানটিকে একটি প্যাকেজে অন্তর্ভুক্ত করেছেন?
শু ওয়াং

20

অর্ডার-পরিসংখ্যান সহ একটি সি ++ ডেটা কাঠামোর একটি আধুনিক বাস্তবায়ন আমি খুঁজে পাইনি সুতরাং এমএকে প্রস্তাবিত শীর্ষ কোডার লিঙ্কে উভয় ধারণাকেই বাস্তবায়িত করে ( ম্যাচ সম্পাদকীয় : ফ্লোটিংমিডিয়ানে স্ক্রোল করুন)।

দুটি মাল্টিস্টেট

প্রথম ধারণাটি inোকান / মুছে ফেলার জন্য ও (এলএনএন) দিয়ে দুটি তথ্য কাঠামো (হিপস, মাল্টিসেটস ইত্যাদি) এ ডেটা বিভাজন করে কোয়ান্টাইলকে বড় ব্যয় ছাড়াই গতিশীল পরিবর্তন করতে দেয় না। অর্থাৎ আমাদের কাছে রোলিং মিডিয়ান বা রোলিং 75% থাকতে পারে তবে উভয় একই সময়ে নয়।

সেগমেন্ট ট্রি

দ্বিতীয় ধারণাটি সেগমেন্ট গাছ ব্যবহার করে যা সন্নিবেশ / মোছা / প্রশ্নের জন্য O (ln N) তবে আরও নমনীয়। সর্বোপরি "এন" আপনার ডেটা ব্যাপ্তির আকার। সুতরাং যদি আপনার রোলিং মিডিয়ানের একটি মিলিয়ন আইটেমের উইন্ডো থাকে তবে আপনার ডেটা 1.65536 থেকে পৃথক হয়, তবে 1 মিলিয়ন রোলিং উইন্ডোর চলন প্রতি 16 টি অপারেশন প্রয়োজন!

সি ++ কোড ডেনিস উপরের পোস্টের মতোই ("এখানে কোয়ান্টাইজড ডেটার জন্য একটি সাধারণ অ্যালগরিদম")

জিএনইউ আদেশ পরিসংখ্যান গাছ

হাল ছেড়ে দেওয়ার আগে, আমি দেখতে পেলাম যে stdlibc ++ এ অর্ডার স্ট্যাটিস্টিক ট্রি রয়েছে !!!

এগুলির দুটি সমালোচনামূলক অপারেশন রয়েছে:

iter = tree.find_by_order(value)
order = tree.order_of_key(value)

দেখুন আগে থেকে libstdc ++ ম্যানুয়াল policy_based_data_structures_test (জন্য অনুসন্ধান "বিভক্ত এবং যোগদান")।

সি ++ 0x / সি ++ 11 শৈলীর আংশিক টাইপডেফ সমর্থনকারী সংকলকগুলির জন্য একটি সুবিধার শিরোনামে ব্যবহারের জন্য আমি গাছটি মুড়ে ফেলেছি:

#if !defined(GNU_ORDER_STATISTIC_SET_H)
#define GNU_ORDER_STATISTIC_SET_H
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

// A red-black tree table storing ints and their order
// statistics. Note that since the tree uses
// tree_order_statistics_node_update as its update policy, then it
// includes its methods by_order and order_of_key.
template <typename T>
using t_order_statistic_set = __gnu_pbds::tree<
                                  T,
                                  __gnu_pbds::null_type,
                                  std::less<T>,
                                  __gnu_pbds::rb_tree_tag,
                                  // This policy updates nodes'  metadata for order statistics.
                                  __gnu_pbds::tree_order_statistics_node_update>;

#endif //GNU_ORDER_STATISTIC_SET_H

আসলে, libstdc ++ এক্সটেনশন পাত্রে ডিজাইন অনুসারে একাধিক মানের জন্য অনুমতি দেয় না ! উপরে আমার নাম দ্বারা প্রস্তাবিত (t_order_statistic_set) হিসাবে, একাধিক মান একত্রিত করা হয়েছে। সুতরাং, আমাদের উদ্দেশ্যগুলির জন্য তাদের আরও কিছুটা কাজের প্রয়োজন :-(
লিও গুডস্ট্যাড

আমাদের 1) গণনার মানগুলির মানচিত্র তৈরি করতে হবে (সেটগুলির পরিবর্তে) 2) শাখার মাপগুলি কীগুলির গণনা প্রতিফলিত করবে (libstdc ++ - v3 / অন্তর্ভুক্ত / এক্সট / পিবি_ডিএস / বিশদ / বৃক্ষ_পলসি / অর্ডার_স্ট্যাটিস_আইপিএইচপি) থেকে প্রাপ্ত উত্তরাধিকারী ট্রি, এবং 3) ওভারলোড সন্নিবেশ () মান বাড়ানোর জন্য / কল আপডেট_ টো_টপ () যদি মানটি ইতিমধ্যে উপস্থিত থাকে 4) ওভারলোড মোছা () গণনা / কল আপডেট কমাতে কল করুন () মানটি অনন্য না হলে (libstdc ++ দেখুন - ভি 3 / অন্তর্ভুক্ত / এক্সট্রা / পিবি_ডিএস / বিস্তারিত / আরবি_ট্রি_ম্যাপ_ / আরবি_ট্রি_ এইচপি) কোনও স্বেচ্ছাসেবক ??
লিও গুডস্ট্যাডট

15

আমি এখানে একটি সি বাস্তবায়ন করেছি । আরও কয়েকটি বিশদ এই প্রশ্নের মধ্যে রয়েছে: সি-টার্ল্যাচ বাস্তবায়নে রোলিং মিডিয়ান

নমুনা ব্যবহার:

int main(int argc, char* argv[])
{
   int i,v;
   Mediator* m = MediatorNew(15);

   for (i=0;i<30;i++)
   {
      v = rand()&127;
      printf("Inserting %3d \n",v);
      MediatorInsert(m,v);
      v=MediatorMedian(m);
      printf("Median = %3d.\n\n",v);
      ShowTree(m);
   }
}

6
মিনি-মিডিয়ান-ম্যাক্স হিপের উপর ভিত্তি করে দুর্দান্ত, দ্রুত এবং স্পষ্ট বাস্তবায়ন। খুব ভাল কাজ.
জোহানেস রুডলফ

আমি এই সমাধানটির জাভা সংস্করণটি কীভাবে খুঁজে পাব?
হেনগামে

10

আমি এই ইনক্রিমেন্টাল মিডিয়ান অনুমানকারীটি ব্যবহার করি:

median += eta * sgn(sample - median)

যা আরও সাধারণ গড় অনুমানকারী হিসাবে একই ফর্ম আছে:

mean += eta * (sample - mean)

এখানে ETA একটি ছোট শেখার হার পরামিতি (যেমন হয় 0.001), এবং sgn()সংকেত ফাংশন যার এক ফেরৎ {-1, 0, 1}। ( etaযদি ডেটা স্থির থাকে না এবং আপনি সময়ের সাথে সাথে পরিবর্তনগুলি ট্র্যাক করতে চান তবে এই ধরণের ধ্রুবক ব্যবহার করুন ; অন্যথায়, স্থির সূত্রগুলি eta = 1 / nরূপান্তর করার মতো কিছু ব্যবহার করে , যেখানে nএখন পর্যন্ত দেখা নমুনাগুলির সংখ্যা is)

এছাড়াও, আমি এটিকে নির্বিচার কোয়ান্টাইলগুলির জন্য কাজ করতে মিডিয়ান অনুমানকারীকে সংশোধন করেছি। সাধারণভাবে, একটি কোয়ান্টাইল ফাংশন আপনাকে সেই মান বলে যা তথ্যকে দুটি ভগ্নাংশে বিভক্ত করে: pএবং 1 - p। নিম্নলিখিতটি ক্রমান্বয়ে এই মানটি অনুমান করে:

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

মানটির মধ্যে pহওয়া উচিত [0, 1]। এটি মূলত sgn()ফাংশনটির প্রতিসাম্য আউটপুটটি {-1, 0, 1}একদিকে ঝুঁকতে স্থানান্তরিত করে, তথ্য নমুনাগুলিকে দুটি অসম আকারের বিনগুলিতে বিভক্ত করে (ভগ্নাংশ pএবং 1 - pডেটার পরিমাণ যথাক্রমে কোয়ান্টাইল অনুমানের চেয়ে কম / বেশি)। মনে রাখবেন যে এর জন্য p = 0.5এটি মধ্যম অনুমানকারীকে হ্রাস করে।


2
শীতল, এখানে একটি পরিবর্তন রয়েছে যা চলমান গড়ের উপর ভিত্তি করে 'এটা' সামঞ্জস্য করে ... (গড়টি মাঝারিটির মোটামুটি অনুমান হিসাবে ব্যবহৃত হয় তাই এটি ছোট মানগুলিতে রূপান্তরিত করে একই হারে বড় মানগুলিতে রূপান্তর করে)। অর্থাৎ এটা স্বয়ংক্রিয়ভাবে সুর করা হয়। stackoverflow.com/questions/11482529/…
জেফ ম্যাকক্লিনটক

3
অনুরূপ প্রযুক্তির জন্য, এই কাগজটি সীমান্তিক স্ট্রিমিংয়ে দেখুন: arxiv.org/pdf/1407.1121v1.pdf এটি কোনও চৌকোটি অনুমান করতে পারে এবং গড় পরিবর্তনের সাথে মানিয়ে নিতে পারে। এটির জন্য প্রয়োজনীয় যে আপনি কেবল দুটি মান সংরক্ষণ করুন: শেষ অনুমান এবং শেষ সামঞ্জস্যের দিকনির্দেশ (+1 বা -1)। অ্যালগরিদম প্রয়োগ করা সহজ। আমি দেখতে পেয়েছি যে ত্রুটিটি সময়ের প্রায় 5% এর মধ্যে%%।
পল চেরনোক

9

কোয়ান্টাইটিসড ডেটা (মাস পরে) এর জন্য এখানে একটি সাধারণ অ্যালগরিদম রয়েছে:

""" median1.py: moving median 1d for quantized, e.g. 8-bit data

Method: cache the median, so that wider windows are faster.
    The code is simple -- no heaps, no trees.

Keywords: median filter, moving median, running median, numpy, scipy

See Perreault + Hebert, Median Filtering in Constant Time, 2007,
    http://nomis80.org/ctmf.html: nice 6-page paper and C code,
    mainly for 2d images

Example:
    y = medians( x, window=window, nlevel=nlevel )
    uses:
    med = Median1( nlevel, window, counts=np.bincount( x[0:window] ))
    med.addsub( +, - )  -- see the picture in Perreault
    m = med.median()  -- using cached m, summ

How it works:
    picture nlevel=8, window=3 -- 3 1s in an array of 8 counters:
        counts: . 1 . . 1 . 1 .
        sums:   0 1 1 1 2 2 3 3
                        ^ sums[3] < 2 <= sums[4] <=> median 4
        addsub( 0, 1 )  m, summ stay the same
        addsub( 5, 1 )  slide right
        addsub( 5, 6 )  slide left

Updating `counts` in an `addsub` is trivial, updating `sums` is not.
But we can cache the previous median `m` and the sum to m `summ`.
The less often the median changes, the faster;
so fewer levels or *wider* windows are faster.
(Like any cache, run time varies a lot, depending on the input.)

See also:
    scipy.signal.medfilt -- runtime roughly ~ window size
    http://stackoverflow.com/questions/1309263/rolling-median-algorithm-in-c

"""

from __future__ import division
import numpy as np  # bincount, pad0

__date__ = "2009-10-27 oct"
__author_email__ = "denis-bz-py at t-online dot de"


#...............................................................................
class Median1:
    """ moving median 1d for quantized, e.g. 8-bit data """

    def __init__( s, nlevel, window, counts ):
        s.nlevel = nlevel  # >= len(counts)
        s.window = window  # == sum(counts)
        s.half = (window // 2) + 1  # odd or even
        s.setcounts( counts )

    def median( s ):
        """ step up or down until sum cnt to m-1 < half <= sum to m """
        if s.summ - s.cnt[s.m] < s.half <= s.summ:
            return s.m
        j, sumj = s.m, s.summ
        if sumj <= s.half:
            while j < s.nlevel - 1:
                j += 1
                sumj += s.cnt[j]
                # print "j sumj:", j, sumj
                if sumj - s.cnt[j] < s.half <= sumj:  break
        else:
            while j > 0:
                sumj -= s.cnt[j]
                j -= 1
                # print "j sumj:", j, sumj
                if sumj - s.cnt[j] < s.half <= sumj:  break
        s.m, s.summ = j, sumj
        return s.m

    def addsub( s, add, sub ):
        s.cnt[add] += 1
        s.cnt[sub] -= 1
        assert s.cnt[sub] >= 0, (add, sub)
        if add <= s.m:
            s.summ += 1
        if sub <= s.m:
            s.summ -= 1

    def setcounts( s, counts ):
        assert len(counts) <= s.nlevel, (len(counts), s.nlevel)
        if len(counts) < s.nlevel:
            counts = pad0__( counts, s.nlevel )  # numpy array / list
        sumcounts = sum(counts)
        assert sumcounts == s.window, (sumcounts, s.window)
        s.cnt = counts
        s.slowmedian()

    def slowmedian( s ):
        j, sumj = -1, 0
        while sumj < s.half:
            j += 1
            sumj += s.cnt[j]
        s.m, s.summ = j, sumj

    def __str__( s ):
        return ("median %d: " % s.m) + \
            "".join([ (" ." if c == 0 else "%2d" % c) for c in s.cnt ])

#...............................................................................
def medianfilter( x, window, nlevel=256 ):
    """ moving medians, y[j] = median( x[j:j+window] )
        -> a shorter list, len(y) = len(x) - window + 1
    """
    assert len(x) >= window, (len(x), window)
    # np.clip( x, 0, nlevel-1, out=x )
        # cf http://scipy.org/Cookbook/Rebinning
    cnt = np.bincount( x[0:window] )
    med = Median1( nlevel=nlevel, window=window, counts=cnt )
    y = (len(x) - window + 1) * [0]
    y[0] = med.median()
    for j in xrange( len(x) - window ):
        med.addsub( x[j+window], x[j] )
        y[j+1] = med.median()
    return y  # list
    # return np.array( y )

def pad0__( x, tolen ):
    """ pad x with 0 s, numpy array or list """
    n = tolen - len(x)
    if n > 0:
        try:
            x = np.r_[ x, np.zeros( n, dtype=x[0].dtype )]
        except NameError:
            x += n * [0]
    return x

#...............................................................................
if __name__ == "__main__":
    Len = 10000
    window = 3
    nlevel = 256
    period = 100

    np.set_printoptions( 2, threshold=100, edgeitems=10 )
    # print medians( np.arange(3), 3 )

    sinwave = (np.sin( 2 * np.pi * np.arange(Len) / period )
        + 1) * (nlevel-1) / 2
    x = np.asarray( sinwave, int )
    print "x:", x
    for window in ( 3, 31, 63, 127, 255 ):
        if window > Len:  continue
        print "medianfilter: Len=%d window=%d nlevel=%d:" % (Len, window, nlevel)
            y = medianfilter( x, window=window, nlevel=nlevel )
        print np.array( y )

# end median1.py

4

সংখ্যার দুটি পার্টিশন বজায় রেখে রোলিং মিডিয়ান পাওয়া যাবে।

পার্টিশন বজায় রাখার জন্য মিন হিপ এবং ম্যাক্স হিপ ব্যবহার করুন।

ম্যাক্স হিপ মিডিয়ানের সমান থেকে কম সংখ্যক থাকবে।

ন্যূনতম হিপটিতে মিডিয়ান সমান সংখ্যার চেয়ে বেশি নম্বর থাকবে।

ব্যালেন্সিং সীমাবদ্ধতা: মোট উপাদানগুলির সংখ্যা এমনকি যদি হয় তবে উভয় স্তূপের সমান উপাদান থাকা উচিত।

যদি মোট সংখ্যার উপাদানগুলি বিজোড় হয় তবে ম্যাক্স হিপ-এ মিন হ্যাপের চেয়ে আরও একটি উপাদান থাকবে।

মিডিয়ান এলিমেন্ট: উভয় পার্টিশনে যদি সমান সংখ্যক উপাদান থাকে তবে মিডিয়ান প্রথম পার্টিশন থেকে সর্বোচ্চ উপাদানটির যোগফল এবং দ্বিতীয় বিভাজন থেকে ন্যূনতম উপাদান হবে।

অন্যথায় মিডিয়ান প্রথম পার্টিশন থেকে সর্বোচ্চ উপাদান হবে।

Algorithm-
1- দুটি হিপ নিন (1 মিনিটের গাদা এবং 1 সর্বোচ্চ গাদা)
   ম্যাক্স হ্যাপে প্রথম অর্ধেক উপাদান থাকবে
   ন্যূনতম হিপতে দ্বিতীয়ার্ধের মতো উপাদান থাকবে

2- ম্যাক্স হ্যাপের শীর্ষের সাথে প্রবাহ থেকে নতুন সংখ্যাটির তুলনা করুন, 
   যদি এটি ছোট বা সমান হয় তবে সর্বাধিক হ্যাপে সেই সংখ্যাটি যুক্ত করুন। 
   অন্যথায় মিন হিপে সংখ্যা যুক্ত করুন number

3- যদি মিনি হিপে ম্যাক্স হ্যাপের চেয়ে বেশি উপাদান থাকে 
   তারপরে মিন হ্যাপের শীর্ষ উপাদানটি সরিয়ে ম্যাক্স হ্যাপে যুক্ত করুন।
   যদি সর্বাধিক হিপ মিন হ্যাপের চেয়ে একাধিক উপাদান থাকে 
   তারপরে ম্যাক্স হ্যাপের শীর্ষ উপাদানটি সরিয়ে মিন হ্যাপে যুক্ত করুন।

4- উভয় স্তূপে যদি সমান সংখ্যক উপাদান থাকে
   মধ্যম হ'ল ম্যাক্স হিপ থেকে সর্বাধিক উপাদান এবং মিন হিপ থেকে ন্যূনতম উপাদানগুলির যোগফল half
   অন্যথায় মিডিয়ান প্রথম পার্টিশন থেকে সর্বোচ্চ উপাদান হবে।
public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        RunningMedianHeaps s = new RunningMedianHeaps();
        int n = in.nextInt();
        for(int a_i=0; a_i < n; a_i++){
            printMedian(s,in.nextInt());
        }
        in.close();       
    }

    public static void printMedian(RunningMedianHeaps s, int nextNum){
            s.addNumberInHeap(nextNum);
            System.out.printf("%.1f\n",s.getMedian());
    }
}

class RunningMedianHeaps{
    PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(Comparator.reverseOrder());

    public double getMedian() {

        int size = minHeap.size() + maxHeap.size();     
        if(size % 2 == 0)
            return (maxHeap.peek()+minHeap.peek())/2.0;
        return maxHeap.peek()*1.0;
    }

    private void balanceHeaps() {
        if(maxHeap.size() < minHeap.size())
        {
            maxHeap.add(minHeap.poll());
        }   
        else if(maxHeap.size() > 1+minHeap.size())
        {
            minHeap.add(maxHeap.poll());
        }
    }

    public void addNumberInHeap(int num) {
        if(maxHeap.size()==0 || num <= maxHeap.peek())
        {
            maxHeap.add(num);
        }
        else
        {
            minHeap.add(num);
        }
        balanceHeaps();
    }
}

এটি তৃতীয় জাভা উত্তর সি প্রশ্নের জন্য কতটা সুবিধা দেয় তা আমার কাছে পরিষ্কার নয়। আপনার একটি নতুন প্রশ্ন জিজ্ঞাসা করা উচিত, এবং তারপরে সেই প্রশ্নটিতে আপনার জাভা উত্তর সরবরাহ করুন।
jww

যুক্তি পড়ার পরে মারা গেল 'তারপরে ন্যূনতম হিপগুলির শীর্ষ উপাদানটি সরিয়ে মিন হিপগুলিতে যুক্ত করুন।' .পুষ্টির আগে কমপক্ষে আলগো পড়ার সৌজন্য থাকতে হবে
সাইক্লোট্রন

4
এই অ্যালগরিদম রোলিং মিডিয়েনের জন্য নয় বরং ক্রমবর্ধমান সংখ্যক উপাদানগুলির মধ্যকের জন্য। রোলিং মিডিয়ানের জন্য, একজনকে অবশ্যই গাদা থেকে একটি উপাদান অপসারণ করতে হবে, যা প্রথমে খুঁজে পাওয়া দরকার।
ওয়াল্টার

2

এটি সম্ভবত উল্লেখ করার মতো যে এখানে একটি বিশেষ কেস রয়েছে যার একটি সাধারণ সঠিক সমাধান রয়েছে: যখন প্রবাহের সমস্ত মানগুলি একটি (অপেক্ষাকৃত) ছোট সংজ্ঞায়িত ব্যাপ্তির মধ্যে পূর্ণসংখ্যা হয়। উদাহরণস্বরূপ, ধরুন যে তাদের সবগুলি 0 এবং 1023 এর মধ্যে থাকা উচিত In এক্ষেত্রে কেবল 1024 উপাদান এবং একটি গণনার অ্যারে সংজ্ঞায়িত করুন এবং এই মানগুলি পরিষ্কার করুন। স্ট্রিমের প্রতিটি মানের জন্য সংশ্লিষ্ট বিন এবং গণনা বৃদ্ধি করে। স্ট্রিমটি শেষ হওয়ার পরে বিনটি খুঁজে বের করে যার মধ্যে গণনা / 2 সর্বোচ্চ মান রয়েছে - 0 থেকে শুরু করে ধারাবাহিক বিনগুলি যোগ করে সহজেই সম্পন্ন করা হয় একই পদ্ধতি ব্যবহার করে একটি স্বেচ্ছাসেবী র‌্যাঙ্ক ক্রমের মান পাওয়া যেতে পারে। (বিন স্যাচুরেশন সনাক্তকরণ এবং সঞ্চয়ের সময় স্টোরেজ বিনের আকারকে আরও বড় আকারে আপগ্রেড করার ক্ষেত্রে একটি ছোটখাটো জটিলতা রয়েছে))

এই বিশেষ ক্ষেত্রেটি কৃত্রিম বলে মনে হতে পারে তবে অনুশীলনে এটি খুব সাধারণ is এগুলি বাস্তব সংখ্যার জন্য একটি সান্নিধ্য হিসাবে প্রয়োগ করা যেতে পারে যদি তারা একটি পরিসরের মধ্যে থাকে এবং যথার্থতার "যথেষ্ট ভাল" স্তরের পরিচিত হয়। এটি "রিয়েল ওয়ার্ল্ড" অবজেক্টগুলির একটি গোষ্ঠীতে পরিমাপের প্রায় কোনও সেটকে ধরে রাখতে পারে। উদাহরণস্বরূপ, একদল লোকের উচ্চতা বা ওজন। একটি বড় যথেষ্ট সেট না? এটি গ্রহের সমস্ত (পৃথক) ব্যাকটিরিয়ার দৈর্ঘ্য বা ওজনের জন্য ঠিক সেইভাবে কাজ করবে - ধরে নেওয়া যে কেউ ডেটা সরবরাহ করতে পারে!

দেখে মনে হচ্ছে আমি আসলটি ভুলভাবে পড়েছি - যা দেখে মনে হচ্ছে এটি খুব দীর্ঘ স্ট্রিমের স্রেফ মিডিয়ানের পরিবর্তে স্লাইডিং উইন্ডো মিডিয়ান চায়। এই পদ্ধতির এখনও এটি জন্য কাজ করে। প্রাথমিক উইন্ডোটির জন্য প্রথম এন স্ট্রিম মানগুলি লোড করুন, তারপরে N + 1 স্ট্রিম মান বর্ধিত করার জন্য সংশ্লিষ্ট বিনটিকে বর্ধন করার সময় 0 র্থ স্ট্রিম মানের সাথে সংযুক্ত বিনটিকে হ্রাস করতে হবে। এই ক্ষেত্রে হ্রাসের অনুমতি দেওয়ার জন্য সর্বশেষ এন মানগুলি ধরে রাখা প্রয়োজন, যা চক্রাকারে N আকারের একটি অ্যারে সম্বোধন করে দক্ষতার সাথে করা যেতে পারে Since যেহেতু মধ্যকের অবস্থান কেবল -2, -1,0,1 দ্বারা পরিবর্তিত হতে পারে স্লাইডিং উইন্ডোর প্রতিটি ধাপে 2, প্রতিটি ধাপে মিডিয়ানের সমস্ত বিন্দু যোগ করার প্রয়োজন হয় না, কেবল "মিডিয়ান পয়েন্টার" সামঞ্জস্য করুন যার উপরের (গুলি) বিনগুলি সংশোধন করা হয়েছিল। এই ক্ষেত্রে, যদি নতুন মান এবং একটি মুছে ফেলা হয় উভয়ই যদি বর্তমান মধ্যকের নীচে পড়ে তবে তা পরিবর্তন হয় না (অফসেট = 0)। এনটি স্মৃতিতে সুবিধামতভাবে ধরে রাখার জন্য এন খুব বড় হয়ে গেলে পদ্ধতিটি ভেঙে যায়।


1

আপনার যদি সময়গুলিতে পয়েন্টগুলির ফাংশন হিসাবে মানগুলি উল্লেখ করার ক্ষমতা থাকে তবে আপনি প্রতিস্থাপনের সাথে মানগুলি নমুনা করতে পারবেন, আত্মবিশ্বাসের ব্যবধানের মধ্যে বুটস্ট্র্যাপড মিডিয়ান মান উত্পন্ন করতে বুটস্ট্র্যাপিং প্রয়োগ করতে পারেন। এটি আপনাকে আগত মানগুলিকে ডেটা স্ট্রাকচারে ক্রমাগত বাছাই করার চেয়ে বৃহত্তর দক্ষতার সাথে একটি আনুমানিক মাঝারি গণনা করতে দেয়।


1

যাঁদের জাভাতে একটি চলমান মিডিয়ান প্রয়োজন তাদের জন্য ... অগ্রাধিকারকুই আপনার বন্ধু। ও (লগ এন) সন্নিবেশ করুন, ও (1) বর্তমান মিডিয়ান এবং ও (এন) সরান। আপনি যদি নিজের ডেটা বন্টন জানেন তবে আপনি এর থেকে আরও অনেক ভাল করতে পারেন।

public class RunningMedian {
  // Two priority queues, one of reversed order.
  PriorityQueue<Integer> lower = new PriorityQueue<Integer>(10,
          new Comparator<Integer>() {
              public int compare(Integer arg0, Integer arg1) {
                  return (arg0 < arg1) ? 1 : arg0 == arg1 ? 0 : -1;
              }
          }), higher = new PriorityQueue<Integer>();

  public void insert(Integer n) {
      if (lower.isEmpty() && higher.isEmpty())
          lower.add(n);
      else {
          if (n <= lower.peek())
              lower.add(n);
          else
              higher.add(n);
          rebalance();
      }
  }

  void rebalance() {
      if (lower.size() < higher.size() - 1)
          lower.add(higher.remove());
      else if (higher.size() < lower.size() - 1)
          higher.add(lower.remove());
  }

  public Integer getMedian() {
      if (lower.isEmpty() && higher.isEmpty())
          return null;
      else if (lower.size() == higher.size())
          return (lower.peek() + higher.peek()) / 2;
      else
          return (lower.size() < higher.size()) ? higher.peek() : lower
                  .peek();
  }

  public void remove(Integer n) {
      if (lower.remove(n) || higher.remove(n))
          rebalance();
  }
}

সি ++ এর মানক লাইব্রেরিতে এক্সটেনশনে gnu থেকে পরিসংখ্যান গাছ রয়েছে। নীচে আমার পোস্ট দেখুন।
লিও গুডস্ট্যাড

আমি মনে করি আপনার কোডটি এখানে সঠিকভাবে দেওয়া হয়নি। এখানে কিছু অসম্পূর্ণ অংশ রয়েছে যেমন: }), higher = new PriorityQueue<Integer>();বা new PriorityQueue<Integer>(10,। আমি কোডটি চালাতে পারিনি।
হেনগামে

@ হেনগামে জাভা সেমিকোলন দিয়ে বিবৃতি শেষ করে - লাইন ব্রেকগুলি মোটেই গুরুত্বপূর্ণ নয়। আপনি অবশ্যই এটি ভুলভাবে অনুলিপি করেছেন।
ম্যাথু

আপনার একটি নতুন প্রশ্ন জিজ্ঞাসা করা উচিত, এবং তারপরে সেই প্রশ্নটিতে আপনার জাভা উত্তর সরবরাহ করুন।
jww

0

নির্ভুল আউটপুট গুরুত্বপূর্ণ না হলে এটি ব্যবহার করা যেতে পারে (প্রদর্শনের উদ্দেশ্যে ইত্যাদির জন্য) আপনার টোটকাউন্ট এবং লাস্টমেডিয়ান প্রয়োজনে নতুন মূল্যায়ন প্রয়োজন।

{
totalcount++;
newmedian=lastmedian+(newvalue>lastmedian?1:-1)*(lastmedian==0?newvalue: lastmedian/totalcount*2);
}

পেজ_ডিসপ্লে_টাইমের মতো জিনিসের জন্য বেশ সঠিক ফলাফল তৈরি করে।

বিধি: ইনপুট স্ট্রিমটি পৃষ্ঠা প্রদর্শন সময়ের ক্রম অনুসারে মসৃণ হওয়া দরকার, গণনায় বড় (> 30 ইত্যাদি), এবং একটি শূন্য নন মাঝারি হওয়া উচিত।

উদাহরণ: পৃষ্ঠা লোড টাইম, 800 আইটেম, 10 মিম ... 3000 মিমি, গড় 90 মিমি, রিয়েল মিডিয়ান: 11 এমএস

30 ইনপুটগুলির পরে, মিডিয়ানদের ত্রুটি সাধারণত <= 20% (9ms..12 মিমি) হয় এবং কম এবং কম হয়। 800 ইনপুটগুলির পরে, ত্রুটিটি + -2%।

অনুরূপ সমাধান সহ অন্য একজন চিন্তাবিদ এখানে আছেন: মিডিয়ান ফিল্টার সুপার দক্ষ বাস্তবায়ন


-1

এখানে জাভা বাস্তবায়ন

package MedianOfIntegerStream;

import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;


public class MedianOfIntegerStream {

    public Set<Integer> rightMinSet;
    public Set<Integer> leftMaxSet;
    public int numOfElements;

    public MedianOfIntegerStream() {
        rightMinSet = new TreeSet<Integer>();
        leftMaxSet = new TreeSet<Integer>(new DescendingComparator());
        numOfElements = 0;
    }

    public void addNumberToStream(Integer num) {
        leftMaxSet.add(num);

        Iterator<Integer> iterMax = leftMaxSet.iterator();
        Iterator<Integer> iterMin = rightMinSet.iterator();
        int maxEl = iterMax.next();
        int minEl = 0;
        if (iterMin.hasNext()) {
            minEl = iterMin.next();
        }

        if (numOfElements % 2 == 0) {
            if (numOfElements == 0) {
                numOfElements++;
                return;
            } else if (maxEl > minEl) {
                iterMax.remove();

                if (minEl != 0) {
                    iterMin.remove();
                }
                leftMaxSet.add(minEl);
                rightMinSet.add(maxEl);
            }
        } else {

            if (maxEl != 0) {
                iterMax.remove();
            }

            rightMinSet.add(maxEl);
        }
        numOfElements++;
    }

    public Double getMedian() {
        if (numOfElements % 2 != 0)
            return new Double(leftMaxSet.iterator().next());
        else
            return (leftMaxSet.iterator().next() + rightMinSet.iterator().next()) / 2.0;
    }

    private class DescendingComparator implements Comparator<Integer> {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    }

    public static void main(String[] args) {
        MedianOfIntegerStream streamMedian = new MedianOfIntegerStream();

        streamMedian.addNumberToStream(1);
        System.out.println(streamMedian.getMedian()); // should be 1

        streamMedian.addNumberToStream(5);
        streamMedian.addNumberToStream(10);
        streamMedian.addNumberToStream(12);
        streamMedian.addNumberToStream(2);
        System.out.println(streamMedian.getMedian()); // should be 5

        streamMedian.addNumberToStream(3);
        streamMedian.addNumberToStream(8);
        streamMedian.addNumberToStream(9);
        System.out.println(streamMedian.getMedian()); // should be 6.5
    }
}

আপনার একটি নতুন প্রশ্ন জিজ্ঞাসা করা উচিত, এবং তারপরে সেই প্রশ্নটিতে আপনার জাভা উত্তর সরবরাহ করুন।
jww

-4

আপনার যদি কেবল একটি ধীরে ধীরে গড়ের প্রয়োজন হয় দ্রুত / সহজ উপায়টি সর্বশেষ মানটিকে x দ্বারা এবং গড় মানকে (1-x) দিয়ে গুণতে পারে তবে সেগুলি যুক্ত করুন। এটি তখন নতুন গড় হয়ে যায়।

সম্পাদনা: ব্যবহারকারী যা চেয়েছিলেন তা নয় এবং পরিসংখ্যানগতভাবে বৈধ হিসাবে নয় তবে প্রচুর ব্যবহারের জন্য যথেষ্ট ভাল।
আমি অনুসন্ধানের জন্য এটি এখানে (ডাউনভোটস সত্ত্বেও) রেখে দেব!


2
এটি গড় গণনা করে। তিনি মিডিয়ান চান। এছাড়াও, তিনি পুরো সেট নয়, মানগুলির একটি স্লাইডিং উইন্ডোর মধ্যম গণনা করছেন।
এ লেভি

1
এটি এক্সের উপর নির্ভর করে ক্ষয়ের ধ্রুবক সহ মানগুলির একটি উইন্ডোটির চলমান গড়ের গণনা করে - এটি খুব কার্যকর যেখানে কর্মক্ষমতা গুরুত্বপূর্ণ এবং আপনাকে কলম্যান ফিল্টার করে বিরক্ত করা যায় না। আমি এটি রেখেছি যাতে অনুসন্ধান এটি সন্ধান করতে পারে।
মার্টিন বেকেট

অডিও অ্যাপ্লিকেশনটির জন্য খুব বেসিক এবং সস্তা লোপাস-ফিল্টার হিসাবে এই ধরনের ফিল্টার বাস্তবায়ন করে আমি এটি অবিলম্বে ভেবেছিলাম।
জেমস মরিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.