গণনা সংক্রান্ত জটিলতা O (n ^ 4) কেন?


50
int sum = 0;
for(int i = 1; i < n; i++) {
    for(int j = 1; j < i * i; j++) {
        if(j % i == 0) {
            for(int k = 0; k < j; k++) {
                sum++;
            }
        }
    }
}

আমি বুঝতে পারছি না কখন কীভাবে j = i, 2i, 3i ... শেষ forলুপটি n বার চলে। আমি অনুমান করি যে আমি ঠিক বুঝতে পারি না যে আমরা কীভাবে ifবিবৃতিটির ভিত্তিতে সেই সিদ্ধান্তে পৌঁছেছি ।

সম্পাদনা: আমি জানি যে সমস্ত লুপের জন্য জটিলতাটি কীভাবে গণনা করতে হবে তা ছাড়া মোড অপারেটরের উপর ভিত্তি করে শেষ লুপটি কেন আমি বার বার চালায় ... আমি কেবল এটি দেখতে পাচ্ছি না i মূলত, কেন আমি% এর চেয়ে j% আমি উপরে যেতে পারি না?


5
আপনি একাধিক বৃহত কারণ দ্বারা এই কোডটির জটিলতা হ্রাস করতে পারেন । ইঙ্গিত : 1 থেকে n সংখ্যার যোগফল হ'ল ((n + 1) * n) / 2 ইঙ্গিত 2 : for (j = i; j < i *i; j += i)তারপরে আপনার মডিউলাস পরীক্ষার দরকার নেই (কারণ jএটি দ্বারা বিভাজনীয় হওয়ার নিশ্চয়তা রয়েছে i)।
এলিয়ট ফ্রিচ

1
ও () ফাংশন একটি বল-পার্কের ফাংশন তাই এই উদাহরণের কোনও লুপ জটিলতায় যুক্ত হচ্ছে। দ্বিতীয় লুপটি এন ^ 2 অবধি চলছে। যদি-বিবৃতি উপেক্ষা করা হয়।
ক্রিস্টোফ বাউয়ার

11
@ ক্রিসটফবাউর ifবিবৃতি একেবারেই উপেক্ষা করা হয় না । এই ifস্টেটমেন্টটির অর্থ জটিলতাটি ও (এন ^ 5) এর পরিবর্তে ও (এন ^ 4), কারণ এটি দ্বিতীয় লুপের প্রতিটি পুনরাবৃত্তির জন্য iবারের পরিবর্তে কেবলমাত্র অভ্যন্তরীণ লুপকে i*iসম্পাদন করে।
কেয়া 3

1
@ কেয়া 3 পুরোপুরি অংশটি মিস করেছে k < n^2o সুতরাং এটি হে (এন ^ 5) তবে জ্ঞান (বোঝার মাধ্যমে if) ও (এন ^ 4) পরামর্শ দেয়।
ক্রিস্টোফ বাউয়ার

1
যদি এটি কেবল কোনও শ্রেণীর অনুশীলন না হয় তবে দ্বিতীয়
লুপটির

উত্তর:


49

আসুন A, B এবং C লুপগুলি লেবেল করা যাক:

int sum = 0;
// loop A
for(int i = 1; i < n; i++) {
    // loop B
    for(int j = 1; j < i * i; j++) {
        if(j % i == 0) {
            // loop C
            for(int k = 0; k < j; k++) {
                sum++;
            }
        }
    }
}
  • লুপ এ ও ( এন ) বার পুনরাবৃত্তি করে ।
  • লুপ বি হে (iterates আমি 2 ) বার A -এর পুনরাবৃত্তির প্রতি । এই প্রতিটি পুনরাবৃত্তির জন্য:
    • j % i == 0 মূল্যায়ন করা হয়, যা O (1) সময় নেয়।
    • এই পুনরাবৃত্তির 1 / i তে , লুপ সি পুনরাবৃত্তির জন্য ও (1) কাজ করে জে বার পুনরাবৃত্তি করে। যেহেতু জে গড় ও ( i 2 ) হয়, এবং এটি কেবল লুপ বি এর 1 / i পুনরাবৃত্তির জন্য করা হয়, গড় ব্যয় হয় ও ( i 2  /  i ) = ও ( i )।

এই সমস্তগুলিকে একসাথে গুটিয়ে নিয়ে আমরা O ( n  ×  i 2  × (1 +  i )) = ও ( এন  ×  i 3 ) পাই । যেহেতু আমি গড় ও ( এন ), তাই এটি ও ( এন 4 )।


এর জটিল অংশটি বলছে যে ifঅবস্থাটি কেবল সময়ের 1 / i-র সত্য :

মূলত, কেন আমি% এর চেয়ে j% আমি উপরে যেতে পারি না?

আসলে, jউপরে যায় j < i * iনা, কেবল না j < i। তবে শর্তটি j % i == 0সত্য এবং যদি jএকাধিক হয় i

এর গুণিতক iপরিসীমা মধ্যে হয় i, 2*i, 3*i, ..., (i-1) * i। এর মধ্যে রয়েছে i - 1, সুতরাং i - 1লুপ বি পুনরাবৃত্তি i * i - 1বার সত্ত্বেও লুপ সি পৌঁছে যায় ।


2
ও (n × i ^ 2 × (1 + i)) এ কেন 1 + i?
একমাত্র

3
কারণ ifলুপ বি এর প্রতিটি পুনরাবৃত্তির ক্ষেত্রে শর্তটি ও (1) সময় নেয় এটি এখানে লুপ সি দ্বারা আধিপত্য বজায় রাখে, তবে আমি উপরে এটি গণনা করেছি যাতে এটি কেবল "আমার কাজ দেখায়"।
কেয়া 3

16
  • প্রথম লুপটি nপুনরাবৃত্তি গ্রহণ করে।
  • দ্বিতীয় লুপটি n*nপুনরাবৃত্তি গ্রহণ করে। কেস কল্পনা যখন i=n, তারপর j=n*n
  • তৃতীয় লুপটি nপুনরাবৃত্তি গ্রহণ করে কারণ এটি কেবলমাত্র মৃত্যুদন্ড কার্যকর করা হয় i, যেখানে সবচেয়ে খারাপ ক্ষেত্রে iআবদ্ধ হয় n

সুতরাং, কোড জটিলতা হ'ল ও (n × n × n × n)।

আমি আশা করি এটি আপনাকে বুঝতে সহায়তা করে।


6

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

for (int n = 1; n < 363; ++n) {
    int sum = 0;
    for(int i = 1; i < n; ++i) {
        for(int j = 1; j < i * i; ++j) {
            if(j % i == 0) {
                for(int k = 0; k < j; ++k) {
                    sum++;
                }
            }
        }
    }

    long cubic = (long) Math.pow(n, 3);
    long hypCubic = (long) Math.pow(n, 4);
    double relative = (double) (sum / (double) hypCubic);
    System.out.println("n = " + n + ": iterations = " + sum +
            ", n³ = " + cubic + ", n⁴ = " + hypCubic + ", rel = " + relative);
}

এটি কার্যকর করার পরে, এটি স্পষ্ট হয়ে ওঠে, জটিলতাটি আসলে n⁴। আউটপুট এর শেষ লাইনগুলি এর মতো দেখায়:

n = 356: iterations = 1989000035, n³ = 45118016, n = 16062013696, rel = 0.12383254507467704
n = 357: iterations = 2011495675, n³ = 45499293, n = 16243247601, rel = 0.12383580700180696
n = 358: iterations = 2034181597, n³ = 45882712, n = 16426010896, rel = 0.12383905075183874
n = 359: iterations = 2057058871, n³ = 46268279, n = 16610312161, rel = 0.12384227647628734
n = 360: iterations = 2080128570, n³ = 46656000, n = 16796160000, rel = 0.12384548432498857
n = 361: iterations = 2103391770, n³ = 47045881, n = 16983563041, rel = 0.12384867444612208
n = 362: iterations = 2126849550, n³ = 47437928, n = 17172529936, rel = 0.1238518469862343

এটি যা দেখায় তা হ'ল প্রকৃত n⁴এবং এই কোড বিভাগের জটিলতার মধ্যে প্রকৃত আপেক্ষিক পার্থক্য হ'ল কাছাকাছি মানের 0.124...(প্রকৃতপক্ষে 0.125) প্রতি অ্যাসিম্পটিক । যদিও এটি আমাদের সঠিক মূল্য দেয় না, আমরা নিম্নলিখিতটি অনুমান করতে পারি:

সময় জটিলতা হ'ল n⁴/8 ~ f(n)যেখানে fআপনার কার্য / পদ্ধতি।

  • বিগ ও স্বরলিপিটির উইকিপিডিয়া পৃষ্ঠাতে 'ফ্যামিলি অফ বাচম্যান – ল্যান্ডাউ স্বরলিপি' এর সারণিতে উল্লেখ করা হয়েছে যে ~দুটি অপারেন্ড পক্ষের সীমাটি সমান নির্ধারণ করে। বা:

    f asmptotically g এর সমান

(আমি উপরের আবদ্ধ বাদে 363 বেছে নিয়েছি, কারণ n = 362এটিই সর্বশেষ মান যার জন্য আমরা একটি বোধগম্য ফলাফল পাই After এর পরে, আমরা দীর্ঘ-স্থানকে অতিক্রম করি এবং আপেক্ষিক মানটি নেতিবাচক হয়ে যায়))

ব্যবহারকারী কেয়া 3 নিম্নলিখিত চিত্রগুলি আবিষ্কার করেছেন:

অ্যাসিম্পটোটিক ধ্রুবকটি ঠিক 1/8 = 0.125, উপায় দ্বারা; ওল্ফ্রাম আলফার মাধ্যমে এখানে সঠিক সূত্র


5
অবশ্যই, O (n⁴) * 0.125 = O (n⁴)। একটি ধনাত্মক ধ্রুবক ফ্যাক্টর দ্বারা রানটাইমকে গুণ করা অ্যাসিপটোটিক জটিলতা পরিবর্তন করে না।
ইলমারি করোনেন

এটা সত্য. তবে আমি আসল জটিলতার প্রতিফলন করার চেষ্টা করছিলাম, উপরের দিকের অনুমানটি নয়। যেহেতু আমি ও-স্বরলিপি ব্যতীত সময়ের জটিলতা প্রকাশের জন্য অন্য কোনও বাক্য গঠন খুঁজে পাইনি, আমি এটির পিছনে পড়ে গিয়েছিলাম। এটি এটি লিখতে 100% বুদ্ধিমানের নয়।
ট্র্যাফনএনএক্স

সময় জটিলতা বলার জন্য আপনি লিটল-ও স্বরলিপি ব্যবহার করতে পারেন n⁴/8 + o(n⁴)তবে n⁴/8 + O(n³)যেভাবেই বড় ও এর সাথে একটি কঠোর অভিব্যক্তি দেওয়া সম্ভব ।
কেয়া 3

@ ট্রাইফনএক্স বিগ ওএইচ একটি গাণিতিক দৃ concept় ধারণা। সুতরাং আপনি যা করছেন তা তহবিলের ভুল / অর্থহীন। অবশ্যই আপনি গাণিতিক ধারণাগুলি পুনরায় সংজ্ঞায়িত করতে মুক্ত, তবে এটি তখন আপনি কীটপতঙ্গ খোলার বড় ক্যান। একটি কঠোর প্রসঙ্গে এটি সংজ্ঞায়িত করার উপায়টি কেয়া 3 বর্ণিত, আপনি একটি আদেশকে "নিম্ন" করে যান এবং সেভাবে এটি সংজ্ঞায়িত করেন। (যদিও গণিতে আপনি সাধারণত পারস্পরিক ব্যবহার করেন)।
পল 23

আপনি সঠিক. আমি আবার নিজেকে সংশোধন করেছি। এই সময়, আমি হিসাবে Bachmann-মধ্যে Landau অক্ষপাতনের পরিবার সংজ্ঞায়িত একই সীমা প্রতি asymtotic বৃদ্ধি ব্যবহার, en.wikipedia.org/wiki/Big_O_notation#Little-o_notation । আমি আশা করি এটি
গণিতগতভাবে

2

ifজটিলতা পরিবর্তন না করে মুছে ফেলুন এবং মডুলো

মূল পদ্ধতিটি এখানে:

public static long f(int n) {
    int sum = 0;
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < i * i; j++) {
            if (j % i == 0) {
                for (int k = 0; k < j; k++) {
                    sum++;
                }
            }
        }
    }
    return sum;
}

যদি আপনি ifএবং মডুলো দ্বারা বিভ্রান্ত হন তবে আপনি jসরাসরি এ থেকে ঝাঁপিয়ে পড়ে কেবল তাদের রিফ্যাক্টর iকরতে 2*iপারেন 3*i...:

public static long f2(int n) {
    int sum = 0;
    for (int i = 1; i < n; i++) {
        for (int j = i; j < i * i; j = j + i) {
            for (int k = 0; k < j; k++) {
                sum++;
            }
        }
    }
    return sum;
}

জটিলতা গণনা করা আরও সহজ করার জন্য, আপনি একটি মধ্যস্থতাকার j2ভেরিয়েবল প্রবর্তন করতে পারেন , যাতে প্রতিটি লুপ ভেরিয়েবল প্রতিটি পুনরাবৃত্তিতে 1 দ্বারা বাড়ানো হয়:

public static long f3(int n) {
    int sum = 0;
    for (int i = 1; i < n; i++) {
        for (int j2 = 1; j2 < i; j2++) {
            int j = j2 * i;
            for (int k = 0; k < j; k++) {
                sum++;
            }
        }
    }
    return sum;
}

প্রতিটি পদ্ধতিতে ট্রিপলেট সর্বদা একই থাকে তা System.out.printlnপরীক্ষা করতে আপনি ডিবাগিং বা পুরাতন স্কুল ব্যবহার করতে পারেন i, j, k

ফর্ম এক্সপ্রেশন বন্ধ

অন্যদের দ্বারা উল্লিখিত হিসাবে, আপনি প্রথম n পূর্ণসংখ্যার যোগফল সমান n * (n+1) / 2( ত্রিভুজ সংখ্যাটি দেখুন ) ব্যবহার করতে পারেন । আপনি যদি প্রতিটি লুপের জন্য এই সরলীকরণটি ব্যবহার করেন তবে আপনি পাবেন:

public static long f4(int n) {
    return (n - 1) * n * (n - 2) * (3 * n - 1) / 24;
}

এটি স্পষ্টতই মূল কোডের মতো একই জটিলতা নয় তবে এটি একই মানগুলি দেয়।

আপনাকে প্রথমে শর্তাদি Google থাকে, তাহলে আপনি লক্ষ্য করতে পারে 0 0 0 2 11 35 85 175 322 546 870 1320 1925 2717 3731প্রদর্শিত "প্রথম ধরনের স্টারলিং সংখ্যার: S (ঢ +2, এন)।" 0শুরুতে দুটি এস যুক্ত করা হয়েছে। এর মানে sumহল প্রথম ধরনের স্টারলিং সংখ্যা s(n, n-2)


0

প্রথম দুটি লুপটি একবার দেখে নেওয়া যাক।

প্রথমটি সহজ, এটি 1 থেকে এন পর্যন্ত লুপিং। দ্বিতীয়টি আরও আকর্ষণীয়। এটি 1 থেকে আমি স্কোয়ারে যায়। আসুন কয়েকটি উদাহরণ দেখুন:

e.g. n = 4    
i = 1  
j loops from 1 to 1^2  
i = 2  
j loops from 1 to 2^2  
i = 3  
j loops from 1 to 3^2  

মোট, i and j loopsমিলিত আছে 1^2 + 2^2 + 3^2
প্রথম এন স্কোয়ারের যোগফলের জন্য একটি সূত্র রয়েছে n * (n+1) * (2n + 1) / 6, যা মোটামুটি O(n^3)

আপনার একটি সর্বশেষ রয়েছে k loopযা 0 থেকে লুপ হয় jযদি হয় এবং কেবল যদি j % i == 0। যেহেতু j1 থেকে যায় i^2, সময়ের j % i == 0জন্য সত্য i। যেহেতু i loopপুনরাবৃত্তি শেষ হয়েছে n, আপনার একটি অতিরিক্ত আছে O(n)

সুতরাং আপনার O(n^3)কাছ থেকে i and j loopsএবং অন্য একটি O(n)থেকে k loopমোট গ্র্যান্ড মোটO(n^4)


আমি জানি যে সমস্ত লুপের জন্য জটিলতাটি কীভাবে গণনা করতে হবে তা ছাড়া মোড অপারেটরের উপর ভিত্তি করে শেষ লুপটি কেন i বার সম্পাদন করে ... আমি কীভাবে তা দেখছি না। মূলত, কেন আমি% এর চেয়ে j% আমি উপরে যেতে পারি না?
ব্যবহারকারী 11452926

1
@ ব্যবহারকারী 11452926 আসুন আমি বলি যে আমি 5 বছর বয়সী ছিলাম, দ্বিতীয় লুপের 1 থেকে 25 পর্যন্ত যেতে হবে। তবে j % i == 0কেবল যখন j 5, 10, 15, 20 এবং 25 হয় 5 গুণ, i এর মানের মতো। যদি আপনি 5 x 5 বর্গক্ষেত্রে 1 থেকে 25 পর্যন্ত সংখ্যাগুলি লিখে রাখেন তবে কেবল 5 তম কলামে 5 দ্বারা বিভাজ্য সংখ্যাগুলি থাকবে This এটি কোনও সংখ্যার জন্য কাজ করে। 1 থেকে n ^ 2 নম্বর ব্যবহার করে n এর বর্গাকার আঁকুন। নবম কলামে n দ্বারা বিভাজ্য সংখ্যাগুলি থাকবে। আপনার n টি সারি রয়েছে, তাই n থেকে 1 থেকে n numbers 2 বিভাজ্য n সংখ্যাগুলি।
সিলভিউ বুর্কিয়া

ধন্যবাদ! বোধগম্য! যদি এটি 25 এর পরিবর্তে 24 এর মতো একটি স্বেচ্ছাসেবী সংখ্যা হয় তবে স্কোয়ার ট্রিকটি কি এখনও কাজ করবে?
ব্যবহারকারী 1145292626

5 আসে যখন iহিট হয় 25 , সুতরাং j1 থেকে 25 পর্যন্ত লুপ হয়, আপনি একটি স্বেচ্ছাসেবী সংখ্যা চয়ন করতে পারবেন না। যদি আপনার ২ য় লুপটি একটি নির্দিষ্ট সংখ্যায় চলে যায়, উদাহরণস্বরূপ 24 এর পরিবর্তে i * i, এটি একটি ধ্রুবক সংখ্যা হবে এবং এর সাথে বাঁধা থাকবে না n, তাই এটি হবে O(1)। আপনি যদি j < i * iবনাম সম্পর্কে চিন্তাভাবনা করেন j <= i * i, তবে এটি ততটা গুরুত্বপূর্ণ হবে না, যেমনটি হবে nএবং n-1অপারেশন হবে, তবে বিগ-ওহ স্বরলিপিতে উভয় অর্থO(n)
সিলভিউ বুর্শিয়া
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.