DSA Interview Prep · पाठ

क्यू का कार्यान्वयन और Deque

Python के deque से क्यू बनाइए, circular queue लागू कीजिए और monotonic deque का उपयोग करके स्लाइडिंग-विंडो का अधिकतम मान निकालिए।

पाठ 2, कुल 4 में से13 चरण

क्यू का कार्यान्वयन और Deque, CoddyKit पर DSA Interview Prep का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह DSA Interview Prep सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

Queue डेटा संरचना

Queue फर्स्ट-इन, फर्स्ट-आउट (FIFO) डेटा संरचना है। इसमें सबसे पहले enqueue किया गया तत्व सबसे पहले dequeue होता है — ठीक किसी दुकान की भुगतान-पंक्ति की तरह। मुख्य संक्रियाएँ हैं enqueue (पिछले सिरे पर जोड़ना) और dequeue (अग्र सिरे से हटाना)। कतार को प्रभावी बनाने के लिए दोनों की जटिलता O(1) होनी चाहिए।

पाइथन की सूची को कतार के रूप में उपयोग करना आकर्षक, लेकिन गलत है: list.pop(0) O(n) होता है, क्योंकि सभी तत्वों को खिसकाना पड़ता है। सही साधन collections.deque है, जो O(1) में appendleft, append, popleft और pop उपलब्ध कराता है।

from collections import deque

queue = deque()

# Enqueue (add to rear)
queue.append(10)
queue.append(20)
queue.append(30)
print('Queue:', queue)          # deque([10, 20, 30])

# Peek front
print('Front:', queue[0])       # 10

# Dequeue (remove from front)
print('Dequeued:', queue.popleft())  # 10
print('Queue after:', queue)         # deque([20, 30])

deque का उपयोग करने वाली Queue क्लास

deque को नाम वाली संक्रियाओं के साथ एक Queue क्लास में लपेटिए, ताकि कार्यान्वयन साक्षात्कारकर्ता की अपेक्षाओं के अनुरूप हो। अंदर से enqueue, append को कॉल करता है और dequeue, popleft को कॉल करता है। peek संक्रिया queue[0] को हटाए बिना पढ़ती है।

from collections import deque

class Queue:
    def __init__(self):
        self._data = deque()

    def enqueue(self, val):
        self._data.append(val)

    def dequeue(self):
        if self.is_empty():
            raise IndexError('dequeue from empty queue')
        return self._data.popleft()

    def peek(self):
        if self.is_empty():
            raise IndexError('peek at empty queue')
        return self._data[0]

    def is_empty(self):
        return len(self._data) == 0

    def __len__(self):
        return len(self._data)

q = Queue()
q.enqueue(1); q.enqueue(2); q.enqueue(3)
print(q.peek())     # 1
print(q.dequeue())  # 1
print(len(q))       # 2

Queue के साथ BFS

कतार का प्रसिद्ध उपयोग चौड़ाई-प्रथम खोज (BFS) है। रूट को enqueue कीजिए; जब तक कतार खाली न हो, एक नोड को dequeue करके उसका प्रसंस्करण कीजिए और उसके उन पड़ोसी नोड को enqueue कीजिए जिन्हें अभी नहीं देखा गया है। नोड को स्तर-दर-स्तर संसाधित करने के कारण BFS बिना भार वाले ग्राफ में स्वाभाविक रूप से सबसे छोटा पथ ढूँढता है। कतार में हमेशा अधिकतम दो आस-पास के स्तरों के नोड होते हैं।

from collections import deque

def bfs(graph, start):
    visited = {start}
    queue   = deque([start])
    order   = []
    while queue:
        node = queue.popleft()
        order.append(node)
        for neighbour in graph[node]:
            if neighbour not in visited:
                visited.add(neighbour)
                queue.append(neighbour)
    return order

graph = {0:[1,2], 1:[0,3,4], 2:[0,5], 3:[1], 4:[1], 5:[2]}
print(bfs(graph, 0))  # [0, 1, 2, 3, 4, 5]

वृत्ताकार Queue (LeetCode 622)

LeetCode 622 ‘वृत्ताकार Queue का अभिकल्प’: ऐसी निश्चित-क्षमता वाली कतार लागू कीजिए जो घूमकर फिर शुरुआत पर आ सके। k आकार का एक ऐरे और दो पॉइंटर उपयोग कीजिए: head और tail। tail पर enqueue, head से dequeue कीजिए और स्थितियों की गणना k से मॉड्यूलो लेकर कीजिए। एक count चर पूर्ण और रिक्त स्थिति में अंतर करता है; अन्यथा k के मॉड्यूलो के अनुसार दोनों में head == tail होता है।

class MyCircularQueue:
    def __init__(self, k):
        self.data  = [0] * k
        self.head  = 0
        self.tail  = 0
        self.count = 0
        self.k     = k

    def enQueue(self, value):
        if self.isFull(): return False
        self.data[self.tail] = value
        self.tail  = (self.tail + 1) % self.k
        self.count += 1
        return True

    def deQueue(self):
        if self.isEmpty(): return False
        self.head  = (self.head + 1) % self.k
        self.count -= 1
        return True

    def Front(self):
        return -1 if self.isEmpty() else self.data[self.head]

    def Rear(self):
        return -1 if self.isEmpty() else self.data[(self.tail - 1) % self.k]

    def isEmpty(self): return self.count == 0
    def isFull(self):  return self.count == self.k

cq = MyCircularQueue(3)
print(cq.enQueue(1), cq.enQueue(2), cq.enQueue(3))  # True True True
print(cq.enQueue(4))   # False (full)
print(cq.Rear())       # 3
print(cq.isFull())     # True
print(cq.deQueue())    # True
print(cq.enQueue(4))   # True

एकरस डेक से स्लाइडिंग-विंडो का अधिकतम मान

LeetCode 239 ‘स्लाइडिंग-विंडो का अधिकतम मान’: k आकार की प्रत्येक विंडो के लिए अधिकतम तत्व ढूँढिए। सीधा तरीका O(n*k) का है। O(n) वाला तरीका सूचकांकों को रखने वाले घटते क्रम वाले एकरस डेक का उपयोग करता है। प्रत्येक नए तत्व के लिए: विंडो के बाहर के सूचकांकों को आगे से हटाइए; छोटे मान वाले सूचकांकों को पीछे से हटाइए, क्योंकि भविष्य की किसी भी विंडो में वे अधिकतम नहीं हो सकते। आगे वाला भाग हमेशा अधिकतम मान रखता है।

from collections import deque

def maxSlidingWindow(nums, k):
    dq     = deque()   # stores indices, decreasing values
    result = []
    for i, n in enumerate(nums):
        # Remove indices outside window
        while dq and dq[0] < i - k + 1:
            dq.popleft()
        # Remove smaller elements from back
        while dq and nums[dq[-1]] < n:
            dq.pop()
        dq.append(i)
        if i >= k - 1:
            result.append(nums[dq[0]])
    return result

print(maxSlidingWindow([1,3,-1,-3,5,3,6,7], 3))
# [3, 3, 5, 5, 6, 7]

Queue के लिए केवल सूची क्यों नहीं, डेक क्यों?

पाइथन का list.pop(0) O(n) में पहला तत्व हटाता है, क्योंकि हर बचे हुए तत्व को एक स्थान बाईं ओर खिसकाना पड़ता है। n बार जोड़ने और n बार हटाने पर कुल जटिलता O(n²) हो जाती है। collections.deque निश्चित आकार वाले खंडों की द्वि-लिंक्ड सूची है; popleft O(1) होता है, क्योंकि वह केवल एक पॉइंटर को समायोजित करता है। 10^5 नोड वाले ग्राफ पर BFS के लिए O(n) और O(n²) का अंतर 100 मिलीसेकंड और 100 सेकंड के बीच का अंतर है।

import timeit

n = 10000

# Using list (O(n) per popleft)
list_time = timeit.timeit(
    stmt='q = list(range(n)); [q.pop(0) for _ in range(n)]',
    globals={'n': n}, number=10
)

# Using deque (O(1) per popleft)
from collections import deque
deque_time = timeit.timeit(
    stmt='q = deque(range(n)); [q.popleft() for _ in range(n)]',
    globals={'n': n, 'deque': deque}, number=10
)

print(f'List:  {list_time:.4f}s')
print(f'Deque: {deque_time:.4f}s')
print(f'Speedup: {list_time / deque_time:.1f}x')

बाइनरी ट्री का स्तर-क्रम भ्रमण (LeetCode 102)

LeetCode 102 ‘बाइनरी ट्री का स्तर-क्रम भ्रमण’: सभी नोड मानों को स्तर-दर-स्तर लौटाइए। एक कतार का उपयोग कीजिए; प्रत्येक स्तर की शुरुआत में कतार का आकार दर्ज कीजिए, क्योंकि यही उस स्तर पर मौजूद नोडों की संख्या है। ठीक उतने नोड dequeue कीजिए, उनके मान एकत्र कीजिए और उनके बच्चों को enqueue कीजिए। कतार खाली होने तक इसे दोहराइए।

from collections import deque

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val   = val
        self.left  = left
        self.right = right

def levelOrder(root):
    if not root:
        return []
    result = []
    queue  = deque([root])
    while queue:
        level      = []
        level_size = len(queue)
        for _ in range(level_size):
            node = queue.popleft()
            level.append(node.val)
            if node.left:  queue.append(node.left)
            if node.right: queue.append(node.right)
        result.append(level)
    return result

root = TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7)))
print(levelOrder(root))  # [[3], [9, 20], [15, 7]]

heapq वाली प्राथमिकता कतार

पाइथन का heapq मॉड्यूल एक न्यूनतम-हीप (प्राथमिकता कतार) उपलब्ध कराता है: सबसे छोटा तत्व हमेशा पहले कतार से निकाला जाता है। heapq.heappush(h, item) O(log n) में एक तत्व जोड़ता है और heapq.heappop(h) O(log n) में न्यूनतम तत्व हटाता है। Dijkstra के एल्गोरिद्म और शीर्ष-k जैसी समस्याओं में, heapq साधारण कतार का स्थान लेता है।

import heapq

pq = []
heapq.heappush(pq, 5)
heapq.heappush(pq, 1)
heapq.heappush(pq, 3)
heapq.heappush(pq, 2)

print('Min:', heapq.heappop(pq))  # 1
print('Min:', heapq.heappop(pq))  # 2
print('Min:', heapq.heappop(pq))  # 3

# Tasks with priorities
tasks = [(2, 'send email'), (1, 'fix bug'), (3, 'write docs')]
heapq.heapify(tasks)
while tasks:
    priority, task = heapq.heappop(tasks)
    print(f'Priority {priority}: {task}')

वॉलपेपर पैटर्न: शब्द-सीढ़ी के लिए कतार

LeetCode 127 “शब्द-सीढ़ी”: केवल शब्दकोश के शब्दों का उपयोग करके, एक शब्द को दूसरे शब्द में बदलने के लिए आवश्यक न्यूनतम एक-अक्षर प्रतिस्थापन खोजिए। इसे ऐसे ग्राफ के रूप में मॉडल कीजिए जिसमें एक अक्षर के अंतर वाले शब्दों को किनारे जोड़ते हैं। इस ग्राफ पर BFS चलाने से O(n * L²) में सबसे छोटा मार्ग (न्यूनतम चरणों की संख्या) मिल जाता है, जहाँ n शब्दकोश का आकार और L शब्द की लंबाई है।

from collections import deque

def ladderLength(beginWord, endWord, wordList):
    word_set = set(wordList)
    if endWord not in word_set:
        return 0
    queue    = deque([(beginWord, 1)])
    visited  = {beginWord}
    while queue:
        word, steps = queue.popleft()
        for i in range(len(word)):
            for ch in 'abcdefghijklmnopqrstuvwxyz':
                new_word = word[:i] + ch + word[i+1:]
                if new_word == endWord:
                    return steps + 1
                if new_word in word_set and new_word not in visited:
                    visited.add(new_word)
                    queue.append((new_word, steps + 1))
    return 0

print(ladderLength('hit', 'cog', ['hot','dot','dog','lot','log','cog']))  # 5

डेक को दोनों सिरों वाली कतार के रूप में

collections.deque एक दोनों सिरों वाली कतार (डेक) है: आप इसके दोनों सिरों से कुशलतापूर्वक तत्व जोड़ और हटा सकते हैं। विधियाँ: आगे वाले सिरे के लिए appendleft और popleft; पीछे वाले सिरे के लिए append और pop। इससे डेक FIFO कतार (दाएँ सिरे पर जोड़ना + popleft) और LIFO स्टैक (append + pop), दोनों के रूप में काम कर सकता है। स्लाइडिंग विंडो का अधिकतम मान दोनों सिरों का उपयोग करता है: पुराने सूचकांकों को बाईं ओर से और छोटे मानों को दाईं ओर से हटाता है।

from collections import deque

dq = deque([3, 4, 5])

dq.appendleft(2)   # add to front: [2,3,4,5]
dq.appendleft(1)   # add to front: [1,2,3,4,5]
dq.append(6)       # add to rear:  [1,2,3,4,5,6]

print(dq.popleft())  # 1 (from front)
print(dq.pop())      # 6 (from rear)
print(list(dq))      # [2, 3, 4, 5]

सारांश: कतार बनाम डेक बनाम हीप

समस्या के अनुसार सही उपकरण चुनिए। FIFO प्रसंस्करण और BFS के लिए साधारण कतार (डेक) का उपयोग कीजिए। स्लाइडिंग विंडो का अधिकतम या न्यूनतम मान चाहिए तो मोनोटोनिक डेक का उपयोग कीजिए—यह कम उपयोगी तत्वों को हटाकर क्रमबद्धता की शर्त बनाए रखता है। क्रम चाहे जैसा हो, वैश्विक न्यूनतम या अधिकतम मान चाहिए तो प्राथमिकता कतार (heapq) का उपयोग कीजिए, जैसे Dijkstra के या शीर्ष-k समस्याओं में। किस उपकरण का उपयोग कब और क्यों करना है, यह जानना साक्षात्कारकर्ता द्वारा जाँची जाने वाली महत्वपूर्ण कुशलता है।

त्वरित जाँच

इस पाठ में डेटा संरचनाओं और एल्गोरिद्म—कोडिंग साक्षात्कार की तैयारी से जुड़ी अवधारणाओं की अपनी समझ जाँचिए।

पाठ का पुनरावलोकन

इस पाठ में आपने सीखा: collections.deque O(1) समय में कतार में जोड़ने और कतार से निकालने की सुविधा देता है, इसलिए पाइथन में यह सही कतार कार्यान्वयन है, BFS स्तर-दर-स्तर नोड संसाधित करने के लिए कतार का उपयोग करता है और भाररहित ग्राफ़ में सबसे छोटे मार्ग खोजता है, तथा मोनोटोनिक घटता हुआ डेक कम उपयोगी सूचकांकों को हटाकर O(n) में स्लाइडिंग विंडो का अधिकतम मान निकालता है। आगे हम मोनोटोनिक स्टैक पैटर्न को विस्तार से समझेंगे।

शुरुआत निःशुल्क

एआई शिक्षक के साथ Python सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
30
पाठ
120

अक्सर पूछे जाने वाले प्रश्न

क्या “क्यू का कार्यान्वयन और Deque” पाठ निःशुल्क है?

हाँ — DSA Interview Prep अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “क्यू का कार्यान्वयन और Deque” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“क्यू का कार्यान्वयन और Deque” में मैं क्या सीखूँगा?

Python के deque से क्यू बनाइए, circular queue लागू कीजिए और monotonic deque का उपयोग करके स्लाइडिंग-विंडो का अधिकतम मान निकालिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ DSA Interview Prep का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या DSA Interview Prep शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर DSA Interview Prep शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“क्यू का कार्यान्वयन और Deque” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस DSA Interview Prep पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर DSA Interview Prep पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. स्टैक का कार्यान्वयन और उपयोग
  2. क्यू का कार्यान्वयन और Deque
  3. Monotonic Stack पैटर्न
  4. स्टैक और क्यू का पारस्परिक अनुकरण
← DSA Interview Prep पर वापस जाएँ