স্ট্যাক ও কিউপড়তে ৫ মিনিট লাগবে

মনোটোনিক স্ট্যাক (Monotonic Stack)

এমন একটা স্ট্যাক যেটা সবসময় ছোট থেকে বড় সাজানেন থাকে — পরের বড় বা ছোট সংখ্যাটা ম্যাজিকের মতো খুঁজে দেয়
build: O(n)query: O(1)push: O(1) (অ্যামরটাইজড/গড়)pop: O(1) (অ্যামরটাইজড/গড়)space: O(n)

মনোটোনিক স্ট্যাক (Monotonic stack) হলো একটা সাধারণ স্ট্যাক, কিন্তু এর একটা মারাত্মক কড়া নিয়ম আছে: এর ভেতরের জিনিসগুলো সবসময় ছোট থেকে বড় (increasing) অথবা বড় থেকে ছোট (decreasing) ক্রমানুসারে সাজানেন থাকতে হবে।

এই নিয়ম বা অর্ডারটা ঠিক রাখার জন্য স্ট্যাকের আসল ট্রিকটা হলো: যখনই আপনি নতুন কোনো সংখ্যা স্ট্যাকে ঢোকাতে বা পুশ (push) করতে যাবেন, তার আগে ওই সিগন্যাল ভাঙার বা অর্ডার নষ্ট করার মতো যা কিছু আছে, সবগুলোকে স্ট্যাক থেকে পপ (pop) করে ঘাড় ধাক্কা দিয়ে বের করে দিতে হবে

নেক্সট গ্রেটার এলিমেন্ট (Next Greater Element) — সবচেয়ে কমন প্রবলেম

ধরুন আপনাকে একটা অ্যারে দেওয়া হলো [2, 1, 5, 3, 6]। এখন প্রত্যেকটা সংখ্যার জন্য তার ডান দিকের প্রথম বড় সংখ্যাটা খুঁজে বের করতে হবে।

  • ২-এর জন্য → ডান দিকের প্রথম বড় সংখ্যা হলো ৫
  • ১-এর জন্য → ডান দিকের প্রথম বড় সংখ্যা হলো ৫
  • ৫-এর জন্য → ডান দিকের প্রথম বড় সংখ্যা হলো ৬
  • ৩-এর জন্য → ডান দিকের প্রথম বড় সংখ্যা হলো ৬
  • ৬-এর জন্য → ডান দিকে আর কেউ নেই (none)

বোকার মতো দুটো লুপ চালিয়ে চেক করলে স্পিড হবে O(n²)। কিন্তু এই মনোটোনিক স্ট্যাক জাস্ট O(n) স্পিডেই পুরোটা সলভ করে দেবে!

Watch monotonic stack

← → অ্যারো কি (arrow key) ব্যবহার করুন · উপাদানগুলোতে ক্লিক করুন

অ্যালগরিদমটা কীভাবে কাজ করে?

অ্যারের বাঁ দিক থেকে ডান দিকে হাঁটতে থাকুন। সাথে একটা বড় থেকে ছোট (decreasing) স্ট্যাক রাখুন (যেখানে সবচেয়ে বড়টা নিচে আর ছোটটা ওপরে থাকে):

  1. প্রতিটা নতুন সংখ্যা x-এর জন্য চেক করুন: স্ট্যাকের একদম ওপরের সংখ্যাটা x-এর চেয়ে ছোট কি না। যদি ছোট হয়, তবে তাকে স্ট্যাক থেকে পপ (pop) করে বা বের করে দিন।
  2. এইভাবে পপ হওয়া প্রতিটা সংখ্যাই মূলত একটা সুসংবাদ পেলো: তারা সবাই তাদের নেক্সট গ্রেটার এলিমেন্ট (Next greater element) খুঁজে পেয়েছে, আর সেটা হলো ওই নতুন আসা x!
  3. পপ করার কাজ শেষ হলে (অথবা স্ট্যাক ফাঁকা হয়ে গেলে), x-কে স্ট্যাকের ভেতরে পুশ বা ঢুকিয়ে দিন।

এখানে হোয়াইল লুপ (while loop) থাকলেও পুরো কাজটাতে সময় লাগে O(n)। কারণ প্রতিটা সংখ্যা তার জীবনে বড়জোর একবার স্ট্যাকে ঢোকে আর একবার বের হয় — অর্থাৎ কোনো সংখ্যাকেই দুইবারের বেশি ঘাঁটাঘাঁটি করতে হয় না।

আরও কোথায় কাজে লাগে?

এই মনোটোনিক স্ট্যাক দিয়ে আরো অনেক ধামাকাদার প্রবলেম সলভ করা যায়:

  • নেক্সট স্মলার এলিমেন্ট (Next Smaller Element) — এর জন্য একটা increasing (ছোট থেকে বড়) স্ট্যাক ব্যবহার করা হয়।
  • হিস্টোগ্রামের সবচেয়ে বড় আয়তক্ষেত্র (Largest Rectangle in Histogram) — হিস্টোগ্রামের বারগুলোকে increasing অর্ডারে মেইনটেইন করা হয়।
  • বৃষ্টির জল ধরে রাখা (Trapping Rain Water) — দুই পাসের মনোটোনিক স্ট্যাক দিয়ে এটা সলভ করা যায়।
  • প্রতিদিনের তাপমাত্রা (Daily Temperatures) — নেক্সট গ্রেটার এলিমেন্টেরই একটা ক্লাসিক ভার্সন।

এই ধরনের সমস্যায় মনোটোনিক কিউ (Monotonic Queue) ভ্যারিয়েন্ট স্লাইডিং উইন্ডো max/min সমাধান করে।

দ্রষ্টব্য: স্ট্যাকের প্রতিটা সংখ্যা জীবনে বড়জোর একবার ঢোকে আর একবার বের হয় — আর এই জাদুকরী গুণের কারণেই প্রবলেমটা দেখতে নেস্টেড লুপের (nested loop) মতো মনে হলেও এর স্পিড কিন্তু লিনিয়ার বা O(n) থাকে।

Complexity

অ্যারে প্রোসেস করা (Build)
প্রতিটা এলিমেন্ট একবার পুশ এবং একবার পপ হয়
লিনিয়ার O(n)
মাথাপিছু খরচ (গড় বা Amortized)
সব অপারেশনের মোট স্পিড হিসাব করলে এমনটাই দাঁড়ায়
সাথে সাথে O(1)
বোকা বা ব্রুট ফোর্স পদ্ধতি
দুটো লুপ দিয়ে প্রতি জোড়া সংখ্যা চেক করা
কোয়াড্রেটিক O(n²)
জায়গা বা স্পেস (স্ট্যাক)
স্ট্যাকের ভেতর একবারে সর্বোচ্চ n-সংখ্যক এলিমেন্ট থাকতে পারে
সর্বোচ্চ n O(n)
Challenge

ছোট কুইজ

ধরি অ্যারেটা হলো [3, 1, 4, 1, 5]। এখানে ১ নম্বর ইনডেক্সে থাকা ১-এর জন্য 'Next greater element' বা ডান দিকের প্রথম বড় সংখ্যা কোনটা?

পড়া চালিয়ে যান