বড় শব্দ অনুক্রমের শীর্ষ কে ঘন ঘন শব্দগুলি সন্ধান করার সর্বাধিক দক্ষ উপায়


86

ইনপুট: একটি ধনাত্মক পূর্ণসংখ্যার কে এবং একটি বড় পাঠ্য। পাঠ্যটি আসলে শব্দ সিকোয়েন্স হিসাবে দেখা যায়। সুতরাং কীভাবে এটি শব্দ শৃঙ্খলে বিভক্ত হবে তা নিয়ে আমাদের চিন্তা করার দরকার নেই।
আউটপুট: পাঠ্যের সবচেয়ে ঘন ঘন কে।

আমার চিন্তাভাবনা এমন।

  1. পুরো শব্দের ক্রমটি অতিক্রম করার সময় সমস্ত শব্দের ফ্রিকোয়েন্সি রেকর্ড করতে একটি হ্যাশ টেবিল ব্যবহার করুন। এই পর্যায়ে, কীটি "শব্দ" এবং মানটি "শব্দ-ফ্রিকোয়েন্সি"। এটি O (n) সময় নেয়।

  2. (শব্দ, শব্দ-ফ্রিকোয়েন্সি) জোড়াটি সাজান; এবং কীটি হ'ল শব্দ-ফ্রিকোয়েন্সি "। এটি স্বাভাবিক বাছাইকরণ অ্যালগরিদমের সাথে ও (এন * এলজি (এন)) সময় নেয়।

  3. বাছাইয়ের পরে, আমরা কেবল প্রথম কে শব্দগুলি গ্রহণ করি। এটি ও (কে) সময় নেয়।

সংক্ষিপ্তসার হিসাবে, মোট সময় হল ও (এন + এন এলজি (এন) + কে) K যেহেতু কে অবশ্যই এন এর চেয়ে ছোট, তাই এটি আসলে ও (এন এলজি (এন))।

আমরা এই উন্নতি করতে পারেন। আসলে, আমরা শুধু শীর্ষ কে শব্দ চাই। অন্য শব্দগুলির ফ্রিকোয়েন্সি আমাদের জন্য উদ্বেগের নয়। সুতরাং, আমরা "আংশিক হিপ বাছাই" ব্যবহার করতে পারি। পদক্ষেপ 2) এবং 3) এর জন্য, আমরা কেবল বাছাই করি না। পরিবর্তে, আমরা এটি হতে পরিবর্তন

2 ') কী হিসাবে "শব্দ-ফ্রিকোয়েন্সি" যুক্ত (শব্দ, শব্দ-ফ্রিকোয়েন্সি) জুটির একটি গাদা তৈরি করুন। গাদা তৈরি করতে ও (এন) সময় লাগে;

3 ') গাদা থেকে শীর্ষ কে শব্দগুলি বের করুন। প্রতিটি নিষ্কাশন O (lg (n)) হয়। সুতরাং, মোট সময় হল ও (কে * এলজি (এন))।

সংক্ষিপ্তসার হিসাবে, এই সমাধানের জন্য ব্যয় সময় ও (এন + কে * এলজি (এন))।

এটা শুধু আমার চিন্তা। পদক্ষেপ 1) উন্নত করার উপায় আমি খুঁজে পাইনি)।
আমি আশা করি কিছু তথ্য পুনরুদ্ধার বিশেষজ্ঞরা এই প্রশ্নের উপর আরও আলোকপাত করতে পারেন।


আপনি ও (এন * লগন) সাজানোর জন্য মার্জ সাজ্ট বা কুইকোর্ট ব্যবহার করবেন?
প্রতিশ্রুতিবদ্ধ

4
ব্যবহারিক ব্যবহারের জন্য, নমুনায় গণনা করার বিষয়ে অ্যারন মেনপা'র উত্তর সবচেয়ে ভাল। এটি এমন নয় যে ঘন ঘন শব্দগুলি আপনার নমুনা থেকে গোপন করবে। আপনার জটিলতার জন্য, নমুনার আকার স্থির হওয়ার পরে এটি ও (1) is আপনি সঠিক গণনা পাবেন না, তবে আপনি তাদের জন্যও চাইছেন না।
নিকানা রেকলাভিক্স

আপনি যা চান তা যদি আপনার জটিলতা বিশ্লেষণের পর্যালোচনা হয় তবে আমি আরও ভাল করে উল্লেখ করতে পারি: n যদি আপনার পাঠ্যের শব্দের সংখ্যা এবং মি বিভিন্ন শব্দগুলির সংখ্যা হয় (প্রকার, আমরা তাদের ডাকি), পদক্ষেপ 1 হ'ল হে ( এন ) তবে দ্বিতীয় ধাপটি হ'ল ( এম। এলজি ( এম )) এবং এম << n (আপনার বিলিয়ন শব্দ হতে পারে এবং মিলিয়ন ধরণের না পৌঁছতে পারে, এটি চেষ্টা করে দেখুন)। এমনকি একটি ডামি অ্যালগরিদম সহ, এটি এখনও হে ( এন + মি lg ( এম )) = ও ( এন )।
নিকানা রেকলাভিকস

4
Pls এই প্রশ্নে একটি অনুমান যুক্ত করে যে বড় পাঠ্যের সমস্ত শব্দ ধরে রাখতে আমাদের কাছে পর্যাপ্ত মূল স্মৃতি রয়েছে। 10 গিগাবাইট ফাইল থেকে কে = 100 শব্দ খুঁজে বের করার পন্থাগুলি দেখতে আকর্ষণীয় হবে (অর্থাত সমস্ত শব্দ 4 জিবি র‍্যামে খাপ খায় না) !!
কেঘাটক

@ কেঘাটাক এটি র‌্যামের আকার ছাড়িয়ে গেলে কীভাবে করব?
ব্যবহারকারী 7098526

উত্তর:


67

এটি ও (এন) সময়ে করা যেতে পারে

সমাধান 1:

পদক্ষেপ:

  1. শব্দগুলি গণনা করুন এবং এটি হ্যাশ করুন, এটি কাঠামোর মধ্যে শেষ হবে

    var hash = {
      "I" : 13,
      "like" : 3,
      "meow" : 3,
      "geek" : 3,
      "burger" : 2,
      "cat" : 1,
      "foo" : 100,
      ...
      ...
    
  2. হ্যাশ পেরিয়ে সর্বাধিক ব্যবহৃত শব্দটি খুঁজে নিন (এই ক্ষেত্রে "foo" 100), তারপরে সেই আকারের অ্যারে তৈরি করুন

  3. তারপরে আমরা আবার হ্যাশকে অতিক্রম করতে পারি এবং অ্যারে সূচক হিসাবে শব্দের সংখ্যার সংখ্যাটি ব্যবহার করতে পারি, যদি সূচীতে কিছু না থাকে তবে অ্যারেতে এটি যুক্ত করে অন্য একটি অ্যারে তৈরি করতে পারেন। তারপরে আমরা একটি অ্যারের সাথে শেষ করি:

      0   1      2            3                  100
    [[ ],[cat],[burger],[like, meow, geek],[]...[foo]]
    
  4. তারপরে কেবল শেষ থেকে অ্যারেটি অতিক্রম করুন এবং কে শব্দগুলি সংগ্রহ করুন।

সমাধান 2:

পদক্ষেপ:

  1. উপরের মতই
  2. মিনিট হিপ ব্যবহার করুন এবং কে নূন্যতম হিপের আকার রাখুন এবং হ্যাশের প্রতিটি শব্দের জন্য আমরা শব্দের উপস্থিতিগুলিকে ন্যূনতম সাথে তুলনা করি, 1) যদি এটি ন্যূনতম মানের চেয়ে বড় হয় তবে মিনিটটি সরিয়ে ফেলুন (যদি মিনিটের আকার হয়) হিপ কে সমান) এবং মিনিটের গাদাতে সংখ্যাটি সন্নিবেশ করান। 2) বিশ্রাম সহজ শর্ত।
  3. অ্যারেটি অনুসরণ করার পরে, আমরা কেবল মিনি হিপকে অ্যারেতে রূপান্তর করি এবং অ্যারেটি ফিরে আসি।

16
আপনার দ্রবণ (1) হ'ল একটি O (n) বালতি বাছাই একটি মান O (n lg n) তুলনা সাজানোর পরিবর্তে। আপনার পদ্ধতির জন্য বালতি কাঠামোর জন্য অতিরিক্ত স্থান প্রয়োজন, তবে তুলনার ধরণের জায়গায় করা যায়। আপনার সমাধান (2) সময়ে O (n lg কে) - অর্থাৎ ও (এন) সমস্ত শব্দের পুনরাবৃত্তি করতে এবং প্রতিটিকে স্তূপে যুক্ত করতে ও (এলজি কে) চালিত হয়।
stackoverflowuser2010

4
প্রথম সমাধানটির জন্য আরও স্থান প্রয়োজন, তবে এটি জোর দেওয়া গুরুত্বপূর্ণ যে এটি আসলে ও (এন) সময়ে। 1: হ্যাশ ফ্রিকোয়েন্সি শব্দের দ্বারা চালিত, ও (এন); 2: ট্র্যাভার্স ফ্রিকোয়েন্সি হ্যাশ, ফ্রিকোয়েন্সি দ্বারা কীড দ্বিতীয় হ্যাশ তৈরি করুন। এই ফ্রিকোয়েন্সি শব্দের তালিকায় একটি শব্দ যুক্ত করতে এটি হ্যাশকে অতিক্রম করতে ও (এন) এবং ও (1)। 3: ট্র্যাভার্স হ্যাশ সর্বাধিক ফ্রিকোয়েন্সি থেকে নীচে নেমে আসা পর্যন্ত hit সর্বাধিক, ও (এন)। মোট = 3 * ও (এন) = ও (এন)।
থ্রিজি মাইকেকব্যাক

4
সাধারণত শব্দের গণনা করার সময়, সমাধান 1 এ আপনার বালতির সংখ্যা ব্যাপকভাবে বিবেচনা করা হয় (কারণ এক নম্বর সর্বাধিক ঘন শব্দটি দ্বিতীয় এবং তৃতীয় সেরাের চেয়ে অনেক বেশি ঘন ঘন হয়), তাই আপনার অ্যারে খুব কম এবং অকার্যকর।
নিকানা রেক্লাভিক্স

আপনার সমাধান # 1 কাজ করে না যখন কে (ঘন শব্দের সংখ্যা) সর্বাধিক ঘন শব্দটির সংখ্যার তুলনায় কম (যেমন, এই ক্ষেত্রে 100) অবশ্যই, এটি অনুশীলনে নাও হতে পারে তবে একটি হওয়া উচিত ধরে নেই!
এক দুই তিন

@ ওয়ানটাইউ প্রস্তাবিত সমাধানটি কেবল একটি উদাহরণ। চাহিদা ভিত্তিতে নম্বর হবে।
চিহং ইউ

22

আপনি যে সমাধানটি বর্ণনা করেছেন তার চেয়ে সাধারণ রানটাইম আর পাবেন না। সমস্ত শব্দের মূল্যায়নের জন্য আপনাকে কমপক্ষে ও (এন) কাজ করতে হবে এবং তারপরে শীর্ষ ক পদগুলি খুঁজে পেতে ও (কে) অতিরিক্ত কাজ করতে হবে।

যদি আপনার সমস্যা সেটটি সত্যিই বড় হয় তবে আপনি কোনও বিতরণ সমাধান যেমন মানচিত্র / হ্রাস ব্যবহার করতে পারেন। এন ম্যাপ কর্মীদের প্রতিটি পাঠ্যের 1 / n তম ফ্রিকোয়েন্সি গণনা করুন এবং প্রতিটি শব্দের জন্য, শব্দের হ্যাশের উপর ভিত্তি করে গণনা করা মি মিডুসার কর্মীদের একটিতে এটি প্রেরণ করুন। হ্রাসকারীগণ তারপর গণনা যোগফল। হ্রাসকারীদের আউটপুটগুলির উপর ক্রমবর্ধমান সংশ্লেষ আপনাকে জনপ্রিয়তার ক্রমে সর্বাধিক জনপ্রিয় শব্দ দেবে।


13

আপনার দ্রষ্ট্রে একটি সামান্য প্রকরণটি যদি ওপরের কে র‌্যাঙ্কিংয়ের বিষয়ে চিন্তা না করে তবে একটি ও (এন) অ্যালগরিদম এবং আমরা যদি এটি করি তবে একটি ও (এন + কে * এলজি (কে)) সমাধান পান s আমি বিশ্বাস করি যে এই দুটি সীমাই একটি ধ্রুবক ফ্যাক্টরের মধ্যে অনুকূল।

হ্যাশ টেবিলটি inোকানোর পরে তালিকাটি চালানোর পরে এখানে অপ্টিমাইজেশনটি আবার আসবে। আমরা মিডিয়ানদের মিডিয়ান ব্যবহার করতে পারিতালিকার Kth বৃহত্তম উপাদানটি নির্বাচন অ্যালগরিদমের । এই অ্যালগরিদম প্রবক্তা হে (এন)।

কেথের ক্ষুদ্রতম উপাদানটি নির্বাচনের পরে, আমরা সেই উপাদানটির চারপাশে তালিকাটি ঠিক কোয়ারকোর্টের মতোই বিভাজন করি। এটি স্পষ্টতই ও (এন)। পিভটের "বাম" পাশে যে কোনও কিছু আমাদের কে উপাদানগুলির গ্রুপে রয়েছে, তাই আমরা সম্পন্ন হয়েছি (আমরা পাশাপাশি যাব আমরা কেবল সমস্ত কিছু ফেলে দিতে পারি)।

সুতরাং এই কৌশলটি হ'ল:

  1. প্রতিটি শব্দ দিয়ে যান এবং একটি হ্যাশ টেবিল intoোকান: ও (এন)
  2. Kth ক্ষুদ্রতম উপাদান নির্বাচন করুন: O (n)
  3. এই উপাদানটির চারপাশে বিভাজন: ও (এন)

আপনি যদি কে উপাদানগুলিকে র‌্যাঙ্ক করতে চান তবে ও (কে + এলজি (কে)) সময়ে যে কোনও দক্ষ তুলনা বাছাই করে কেবল ও (এন + কে * এলজি (কে)) এর মোট রান সময় উপার্জন করে এগুলি সহজে সাজান।

O (n) সময়সীমাটি একটি ধ্রুবক ফ্যাক্টরের মধ্যে অনুকূল হয় কারণ আমাদের প্রতিটি শব্দ কমপক্ষে একবার পরীক্ষা করতে হবে।

ও (এন + কে * এলজি (কে)) সময়সীমাটিও অনুকূল because


যখন আমরা Kth ক্ষুদ্রতম উপাদানটি নির্বাচন করি তখন যা নির্বাচিত হয় তা হ'ল Kth ক্ষুদ্রতম হ্যাশ-কী। পদক্ষেপ 3
প্রকাশ মুরালি

4
অদলবদল হ'ল আপনি হ্যাশ টেবিলে "মিডিয়ান মেডিয়ানস" চালাতে পারবেন না। আপনাকে হ্যাশ টেবিল থেকে একটি অস্থায়ী অ্যারেতে অনুলিপি করতে হবে। সুতরাং, ও (এন) স্টোরেজটি পুনরায় গণনা করা হবে।
ব্যবহারকারী 674669

আমি বুঝতে পারি না আপনি কীভাবে ও (এন) এর Kth ক্ষুদ্রতম উপাদানটি নির্বাচন করতে পারেন?
মাইকেল হো চাম

(ঢ) হে মধ্যে Kth ক্ষুদ্রতম উপাদান খোঁজার জন্য অ্যালগরিদম এই পরীক্ষা করে দেখুন - wikiwand.com/en/Median_of_medians
পীযূষ

আপনি হ্যাশ টেবিল + মিনিট হিপ ব্যবহার করলেও জটিলতা একই। আমি কোন অপ্টিমাইজেশন দেখতে পাচ্ছি না।
বিনয়

8

যদি আপনার "বড় শব্দের তালিকা" যথেষ্ট বড় হয় তবে আপনি কেবল নমুনা তৈরি করতে পারেন এবং অনুমানগুলি পেতে পারেন। অন্যথায়, আমি হ্যাশ সমষ্টি পছন্দ করি।

সম্পাদনা করুন :

নমুনা অনুসারে আমার অর্থ পৃষ্ঠার কয়েকটি উপসেট চয়ন করুন এবং সেই পৃষ্ঠাগুলিতে সর্বাধিক ঘন শব্দটি গণনা করুন। আপনি যদি যুক্তিসঙ্গত উপায়ে পৃষ্ঠাগুলি নির্বাচন করেন এবং একটি পরিসংখ্যানগতভাবে তাৎপর্যপূর্ণ নমুনা নির্বাচন করেন তবে সর্বাধিক ঘন শব্দগুলির আপনার অনুমান যুক্তিসঙ্গত হওয়া উচিত।

এই পদ্ধতিরটি কেবলমাত্র যুক্তিসঙ্গত যদি আপনার কাছে এত বেশি ডেটা থাকে যে এটির সমস্ত প্রক্রিয়াজাতকরণ কেবল নির্বোধ। যদি আপনার কাছে কেবল কয়েকটি মেগ থাকে তবে আপনি কোনও হিসাবের ব্যয় না করে ঘাম ভেঙে ডেটা ছিঁড়ে ফেলতে এবং সঠিক উত্তরটি গণনা করতে সক্ষম হন।


কখনও কখনও আপনাকে এটি বহুবার করতে হবে, উদাহরণস্বরূপ যদি আপনি ওয়েবসাইট প্রতি, বা বিষয় প্রতি ঘন ঘন শব্দের তালিকা পাওয়ার চেষ্টা করছেন। সেক্ষেত্রে "ঘাম না ভেঙে" সত্যিকার অর্থে এটি কেটে দেয় না। যথাসম্ভব দক্ষতার সাথে এটি করার জন্য আপনাকে এখনও একটি উপায় খুঁজে বের করতে হবে।
itadok

4
ব্যবহারিক উত্তরের জন্য +1 যা অপ্রাসঙ্গিক জটিলতার সমস্যার সমাধান করে না। @ আইস্যাডোক: প্রতিটি রানের জন্য: এটি যথেষ্ট বড় হলে, নমুনা করুন; যদি এটি না হয় তবে লগ ফ্যাক্টর অর্জন অপ্রাসঙ্গিক।
নিকানা রেকলাভিক্স

2

আপনি শব্দের প্রথম অক্ষর ব্যবহার করে বিভাজন করে আরও সময় কেটে ফেলতে পারবেন, তারপরে আপনার একক-শব্দ সেট না হওয়া পর্যন্ত পরবর্তী অক্ষরটি ব্যবহার করে বৃহত্তম মাল্টি-ওয়ার্ড সেট বিভাজন করুন। আপনি পাতায় আংশিক / সম্পূর্ণ শব্দের তালিকা সহ 256-উপায় গাছ একটি ছদ্মবেশ ব্যবহার করবেন। আপনার কোথাও স্ট্রিং অনুলিপি তৈরি না করতে খুব সতর্ক হওয়া দরকার।

এই অ্যালগরিদমটি হ'ল (মি), যেখানে মি অক্ষরের সংখ্যা। এটি কে-এর উপর নির্ভরশীলতা এড়ায় যা বৃহত্তর কে-এর জন্য খুব সুন্দর [আপনার পোস্টের চলমান সময়টি যেভাবে ভুল, এটি ও (এন * এলজি (কে)) হওয়া উচিত এবং আমি নিশ্চিত নই যে এটির ক্ষেত্রে কী আছে মি]।

আপনি যদি পাশাপাশি উভয় অ্যালগরিদম চালিয়ে যান তবে আমি যা পেয়ে যাব তা নিশ্চিত হ'ল একটি অসম্পটিকভাবে অনুকূল ও (কমপক্ষে (এম, এন * এলজি (কে))) অ্যালগরিদম তবে আমার গড় গড়ে দ্রুত হওয়া উচিত কারণ এতে জড়িত নেই হ্যাশিং বা বাছাই


7
আপনি যা বর্ণনা করছেন তাকে 'ত্রি' বলা হয়।
নিক জনসন

হাই স্ট্রিল্যাঙ্ক। আপনি কি পার্টিশন প্রক্রিয়া বিশদটি ব্যাখ্যা করতে পারেন?
মরগান চেং

4
কিভাবে এটি বাছাই জড়িত না ?? আপনার একবার ট্রাই হয়ে গেলে, আপনি কীভাবে সবচেয়ে বড় ফ্রিকোয়েন্সি সহ কে শব্দগুলি বের করেন। কোনও ধারণা নেই
সাধারণ

2

আপনার বিবরণে একটি ত্রুটি রয়েছে: গণনা O (n) সময় নেয় তবে বাছাইয়ের ক্ষেত্রে O (m * lg (m)) লাগে, যেখানে মি হল অনন্য শব্দের সংখ্যা । এটি মোট শব্দের সংখ্যার তুলনায় অনেক ছোট, সম্ভবত হ্যাশটি কীভাবে নির্মিত তা কেবল অনুকূলিত করা উচিত।



2

কি তোমার পরে হন, তাহলে তালিকা কোন ব্যবহারিক জন্য আপনার পাঠে অধিকাংশ ঘন শব্দ এবং কোন প্রাকৃতিক langage জন্য, তারপর আপনার অ্যালগরিদম জটিলতা প্রাসঙ্গিক নয়।

কেবলমাত্র নমুনা বলুন, আপনার পাঠ্য থেকে কয়েক মিলিয়ন শব্দ, কয়েক সেকেন্ডের ক্ষেত্রে কোনও অ্যালগরিদমের সাথে প্রক্রিয়া করুন এবং সর্বাধিক ঘন ঘন গণনাগুলি খুব নির্ভুল হবে।

পার্শ্ব দ্রষ্টব্য হিসাবে, ডামি অ্যালগরিদমের জটিলতা (১. সবগুলি গণনা করুন the. গণনাগুলি সাজান 3.. সেরাটি গ্রহণ করুন) হ'ল হে (এন + এম * লগ (এম)), যেখানে এম আপনার বিভিন্ন শব্দের সংখ্যা পাঠ্য লগ (এম) (এন / এম) এর চেয়ে অনেক ছোট, সুতরাং এটি ও (এন) থেকে যায়।

ব্যবহারিকভাবে, দীর্ঘ পদক্ষেপ গণনা করা হয়।


2
  1. শব্দগুলি সঞ্চয় করতে মেমরি দক্ষ ডেটা স্ট্রাকচারটি ব্যবহার করুন
  2. শীর্ষস্থানীয় কে ঘন ঘন শব্দের সন্ধান করতে ম্যাক হিপ ব্যবহার করুন।

কোডটি এখানে

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

import com.nadeem.app.dsa.adt.Trie;
import com.nadeem.app.dsa.adt.Trie.TrieEntry;
import com.nadeem.app.dsa.adt.impl.TrieImpl;

public class TopKFrequentItems {

private int maxSize;

private Trie trie = new TrieImpl();
private PriorityQueue<TrieEntry> maxHeap;

public TopKFrequentItems(int k) {
    this.maxSize = k;
    this.maxHeap = new PriorityQueue<TrieEntry>(k, maxHeapComparator());
}

private Comparator<TrieEntry> maxHeapComparator() {
    return new Comparator<TrieEntry>() {
        @Override
        public int compare(TrieEntry o1, TrieEntry o2) {
            return o1.frequency - o2.frequency;
        }           
    };
}

public void add(String word) {
    this.trie.insert(word);
}

public List<TopK> getItems() {

    for (TrieEntry trieEntry : this.trie.getAll()) {
        if (this.maxHeap.size() < this.maxSize) {
            this.maxHeap.add(trieEntry);
        } else if (this.maxHeap.peek().frequency < trieEntry.frequency) {
            this.maxHeap.remove();
            this.maxHeap.add(trieEntry);
        }
    }
    List<TopK> result = new ArrayList<TopK>();
    for (TrieEntry entry : this.maxHeap) {
        result.add(new TopK(entry));
    }       
    return result;
}

public static class TopK {
    public String item;
    public int frequency;

    public TopK(String item, int frequency) {
        this.item = item;
        this.frequency = frequency;
    }
    public TopK(TrieEntry entry) {
        this(entry.word, entry.frequency);
    }
    @Override
    public String toString() {
        return String.format("TopK [item=%s, frequency=%s]", item, frequency);
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + frequency;
        result = prime * result + ((item == null) ? 0 : item.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        TopK other = (TopK) obj;
        if (frequency != other.frequency)
            return false;
        if (item == null) {
            if (other.item != null)
                return false;
        } else if (!item.equals(other.item))
            return false;
        return true;
    }

}   

}

এখানে ইউনিট পরীক্ষা করা হয়

@Test
public void test() {
    TopKFrequentItems stream = new TopKFrequentItems(2);

    stream.add("hell");
    stream.add("hello");
    stream.add("hello");
    stream.add("hello");
    stream.add("hello");
    stream.add("hello");
    stream.add("hero");
    stream.add("hero");
    stream.add("hero");
    stream.add("hello");
    stream.add("hello");
    stream.add("hello");
    stream.add("home");
    stream.add("go");
    stream.add("go");
    assertThat(stream.getItems()).hasSize(2).contains(new TopK("hero", 3), new TopK("hello", 8));
}

আরও তথ্যের জন্য এই পরীক্ষার কেসটি দেখুন


1
  1. পুরো শব্দের ক্রমটি অতিক্রম করার সময় সমস্ত শব্দের ফ্রিকোয়েন্সি রেকর্ড করতে একটি হ্যাশ টেবিল ব্যবহার করুন। এই পর্যায়ে, কীটি "শব্দ" এবং মানটি "শব্দ-ফ্রিকোয়েন্সি"। এটি ও (এন) সময় নেয় his এটি উপরে বর্ণিত প্রত্যেকের মতোই

  2. হ্যাশম্যাপে সন্নিবেশ করার সময়, শীর্ষ 10 ঘন ঘন শব্দ রাখার জন্য ট্রিসেটটি (জাভাতে নির্দিষ্ট, প্রতিটি ভাষায় বাস্তবায়ন রয়েছে) আকার 10 (কে = 10) রাখুন। যতক্ষণ না আকার 10 এরও কম হয়, এটি যুক্ত করতে থাকুন। যদি আকার 10 এর সমান হয় তবে সন্নিবেশ করা উপাদানটি ন্যূনতম উপাদানের চেয়ে বেশি হলে প্রথম উপাদান হিসাবে। যদি হ্যাঁ এটি সরান এবং নতুন উপাদান .োকান

ট্রিসেটের আকার সীমাবদ্ধ করতে এই লিঙ্কটি দেখুন


0

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

সম্ভবত আমি আপনার বক্তব্য ভুল বুঝতে পারি। আপনি কি পার্টিশন সম্পর্কে আপনার প্রক্রিয়া বিস্তারিত বলতে পারেন?


0

আমি বিশ্বাস করি এই সমস্যাটি কোনও ও (এন) অ্যালগরিদম দ্বারা সমাধান করা যেতে পারে। আমরা উড়ে বাছাই করতে পারে। অন্য কথায়, সেই ক্ষেত্রে বাছাই করা theতিহ্যবাহী বাছাই করা সমস্যার একটি উপ-সমস্যা কারণ প্রতিবার আমরা হ্যাশ টেবিলটি অ্যাক্সেস করি কেবলমাত্র একজন কাউন্টার একটি করে বাড়িয়ে তোলে। প্রাথমিকভাবে, তালিকাটি বাছাই করা হয় কারণ সমস্ত কাউন্টার শূন্য। যেহেতু আমরা হ্যাশ টেবিলের ইনক্রিমেন্টিং কাউন্টারগুলি রাখি, আমরা নিম্নলিখিতভাবে ফ্রিকোয়েন্সি অনুসারে অর্ডার করা হ্যাশ মানগুলির আরেকটি অ্যারে বুকপিকেক করি। প্রতিবার আমরা কাউন্টারকে বাড়িয়ে দিই, আমরা এর তালিকাটি অ্যারেটিতে সূচকটি পরীক্ষা করে দেখি এবং তালিকায় এর গণনাটি তার পূর্বসূরীর চেয়ে বেশি কিনা check যদি তা হয় তবে আমরা এই দুটি উপাদানকে অদলবদল করি। যেমন আমরা একটি সমাধান পাই যা সর্বাধিক O (n) হয় যেখানে n মূল পাঠ্যের শব্দের সংখ্যা।


এটি সাধারণত একটি ভাল দিক - তবে এটির একটি ত্রুটি রয়েছে। যখন গণনা বাড়ানো হয়, আমরা কেবল "এর পূর্বসূরি" চেক করব না, তবে আমাদের "পূর্বসূরীদের" চেক করা দরকার। উদাহরণস্বরূপ, বড় সুযোগ রয়েছে যে অ্যারেটি হবে [৪,৩,১,১,১,১,১,১,১,১,১,১] - ১ জন এর বেশি হতে পারে - এটি এটিকে কম দক্ষ করে তুলবে যেহেতু অদলবদলের জন্য সঠিকটি খুঁজে পেতে আমাদের সমস্ত পূর্বসূরীদের মধ্য দিয়ে ফিরে তাকাতে হবে।
শান

এটি কি আসলে ও (এন) এর চেয়ে খারাপ হবে না? এটি ও (এন ^ 2) এর মতো কী এটি মূলত একটি অকার্যকর সাজানোর কারণে?
dcarr622

হাই শন হ্যা আমি আপনার সাথে একমত. তবে আমি সন্দেহ করি যে আপনি উল্লিখিত সমস্যাটি সমস্যাটির জন্য মৌলিক। প্রকৃতপক্ষে, যদি মানগুলির কেবল একটি সাজানো অ্যারে রাখার পরিবর্তে আমরা (মান, সূচক) জোড়ার একটি অ্যারে রেখে এগিয়ে যেতে পারি, যেখানে সূচকটি পুনরাবৃত্ত উপাদানটির প্রথম উপস্থিতির দিকে নির্দেশ করে, সমস্যাটি ওতে সমাধানযোগ্য হবে (এন) সময় উদাহরণস্বরূপ, [4,3,1,1,1,1,1,1,1,1,1] দেখতে [[4,0), (3,1), (1,2), (1 , 2), (1,2, ..., (1,2)]; সূচকগুলি 0 থেকে শুরু হয়
এলি ফারাহাত

0

আমি এটির সাথেও লড়াই করে যাচ্ছিলাম এবং @ ইলে দ্বারা অনুপ্রাণিত হয়েছি। পরে বাছাইয়ের পরিবর্তে, আমরা কেবলমাত্র শব্দের একটি পূর্বনির্ধারিত তালিকা বজায় রাখতে পারি ( List<Set<String>>) এবং শব্দটি এক্স অবস্থানে থাকবে যেখানে X শব্দের বর্তমান গণনা। সাধারণত এটি এখানে কীভাবে কাজ করে তা এখানে:

  1. প্রতিটি শব্দ জন্য, এটা ঘটনার মানচিত্র অংশ হিসেবে এটা দোকান: Map<String, Integer>
  2. তারপরে, গণনার উপর ভিত্তি করে, এটি পূর্ববর্তী গণনা সেট থেকে সরান এবং এটিকে নতুন কাউন্ট সেটে যুক্ত করুন।

এর ত্রুটিটি সম্ভবত তালিকাটি বড় - এটি ব্যবহার করে অনুকূলিত করা যেতে পারে TreeMap<Integer, Set<String>>- তবে এটি কিছু ওভারহেড যুক্ত করবে। শেষ পর্যন্ত আমরা হ্যাশম্যাপ বা আমাদের নিজস্ব ডেটা স্ট্রাকচারের মিশ্রণটি ব্যবহার করতে পারি।

কোড

public class WordFrequencyCounter {
    private static final int WORD_SEPARATOR_MAX = 32; // UNICODE 0000-001F: control chars
    Map<String, MutableCounter> counters = new HashMap<String, MutableCounter>();
    List<Set<String>> reverseCounters = new ArrayList<Set<String>>();

    private static class MutableCounter {
        int i = 1;
    }

    public List<String> countMostFrequentWords(String text, int max) {
        int lastPosition = 0;
        int length = text.length();
        for (int i = 0; i < length; i++) {
            char c = text.charAt(i);
            if (c <= WORD_SEPARATOR_MAX) {
                if (i != lastPosition) {
                    String word = text.substring(lastPosition, i);
                    MutableCounter counter = counters.get(word);
                    if (counter == null) {
                        counter = new MutableCounter();
                        counters.put(word, counter);
                    } else {
                        Set<String> strings = reverseCounters.get(counter.i);
                        strings.remove(word);
                        counter.i ++;
                    }
                    addToReverseLookup(counter.i, word);
                }
                lastPosition = i + 1;
            }
        }

        List<String> ret = new ArrayList<String>();
        int count = 0;
        for (int i = reverseCounters.size() - 1; i >= 0; i--) {
            Set<String> strings = reverseCounters.get(i);
            for (String s : strings) {
                ret.add(s);
                System.out.print(s + ":" + i);
                count++;
                if (count == max) break;
            }
            if (count == max) break;
        }
        return ret;
    }

    private void addToReverseLookup(int count, String word) {
        while (count >= reverseCounters.size()) {
            reverseCounters.add(new HashSet<String>());
        }
        Set<String> strings = reverseCounters.get(count);
        strings.add(word);
    }

}

0

আমি কেবল এই সমস্যার জন্য অন্যান্য সমাধানটি সন্ধান করি। তবে আমি নিশ্চিত না যে এটি ঠিক is সমাধান:

  1. সমস্ত শব্দের ফ্রিকোয়েন্সি টি (এন) = ও (এন) রেকর্ড করতে একটি হ্যাশ টেবিল ব্যবহার করুন
  2. হ্যাশ টেবিলের প্রথম কে উপাদানগুলি চয়ন করুন এবং সেগুলি একটি বাফারে পুনরুদ্ধার করুন (যার স্থান = কে)। টি (এন) = ও (কে)
  3. প্রতিবার, প্রথমে আমাদের বাফারের বর্তমান ন্যূনতম উপাদানটি সন্ধান করা প্রয়োজন এবং কেবল বাফের ন্যূনতম উপাদানগুলির সাথে হ্যাশ টেবিলের (এন - কে) উপাদানগুলির সাথে একে অপরের তুলনা করতে হবে। যদি হ্যাশ টেবিলের উপাদানটি বাফারের এই ন্যূনতম উপাদানের চেয়ে বেশি হয় তবে বর্তমান বাফারের মিনিটটি ফেলে দিন এবং হ্যাশ সারণির উপাদান যুক্ত করুন। সুতরাং প্রতিবার আমরা যখন বাফারে সর্বনিম্ন একটিকে টি (এন) = ও (কে) প্রয়োজন এবং পুরো হ্যাশ টেবিলটি টি (এন) = হে (এন - কে) প্রয়োজন হয় verse সুতরাং এই প্রক্রিয়াটির পুরো সময়ের জটিলতা হ'ল টি (এন) = ও ((এনকে) * কে)।
  4. পুরো হ্যাশ টেবিলটি অতিক্রম করার পরে, ফলাফলটি এই বাফারে আসে।
  5. পুরো সময়ের জটিলতা: টি (এন) = ও (এন) + ও (কে) + ও (ক - কে ^ 2) = ও (ন + এন - কে ^ 2 + কে)। যেহেতু, k সাধারণভাবে n এর চেয়ে ছোট। সুতরাং এই সমাধানের জন্য, সময় জটিলতা হ'ল টি (এন) = ও (ন) । এটি লিনিয়ার সময়, যখন কে সত্যিই ছোট হয়। এটা কি ঠিক? আমি সত্যিই নিশ্চিত নই।

0

এই জাতীয় সমস্যাগুলির কাছে যাওয়ার জন্য বিশেষ ডেটা কাঠামোর কথা চিন্তা করার চেষ্টা করুন। এক্ষেত্রে বিশেষ ধরণের গাছ যেমন ট্রাইগুলি নির্দিষ্ট উপায়ে স্ট্রিং রাখতে খুব কার্যকর like বা আপনার নিজের সমাধানটি শব্দের গণনার মতো সমাধানের দ্বিতীয় উপায়। আমি মনে করি এই টিবি ডেটাটি ইংরেজিতে থাকবে তখন আমাদের প্রায় ,000০০,০০০ শব্দ থাকতে পারে তাই কেবলমাত্র সেই শব্দগুলি সংরক্ষণ করা সম্ভব হবে এবং কোন স্ট্রিংগুলি পুনরাবৃত্তি হবে তা গণনা করা হবে + কিছু বিশেষ অক্ষর দূর করতে এই সমাধানটির জন্য রেইজেক্সের প্রয়োজন হবে। প্রথম সমাধানটি আরও দ্রুত হবে, আমি নিশ্চিত।

http://en.wikedia.org/wiki/Trie


0

এটি অনুসন্ধান করার জন্য একটি আকর্ষণীয় ধারণা এবং আমি টপ-কে সম্পর্কিত এই কাগজটি পেতে পারি https://icmi.cs.ucsb.edu/research/tech_reports/reports/2005-23.pd

এছাড়াও এটি এখানে একটি বাস্তবায়ন আছে


আপনার লিঙ্কটি 404 ফিরে আসে
এমবিদেব 20'16

0

সর্বাধিক ঘন ঘন ব্যবহৃত শব্দের সংঘটন পেতে সবচেয়ে সহজ কোড।

 function strOccurence(str){
    var arr = str.split(" ");
    var length = arr.length,temp = {},max; 
    while(length--){
    if(temp[arr[length]] == undefined && arr[length].trim().length > 0)
    {
        temp[arr[length]] = 1;
    }
    else if(arr[length].trim().length > 0)
    {
        temp[arr[length]] = temp[arr[length]] + 1;

    }
}
    console.log(temp);
    var max = [];
    for(i in temp)
    {
        max[temp[i]] = i;
    }
    console.log(max[max.length])
   //if you want second highest
   console.log(max[max.length - 2])
}

0

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

import java.io.*;
import java.lang.reflect.Array;
import java.util.*;

public class TopKWordsTextFile {

    static class SortObject implements Comparable<SortObject>{

        private String key;
        private int value;

        public SortObject(String key, int value) {
            super();
            this.key = key;
            this.value = value;
        }

        @Override
        public int compareTo(SortObject o) {
            //descending order
            return o.value - this.value;
        }
    }


    public static void main(String[] args) {
        HashMap<String,Integer> hm = new HashMap<>();
        int k = 1;
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("words.in")));

            String line;
            while ((line = br.readLine()) != null) {
                // process the line.
                //System.out.println(line);
                String[] tokens = line.split(" ");
                for(int i=0; i<tokens.length; i++){
                    if(hm.containsKey(tokens[i])){
                        //If the key already exists
                        Integer prev = hm.get(tokens[i]);
                        hm.put(tokens[i],prev+1);
                    }else{
                        //If the key doesn't exist
                        hm.put(tokens[i],1);
                    }
                }
            }
            //Close the input
            br.close();
            //Print all words with their repetitions. You can use 3 for printing top 3 words.
            k = hm.size();
            // Get a set of the entries
            Set set = hm.entrySet();
            // Get an iterator
            Iterator i = set.iterator();
            int index = 0;
            // Display elements
            SortObject[] objects = new SortObject[hm.size()];
            while(i.hasNext()) {
                Map.Entry e = (Map.Entry)i.next();
                //System.out.print("Key: "+e.getKey() + ": ");
                //System.out.println(" Value: "+e.getValue());
                String tempS = (String) e.getKey();
                int tempI = (int) e.getValue();
                objects[index] = new SortObject(tempS,tempI);
                index++;
            }
            System.out.println();
            //Sort the array
            Arrays.sort(objects);
            //Print top k
            for(int j=0; j<k; j++){
                System.out.println(objects[j].key+":"+objects[j].value);
            }


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

আরও তথ্যের জন্য, দয়া করে https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/TopKWordsTextFile.java দেখুন । আমি আসা করি এটা সাহায্য করবে.


কোনভাবে প্রশ্নে স্কেচ করা পদ্ধতির উন্নতি হয়? (দয়া করে না না (আউট মন্তব্য দঃপূঃ উপস্থাপন কোড থেকে ছেড়ে।) I recommend to use Java built-in featuresমত foreach loops, এবং প্রক্রিয়াকরণের স্ট্রিম ?)
বৃদ্ধলোক

আপনি যেমন জানেন, একটি দক্ষ অ্যালগরিদম ডিজাইনের সবচেয়ে গুরুত্বপূর্ণ কারণগুলির মধ্যে একটি সঠিক ডেটা কাঠামোটি বেছে নেওয়া choosing তারপরে, আপনি কীভাবে সমস্যাটির কাছে যান এটি গুরুত্বপূর্ণ। উদাহরণস্বরূপ, আপনাকে বিভাজন এবং বিজয় দ্বারা কোনও সমস্যার আক্রমণ করতে হবে। আপনাকে লোভ দেখিয়ে অন্যকে আক্রমণ করা দরকার। আপনি জানেন যে ওরাকল সংস্থা জাভাতে কাজ করছে। তারা বিশ্বের অন্যতম সেরা প্রযুক্তি সংস্থা। সেখানে জাভা অন্তর্নির্মিত বৈশিষ্ট্যগুলিতে কাজ করছেন সবচেয়ে উজ্জ্বল প্রকৌশলী। সুতরাং, এই বৈশিষ্ট্যগুলি ভালভাবে পরীক্ষিত এবং বুলেট প্রুফ। যদি আমরা সেগুলি ব্যবহার করতে পারি তবে সেগুলি আমার মতে ব্যবহার করা ভাল।
মোহাম্মদ

0
**

সি ++ 11 উপরোক্ত চিন্তার বাস্তবায়ন

**

class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {

    unordered_map<int,int> map;
    for(int num : nums){
        map[num]++;
    }

    vector<int> res;
    // we use the priority queue, like the max-heap , we will keep (size-k) smallest elements in the queue
    // pair<first, second>: first is frequency,  second is number 
    priority_queue<pair<int,int>> pq; 
    for(auto it = map.begin(); it != map.end(); it++){
        pq.push(make_pair(it->second, it->first));

        // onece the size bigger than size-k, we will pop the value, which is the top k frequent element value 

        if(pq.size() > (int)map.size() - k){
            res.push_back(pq.top().second);
            pq.pop();
        }
    }
    return res;

}

};

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