200000+ উপাদান যুক্ত 2 অ্যারে উপাদানগুলির ন্যূনতম পণ্য সন্ধান করার দ্রুততম উপায় way


13

আমি একটি অ্যারে আছে a[n]। নম্বরটি nআমাদের দ্বারা প্রবেশ করা হয়েছে। আমার ন্যূনতম পণ্যটি খুঁজে পেতে হবে a[i]এবং a[j]যদি:

1) abs(i - j) > k

2) a[i] * a[j]হ্রাস করা হয়

এখানে আমার সমাধান (খুব নিষ্পাপ):

#include <iostream>
using namespace std;
#define ll long long
int main() {
    ll n,k; cin >> n >> k;

    ll a[n]; for(ll i=0;i<n;i++) cin >> a[i];

    ll mn; bool first = true;

    for(ll i=0;i<n;i++) {
        for(ll j=0;j<n;j++) {
            if(i!=j)
            if(abs(i-j) > k) {
                if(first) {
                    mn = a[i]*a[j];
                    first = false;
                } else if(a[i]*a[j] < mn) mn = a[i]*a[j];
            }
        }
    }
    cout << mn << endl;
}

তবে আমি জানতে চাই যে দূরত্ব সহ কোনও ন্যূনতম পণ্য সন্ধানের কোনও দ্রুত উপায় আছে কিনা?


7
আমি কেন # বিটস / স্টাডিসি ++ অন্তর্ভুক্ত করব না? এবং সি ++ কেবল সংকলক এক্সটেনশান দ্বারা একটি পরিবর্তনশীল দৈর্ঘ্য অ্যারে সরবরাহ করে। আপনি ব্যবহার করছেন না কেন std::vector? @ শেফ - বাছাই করা মূল "দূরত্ব" সম্পর্ককে ধ্বংস করে দেবে।
ডেভিড সি র্যাঙ্কিন

3
কমপক্ষে চেকটি if (i!=j) if (abs(i - j) > k)বাদ দেওয়া যায়। কেবলমাত্র আই + কে + 1: এ অভ্যন্তরীণ লুপটি শুরু করুন for (ll j = i + k + 1; j < n; ++j)। প্রারম্ভিক উদাহরণস্বরূপ firstযদি এর সাথে চেক করা যায় তবে mnতাও মুছে ফেলা যায় mn = a[0] * a[k + 1];। (সম্ভবত, এই বুলেট-প্রুফ তৈরি করতে প্রথমে তার kবিরুদ্ধে চেক করা উচিত n)) তবে এটি এখনও ও (N²)। এটি অবশ্যই দ্রুত করণীয় হতে পারে ...
শেফ

2
@ পলম্যাককেনজি অনুগ্রহ করে সূচক দূরত্ব (বা সর্বাধিক) সহ সর্বনিম্ন পণ্যের জন্য প্রথম দশের মধ্যে দু'টির চেয়ে কম কার্যকর হিট ছাড়া একটি কোয়েরি দেখান ।
গ্রেইবার্ড

1
@ পলম্যাক কেঞ্জি "এই প্রশ্নের উত্তর দেখায় এমন কয়েক হাজার ইউআরএল লিঙ্ক না থাকলে সম্ভবত কয়েকশো রয়েছে।" - দয়া করে এই URL গুলির মধ্যে কমপক্ষে তিনটি ভাগ করুন।
ברקן ברקן

2
এই প্রশ্নটি কোথা থেকে এল? এটি কেবল পাতলা বাতাসে তৈরি কোনও কিছুর মতো শোনাচ্ছে না। আমি যদি এই "অনলাইন জাজ" সাইটের কোনও একটি থেকে অবাক হই তবে অবাক হব না। যদি তা হয় তবে সেই সমাধানগুলিতে সম্পূর্ণ সমাধান না হলে সম্ভবত সমস্যা সমাধানের জন্য দীর্ঘ আলোচনা করা হয়েছে।
পলম্যাঙ্কেনজি

উত্তর:


12

ধরে নিই যে শর্ত পূরণে কমপক্ষে একজোড়া উপাদান রয়েছে এবং এতে দুটি উপাদানের কোনও গুণই উপচে পড়েছে না, এটি Theta(n-k)সময় এবং Theta(1)স্থানের ক্ষেত্রে সবচেয়ে খারাপ-এবং সেরা ক্ষেত্রে করা যায়, এরকম কিছু দিয়ে:

auto back_max = a[0];
auto back_min = a[0];
auto best = a[0]*a[k+1];

for(std::size_t i=1; i<n-(k+1); ++i) {
    back_max = std::max(back_max, a[i]);
    back_min = std::min(back_min, a[i]);
    best = std::min(best, std::min(a[i+k+1]*back_max, a[i+k+1]*back_min));
}

return best;

সময় এবং স্থান উভয়ের জন্যই এ্যাসিম্পোটিকের সবচেয়ে খারাপ ক্ষেত্রে জটিলতার ক্ষেত্রে এটি সর্বোত্তম কারণ কারণ সর্বোত্তম পণ্যটি অন্তত দূরত্বের যে a[0]কোনও n-(k+1)উপাদানগুলির সাথে থাকতে পারে k+1, সুতরাং n-(k+1)সমস্যা সমাধানের জন্য কমপক্ষে পূর্ণসংখ্যক কোনও অ্যালগরিদম দ্বারা পড়তে হবে।


অ্যালগরিদমের পিছনে ধারণাটি নিম্নরূপ:

অনুকূল পণ্যটি দুটি উপাদান ব্যবহার করে a, ধরে নিন যে এগুলি হয় a[r]এবং a[s]। সাধারণতার ক্ষতি ছাড়াই আমরা ধরে নিতে পারি s > rযেহেতু পণ্যটি পরিবর্তনশীল।

সীমাবদ্ধতার কারণে এটি abs(s-r) > kবোঝায় s >= k+1। এখন sপ্রতিটি সূচক এই শর্তটি সন্তুষ্ট হতে পারে, তাই আমরা এই সূচকগুলি নিয়ে পুনরাবৃত্তি করি। iএটি দেখানো কোডটিতে পুনরাবৃত্তিটি শেষ , তবে এটি k+1সুবিধার জন্য স্থানান্তরিত হয়েছে (আসলে কোনও ব্যাপার নয়)। প্রতিটি পুনরাবৃত্তির জন্য আমাদের সর্বোত্তম i+k+1সূচক হিসাবে জড়িত অনুকূল পণ্যটি সন্ধান করতে হবে এবং এটি পূর্বের সেরা অনুমানের সাথে তুলনা করতে হবে।

এর সাথে যুক্ত হওয়ার সম্ভাব্য সূচকগুলি দূরত্বের প্রয়োজনীয়তার কারণে i+k+1সমস্ত সূচকগুলি ছোট বা সমান i। আমাদেরও এগুলি নিয়ে পুনরাবৃত্তি করা দরকার, তবে এটি অপ্রয়োজনীয় কারণ নির্ধারিত সময়ে ন্যূনতম a[i+k+1]*a[j]ওভারের পণ্যটির একঘেয়েতার কারণে সমান ( দু'জনের পক্ষে ন্যূনতম এবং সর্বাধিক উভয় অ্যাকাউন্টের জন্য সর্বনিম্ন গ্রহণ করা) একঘেয়েমিটির সম্ভাব্য দুটি দিকের লক্ষণ বা সমতুল্য)jimin(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))a[j]a[i+k+1]

সেট যেহেতু a[j]মান যার উপর আমরা এখানে নিখুত শুধু {a[0], ..., a[i]}যা কেবল এক উপাদান (দ্বারা growths, a[i]প্রতিটি পুনরাবৃত্তির মধ্যে) i, কেবলমাত্র আমরা ট্র্যাক রাখতে পারবেন max(a[j])এবং min(a[j])তাদের আপডেট যদি একক ভেরিয়েবল সঙ্গে a[i]বৃহত্তর অথবা পূর্ববর্তী অনুকূল মান চেয়ে কম। এটি কোড উদাহরণ সহ back_maxএবং back_minএর সাথে সম্পন্ন হয় ।

পুনরাবৃত্তির প্রথম ধাপ ( i=0) লুপে এড়িয়ে যায় এবং পরিবর্তে ভেরিয়েবলগুলির আরম্ভকরণ হিসাবে সম্পাদিত হয়।


3
@ গ্রেইবার্ড আমাকে এগুলি রাখার দরকার নেই, কারণ একটি সর্বোত্তম পণ্যের জন্য সম্ভাব্য প্রার্থীরা a[i+k+1]সর্বনিম্ন এবং সর্বোচ্চ।
আখরোট

আপনি ব্যাখ্যা করতে পারেন কেন আপনার উত্তরটিতে অ্যালগরিদম কাজ করে?
মিনাহানী

6

দ্রুততম সম্পর্কে নিশ্চিত নয় ।

আই <জে - কে ছাড়াই সহজ সমস্যার জন্য , সর্বনিম্ন পণ্য দুটি সবচেয়ে ছোট এবং বৃহত্তম উপাদানগুলির জুটির পণ্যগুলির মধ্যে।

সুতরাং, (নিম্নলিখিতটি খুব জটিল, আখরোটের উত্তর দেখুন )
(k
  বাল্ক যদি কে ≤ n • মিনিট প্রারম্ভিক একটি [0] * ক [কে + 1])

  • দুটি গতিশীল মিনম্যাক্স ডেটা স্ট্রাকচারকে উপরে এবং বাইরে p
    } এবং {এ [ জে ] দিয়ে শুরু করে প্লাসকে রাখুন কে }
  • প্রতিটি আমি 0 থেকে এন - কে - 1 এর জন্য
    • টুআই-তে একটি [ i ] যুক্ত করুন
    • বহির্মুখী থেকে একটি [ i + কে ] সরান

    • কমপক্ষে ( upToI ) × মিনিট ( আউটপুটকি ), মিনিট ( upToI ) × সর্বাধিক ( বহির্মুখী ),
      সর্বাধিক ( upToI ) × মিনিট ( বহির্মুখী ) এবং সর্বাধিক ( upToI ) × সর্বাধিক ( বহির্মুখী ) এর মধ্যে নতুন সর্বনিম্ন পণ্যের জন্য পরীক্ষা করুন

এটি দ্রুত, কমপক্ষে জটিলতার ভিত্তিতে হওয়া উচিত। এটি ও (এন) সময় এবং স্টোরেজ।
শ্রীমতী

মূল সমাধানটির জটিলতা রয়েছে (এন ** 2), আপনি কীভাবে আপনার সমাধানের জটিলতা অনুমান করবেন?
লেনিক

O (nlogn) সময়, O (n) স্পেস (উপযুক্ত মিনিম্যাক্স বাস্তবায়নের জন্য)
গ্রেইবার্ড

@greybeard। আপনার এন * লগইন সময় প্রয়োজন কেন। কেন কেবল একটি 4 * এন অ্যারে রয়েছে সেটা না রেখে minUpto, maxUpto, minBeyond, maxBeyond(আপনি দুই পুনরাবৃত্তিও মধ্যে তৈরি করতে পারেন)? তারপরে তৃতীয় পুনরাবৃত্তিতে প্রতিটি সূচকের জন্য, সর্বনিম্ন সম্ভাব্য গুণফলটি সন্ধান করুন।
শ্রীমতী

(@smttsp এটি আখরোটের সমাধানের দিকের বিকল্প পদক্ষেপ হবে ))
গ্রেইবার্ড

4

"সর্বনিম্ন প্রস্থ"

2 "ক্ষুদ্রতম মাত্রার" উপাদানগুলি সন্ধান করুন, তারপরে (আপনি দু'টি শূন্য খুঁজে পেয়েছেন বা পুরো অ্যারেটি অনুসন্ধান করার পরে) তাদের গুণ করুন।

abs(i - j) > kঅংশ ব্যতীত "সর্বনিম্ন মান" এর জন্য

3 টি সম্ভাবনা রয়েছে:

  • দুটি সর্বাধিক (ক্ষুদ্রতম মাত্রার) নেতিবাচক সংখ্যা

  • দুটি সর্বনিম্ন (ক্ষুদ্রতম মাত্রা) অ-নেতিবাচক সংখ্যা

  • সর্বনিম্ন (বৃহত্তম মাত্রা) নেতিবাচক সংখ্যা এবং সর্বাধিক (বৃহত্তম মাত্রা) অ-নেতিবাচক সংখ্যা

আপনি সমস্ত 6 টি মান খুঁজে পেতে এবং পণ্যগুলি বের করতে পারেন এবং কোনটি শেষ পর্যন্ত সেরা।

যাহোক; আপনি একটি শূন্য দেখতে পাওয়ার সাথে সাথেই আপনি জানেন যে প্রথম 2 সম্ভাবনা সম্পর্কে আপনাকে আর জানার দরকার নেই; এবং যত তাড়াতাড়ি আপনি একটি নেতিবাচক সংখ্যা এবং একটি অ-নেতিবাচক নম্বর দেখতে পাবেন আপনি জানেন যে আপনি কেবল তৃতীয় সম্ভাবনার বিষয়ে যত্নশীল।

এটি 3 টি রাষ্ট্রের একটি সীমাবদ্ধ রাষ্ট্রের মেশিনে নিয়ে যায় - "সমস্ত 3 সম্ভাবনার বিষয়ে যত্নশীল", "উত্তর শূন্য হয় যদি না কোনও নেতিবাচক সংখ্যা না দেখা হয়" এবং "কেবলমাত্র শেষ সম্ভাবনার বিষয়ে যত্নশীল"। এটি 3 টি লুপের সেট হিসাবে প্রয়োগ করা যেতে পারে, যেখানে gotoরাষ্ট্রটি (সীমাবদ্ধ রাষ্ট্রের মেশিনের) পরিবর্তন হলে লুপগুলির 2 টি অন্য লুপের মাঝখানে ( ) লাফ দেয় ।

বিশেষত, এটিকে অস্পষ্টভাবে কিছু দেখতে পাওয়া যায় (অচিহ্নিত):

   // It could be any possibility

   for(ll i=0;i<n;i++) {
       if(a[i] >= 0) {
            if(a[i] < lowestNonNegative1) {
                lowestNonNegative2 = lowestNonNegative1;
                lowestNonNegative1 = a[i];
            }
            if(lowestNonNegative2 == 0) {
                goto state2;
            }
       } else {
            if(a[i] > highestNegative1) {
                highestNegative2 = highestNegative1;
                highestNegative1= a[i];
            }
            if(lowestNonNegative1 < LONG_MAX) {
                goto state3;
            }
       }
   }
   if(lowestNonNegative2 * lowestNonNegative1 < highestNegative2 * highestNegative1) {
       cout << lowestNonNegative2 * lowestNonNegative1;
   } else {
       cout << highestNegative2 * highestNegative1;
   }
   return;

   // It will be zero, or a negative and a non-negative

   for(ll i=0;i<n;i++) {
state2:
       if(a[i] < 0) {
           goto state3;
       }
   }
   cout << "0";
   return;

   // It will be a negative and a non-negative

   for(ll i=0;i<n;i++) {
state3:
       if(a[i] < lowestNegative) {
           lowestNegative = a[i];
       } else if(a[i] > highestNonNegative) {
           highestNonNegative = a[i];
       }
    }
    cout << lowestNegative * highestNonNegative;
    return;

abs(i - j) > kঅংশটির সাথে "সর্বনিম্ন মান" এর জন্য

এই ক্ষেত্রে আপনার কাছে এখনও 3 টি সম্ভাবনা রয়েছে; এবং এটি একই "3 টি লুপস ফিনাইট স্টেট মেশিন সহ" পদ্ধতির সাথে কাজ করতে পারে তবে এটি খুব অগোছালো / কুরুচিপূর্ণ হয়। এই ক্ষেত্রে আরও ভাল বিকল্পের অ্যারে প্রাক-স্ক্যান করার সম্ভাবনা রয়েছে কিনা তা নির্ধারণ করার জন্য কোনও জিরো রয়েছে কিনা এবং সেগুলি যদি সমস্ত নেতিবাচক বা সমস্ত ধনাত্মক হয়; যাতে প্রাক-স্ক্যানের পরে আপনি উত্তরটি শূন্য কিনা তা জানতে পারবেন বা নির্দিষ্ট সম্ভাবনার জন্য এককভাবে তৈরি লুপটি নির্বাচন করতে পারেন।


1
সূচক পার্থক্যে নীচের বাউন্ডের কে এই অ্যাকাউন্টটি কোথায় ?
গ্রাইবার্ড

1
@ গ্রেইবার্ড: এটি (আমি সেই অংশটি মিস করেছি) না - কোডটি অ্যাকাউন্টে নেওয়ার জন্য কোডটি পরিবর্তন করা দরকার।
ব্রেন্ডন

আপনার কেন দুটি শূন্যের দরকার হবে ?
ট্রেন্টপি

@ ট্রেন্টপ: আরগ - আপনি ঠিক বলেছেন। উত্তরটি 0 বা একটি নেতিবাচক সংখ্যাটি জানার জন্য একটি শূন্যই যথেষ্ট।
ব্রেন্ডন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.