একটি ইনপুট মানটি বন্ধন করে ভাসমানের জুটির সন্ধান করতে ফ্লোটের সাজানো অ্যারে অনুসন্ধান করতে দ্রুত অ্যালগরিদম


10

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

অ্যারে মাধ্যমে একটি সরল রৈখিক অনুসন্ধান করা একটি নিখুঁত পন্থা হবে। এটি দেখতে এইরকম হতে পারে:

void FindClosestFloatsInArray( float input, std::vector<float> array, 
                               float *min_out, float *max_out )
{
    assert( input >= array[0] && input < array[ array.size()-1 ] );
    for( int i = 1; i < array.size(); i++ )
    {
        if ( array[i] >= input )
        {
            *min = array[i-1];
            *max = array[i];
        }
    }
}

তবে স্পষ্টতই অ্যারে বড় হওয়ার সাথে সাথে এটি ধীর এবং ধীর হয়ে উঠবে।

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

আরও তথ্য: অ্যারেতে ভাসমান পয়েন্টের মানগুলি অগত্যা সমানভাবে বিতরণ করা হয় না (অর্থাৎ অ্যারেতে "1.f, 2.f, 3.f, 4.f, 100.f, 1200.f মান থাকতে পারে , 1203.f, 1400.f "।

আমি কয়েক হাজার বার এই অপারেশনটি করছি, তবে আমি এটির সময়কালের উন্নতি করতে পারলে ফ্লোটের অ্যারেতে প্রাক প্রসেসিংয়ের যে কোনও পরিমাণ কাজ করতে পারি। আমি ভেক্টর ব্যতীত অন্য কিছু সংরক্ষণের জন্য তাদের ব্যবহার করতে পরিবর্তন করতে পারি, যদি তা সহায়তা করে।


আপনাকে কী মনে করে যে আপনার বাইনারি অনুসন্ধান তাড়াতাড়ি শেষ হতে পারে না? অবশ্যই আপনি কেবলমাত্র i এবং i + 1 এ থাকা উপাদানগুলিকে লক্ষ্য মানটি বন্ধন করে কিনা তা পরীক্ষা করতে পারেন, এবং তারা যদি শেষ করেন তবে?
পল আর

পর্যায়ক্রমে, আমি এবং i-1 এ থাকা উপাদানগুলি লক্ষ্যবস্তুতে বন্ধনী দেয় কিনা তা পরীক্ষা করতে পারতাম। 'আমি'> = অ্যারে.সাইজ () - 1 ছিল কিনা তাও আমাকে পরীক্ষা করতে হবে যাতে আমি আপনার পরীক্ষা করা এড়াতে পারি এবং এটি <= 0 ছিল কিনা তাই আমি আমার পরীক্ষা করা এড়াতে পারতাম ... এটি আসলে অনেক কিছু প্রথম দিকে আউট পরীক্ষা করার জন্য প্রতিটি পদক্ষেপে অতিরিক্ত শর্তযুক্ত করা। আমি ধারণা করি তারা অ্যালগরিদমকে অনেকটা কমিয়ে দেবে, যদিও আমি স্বীকার করব যে আমি এখনও এটির প্রোফাইল দিইনি।
ট্রেভর পাওয়েল

3
এটি এত জটিল হওয়ার দরকার নেই - আপনার অ্যারেটি যদি N এর আকারের হয় তবে আপনার ঠিক এটির আকারের N - 1 এর মতো আচরণ করা দরকার That এইভাবে আই ++ এ সর্বদা একটি বৈধ উপাদান থাকে You আই-এর জন্য এন - ১ উপাদান বাইনারি অনুসন্ধান যা আপনার টার্গেটের মানের চেয়ে কম, এলিমেন্ট i + 1 এর সাথে লক্ষ্য মানের চেয়ে বেশি হয়।
পল আর

উত্তর:


11

প্রশ্নের যথাযথ কোড (একটি লিনিয়ার সন্ধান) যেমন আপনি যথাযথভাবে উল্লেখ করেছেন, বড় বড় ফ্লোট অ্যারেগুলি ধীরে ধীরে পেতে চলেছে। প্রযুক্তিগতভাবে এটি O (n) যেখানে n হ'ল আপনার অ্যারেতে ভাসমান মানের সংখ্যা।

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

আমার প্রস্তাবিত পদ্ধতির ফলে অ্যারের সাধারণ বাইনারি অনুসন্ধান হবে , অর্থাত:

  1. আপনার পুরো ফ্লোট অ্যারেটি কভার করার জন্য ন্যূনতম / সর্বাধিক পূর্ণসংখ্যা সূচকগুলি সেট করুন
  2. এক্স-এর বিপরীতে মাঝারি মানের সূচক মাঝের = (মিনিট + সর্বোচ্চ / 2) এর মান পরীক্ষা করুন
  3. x যদি এই মানটির চেয়ে কম হয় তবে সর্বোচ্চ থেকে মাঝখানে সেট করুন, অন্যথায় মিনিট থেকে মাঝখানে সেট করুন
  4. আপনি সঠিক মান না পাওয়া পর্যন্ত পুনরাবৃত্তি করুন (2-4)

এটি একটি ও (লগ এন) অ্যালগরিদম যা প্রায় সমস্ত পরিস্থিতির জন্য দ্রুত হওয়া উচিত। স্বজ্ঞাতভাবে, এটি সঠিক মান খুঁজে না পাওয়া পর্যন্ত প্রতিটি ধাপে অনুসন্ধানের জন্য সীমাটি অর্ধেক করে কাজ করে।

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

  • বকেটিং - বালতি তৈরি করুন (উদাহরণস্বরূপ দুটি পূর্ণসংখ্যার মধ্যবর্তী প্রতিটি ব্যবধানের জন্য), যার প্রত্যেকটিতে প্রতিটি সীমাবদ্ধতার নীচে এবং তত্ক্ষণাত উপরে দুটি অবধি পূর্ণসংখ্যা এবং দুটি মানের মধ্যে ভাসমান মানের একটি ছোট সাজানো তালিকা থাকে। তারপরে আপনি আপনার অনুসন্ধান (ট্রাঙ্ক (এক্স) +0.5) এ শুরু করতে পারেন। আপনি যদি যথাযথ আকারের বালতি বেছে নেন (এটি কার্যকরভাবে গাছের শাখা ফ্যাক্টরকে বাড়িয়ে তুলছে .....) তবে এটি আপনাকে একটি ভাল গতিবেগ দেয়। যদি পূর্ণসংখ্যাগুলি আপনার পক্ষে কাজ করে না, তবে আপনি কিছু অন্যান্য নির্দিষ্ট-পয়েন্ট যথার্থতার বালতি চেষ্টা করতে পারেন (উদাহরণস্বরূপ 1/1 এর গুণক)।
  • বিট-ম্যাপিং - যদি সম্ভাব্য অনুসন্ধানের মানগুলির পরিধিটি যথেষ্ট পরিমাণে ছোট হয় তবে আপনি x এর বিটওয়াইভ মান দ্বারা সূচিযুক্ত একটি বড় লুক টেবিল তৈরি করতে চেষ্টা করতে পারেন। এটি ও (1) হবে তবে আপনার প্রচুর স্মৃতি দরকার হতে পারে যা আপনার ক্যাশে খুব বন্ধুত্বপূর্ণ হবে ... তাই সাবধানতার সাথে ব্যবহার করুন। এটি বিশেষত বাজে কারণ আপনি ভাসমান মানগুলি সন্ধান করছেন, তাই আপনার কম সংখ্যক তাত্পর্যপূর্ণ বিটগুলির জন্য অ্যাকাউন্ট করতে বেশ কয়েকটি জিবি প্রয়োজন হতে পারে ......
  • রাউন্ডিং এবং হ্যাশিং - হ্যাশ টেবিলগুলি সম্ভবত এই সমস্যার জন্য সর্বোত্তম ডেটা কাঠামো নয়, তবে আপনি যদি কিছুটা যথার্থতা হারাতে পারেন তবে তারা কাজ করতে পারে - কেবল আপনার অনুসন্ধানের মানগুলির সর্বনিম্ন বিটগুলি সরিয়ে ফেলুন এবং সরাসরি অনুসন্ধান করার জন্য একটি হ্যাশম্যাপ ব্যবহার করুন সঠিক মান। আপনাকে হ্যাশম্যাপ আকার এবং নির্ভুলতার মধ্যে ডান বাণিজ্য বন্ধের উপর পরীক্ষা করতে হবে, এবং এটিও নিশ্চিত করতে হবে যে সমস্ত সম্ভাব্য হ্যাশ মানগুলি জনবহুল তাই এটি কিছুটা জটিল হতে পারে ......
  • গাছের ভারসাম্য - আপনার আদর্শ গাছে বাম বা ডান দিকে যাওয়ার 50% সুযোগ থাকা উচিত। সুতরাং আপনি যদি অনুসন্ধান মানগুলির (x) বিতরণের উপর ভিত্তি করে একটি গাছ তৈরি করেন তবে আপনি ন্যূনতম পরীক্ষার সাথে উত্তর উত্পন্ন করতে গাছটিকে অনুকূলিত করতে পারেন। আপনার ভাসমান অ্যারের অনেকগুলি মান একসাথে খুব কাছাকাছি থাকলে এটি একটি ভাল সমাধান হতে পারে, কারণ এটি আপনাকে এই শাখাগুলি খুব ঘন ঘন এড়াতে সক্ষম করবে।
  • ক্রিট-বিট গাছ - এগুলি এখনও গাছ (তাই এখনও হে (লগ এন) ...) তবে কিছু ক্ষেত্রে: তুলনা কাজ করার জন্য আপনাকে আপনার ফ্লোটগুলি কিছু নির্দিষ্ট-বিন্দু বিন্যাসে রূপান্তর করতে হবে

তবে, আপনি যদি খুব বিশেষ পরিস্থিতিতে না থাকেন তবে আমি সম্ভবত সাধারণ বাইনারি অনুসন্ধানের সাথে লেগে থাকার পরামর্শ দিই। কারণ:

  • এটি প্রয়োগ করা অনেক সহজ
  • এটি বেশিরভাগ সাধারণ ক্ষেত্রে খুব দ্রুত
  • আরও জটিল পদ্ধতির অতিরিক্ত ওভারহেড (যেমন উচ্চতর মেমরির ব্যবহার / ক্যাশে চাপ) প্রায়শই ছোটখাটো তাত্ত্বিক লাভকে ছাড়িয়ে যায়
  • এটি ডেটা বিতরণে ভবিষ্যতের পরিবর্তনের জন্য আরও দৃust় হবে ....

1

এটি যথেষ্ট সহজ বলে মনে হচ্ছে:

আপনি যে ফ্লোটটি আবদ্ধ করতে চান তার জন্য বাইনারি অনুসন্ধান করুন - ও (লগ এন) সময়।

তারপরে বাম দিকের উপাদানটি নিম্ন আবদ্ধ এবং এর ডানদিকে উপাদানটি উপরের আবদ্ধ।


0

এর সুস্পষ্ট উত্তর হ'ল একটি গাছে ভাসমান ভান্ডার । 'পূর্ববর্তী' এবং 'পরবর্তী' ক্রিয়াকলাপগুলিকে কোনও গাছে ক্ষুদ্র। সুতরাং আপনার মানটির জন্য কেবল একটি 'পরবর্তী' করুন এবং তারপরে প্রথম ধাপে আপনি যে মান খুঁজে পাবেন তার উপর 'পূর্ববর্তী' করুন।


1
এটি মূলত বাইনারি অনুসন্ধানের মতো।
কেভিন ক্লাইনে

-1

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

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