ইনভার্সন গণনা (Count Inversions)
ধরুন আপনি একটি গানের প্লেলিস্ট (playlist) তৈরি করেছেন এবং আপনার কোনো এক বন্ধু সেটিকে সম্পূর্ণ এলোমেলো করে দিয়েছে। তাদের সাজানো ভার্সনটি বা সংস্করণটি আপনার আসল প্লেলিস্টের থেকে কতটা আলাদা? এটি পরিমাপ করার একটি উপায় হতে পারে: ঠিক কত জোড়া গান ভুল আপেক্ষিক ক্রমানুসারে (wrong relative order) আছে তা গণনা বা হিসাব করা। যদি আপনার আসল প্লেলিস্টে গান A, গান B এর আগে থেকে থাকে, কিন্তু এখন গান B যদি গান A এর আগে চলে আসে — তবে এটি হলো একটি ইনভার্সন (inversion)। যত বেশি ইনভার্সন থাকবে, তার মানে হলো জিনিসগুলো ঠিক তত বেশি এলোমেলো হয়ে গেছে।
আনুষ্ঠানিকভাবে বলতে গেলে, একটি ইনভার্সন (inversion) হলো পজিশন বা অবস্থানের এমন একটি জোড়া (i, j) যেখানে i < j কিন্তু A[i] > A[j] — অর্থাৎ দুটি উপাদান বা এলিমেন্ট (elements) তাদের স্বাভাবিক ক্রমানুসারের বা অর্ডারের বাইরে অবস্থান করছে। একটি সম্পূর্ণ সাজানো বা সর্টেড অ্যারের ০ টি বা 0 ইনভার্সন থাকে। একটি সম্পূর্ণ বিপরীতভাবে বা উল্টোভাবে সাজানো (reversed) অ্যারের ক্ষেত্রে সর্বোচ্চ: n(n−1)/2 সংখ্যক ইনভার্সন থাকে (এর সম্ভাব্য প্রতিটি জোড়াই সাধারণ অর্ডারের বা ক্রমানুসারের বাইরে থাকে)।
লেইজি বা সাধারণ পদ্ধতি (The naive approach) — অতিমাত্রায় ধীরগতির
প্রতিটি জোড়াকে (i, j) চেক বা পরীক্ষা করুন যেখানে i < j। যদি A[i] > A[j] হয়, তবে এটি গণনা বা কাউন্ট (count) করুন। এটি বেশ সহজ একটি পদ্ধতি হলেও, এর কমপ্লেক্সিটি (complexity) হলো \(O(n^2)\) — অর্থাৎ এক মিলিয়ন বা দশ লক্ষ গানের জন্য, এটি এক ট্রিলিয়ন (trillion) বা এক লক্ষ কোটি বার তুলনা বা কম্পারিজন (comparisons) করবে।
চতুর অন্তর্দৃষ্টি (The clever insight): মার্জ সর্ট (merge sort) করার সময় গণনা করুন
এখানে আশ্চর্যের বা বোঝার বিষয়টি হলো: মার্জ সর্টের বা merge sort এর মার্জ করার ধাপটি আগে থেকেই ইনভার্সনগুলো ধরতে বা শনাক্ত করতে পারে — শুধু এটিকে এখন পর্যন্ত সেভাবে গণনা করা হয়নি, এই টুকুই যা পার্থক্য।
যখন দুটি সাজানো বা সর্টেড হওয়া অর্ধাংশ [Left] এবং [Right] কে মার্জ বা একত্রিত করা হয়, তখন যদি আমরা রাইট বা Right অংশ থেকে কোনো উপাদান বা এলিমেন্ট (element) বেছে নেই কারণ এটি বর্তমান লেফট বা Left উপাদানের বা এলিমেন্টের চেয়ে ছোট থাকে — তখন লেফটে থাকা অবশিষ্ট প্রতিটি এলিমেন্ট বা উপাদানই এর থেকে বড় হয় এবং আসল অ্যারেতে এটি তার আগেই আসার কথা ছিল। আর এখানকার প্রতিটি উপাদানই মূলত আমরা এইমাত্র বেছে নেওয়া রাইট বা Right উপাদানটির সাথে একটি করে ইনভার্সন (inversion) ঘটাবে।
সুতরাং: আপনি যখন রাইট বা Right থেকে অনুলিপি বা কপি করবেন, তখন ইনভার্সন কাউন্ট বা গণনার সাথে (Left এ থাকা বাকি বা অবশিষ্ট উপাদানগুলোর সংখ্যা) যোগ করে নিন। এটি কোনো অতিরিক্ত অ্যাসিম্পটোটিক (asymptotic) খরচ ছাড়াই মার্জ সর্টের বা merge sort এর স্কন্ধের ওপর ভর করে চলে — যার মানে এটি সর্বমোট \(O(n \log n)\) সময়েই তার কাজ সম্পন্ন করতে পারে।
উদাহরণের সাহায্যে পর্যালোচনা (Example walkthrough)
অ্যারে বা Array: [3, 1, 2]। এখানকার ইনভার্সনগুলো হলো (3,1) এবং (3,2) — অর্থাৎ কাউন্ট বা গণনা = 2।
মার্জ সর্ট (Merge sort) এটিকে [3] এবং [1, 2] তে বিভক্ত করে। Left=[3], Right=[1,2]। প্রথমত, আমরা Right থেকে 1 তুলি (1 < 3) — Left এ অবশিষ্ট থাকা 1 টি উপাদান যোগ করুন → কাউন্ট count += 1। তারপর Right থেকে 2 তুলি (2 < 3) — Left এ অবশিষ্ট থাকা 1 টি উপাদান যোগ করুন → কাউন্ট count += 1। মোট বা Total = 2। একদম সঠিক উত্তর!
মডিফাইড বা পরিবর্তিত মার্জ সর্টের সাহায্যে ইনভার্সন গণনা (Count Inversions via Modified Merge Sort)
Complexity
ছোট কুইজ
পড়া চালিয়ে যান