कोडिंग साक्षात्कार की तैयारी · पाठ

ग्राफ निरूपण और भ्रमण की तैयारी

adjacency list से निर्देशित और अनिर्देशित ग्राफ बनाइए, deque से BFS आरंभ कीजिए और स्टैक या पुनरावृत्ति से DFS चलाइए; देखे गए नोडों का रिकॉर्ड भी रखिए।

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

ग्राफ निरूपण और भ्रमण की तैयारी, CoddyKit पर कोडिंग साक्षात्कार की तैयारी का एक निःशुल्क पाठ है। यह 4 में से 1वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह कोडिंग साक्षात्कार की तैयारी सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

ग्राफ क्या है?

ग्राफ नोडों (शीर्षों) का ऐसा समूह है जो किनारों से जुड़ा होता है। ट्री के विपरीत, ग्राफ में चक्र, नोडों के बीच कई पथ और असंबद्ध घटक हो सकते हैं। ग्राफ सामाजिक नेटवर्क, सड़क मानचित्र, निर्भरता वृक्ष और वेब पृष्ठों के लिंक जैसी वास्तविक दुनिया की प्रणालियों का मॉडल बनाते हैं। लगभग हर जटिल प्रणाली-अभिकल्पना और एल्गोरिद्म साक्षात्कार में ग्राफ का उल्लेख होता है — इसलिए उनके निरूपण और भ्रमण में निपुण होना आवश्यक है।

# Graph terminology:
# - V: set of vertices (nodes)
# - E: set of edges
# - Directed graph: edges have direction (A -> B but not B -> A)
# - Undirected graph: edges are bidirectional
# - Weighted graph: edges have costs/weights
# - Cyclic: contains at least one cycle
# - Acyclic: no cycles (DAG = Directed Acyclic Graph)
# - Connected: every node reachable from every other
# - Disconnected: multiple isolated components
print('Graph: nodes + edges, directed/undirected, weighted/unweighted')

आसन्नता सूची का निरूपण

एक आसन्नता सूची प्रत्येक नोड के पड़ोसी नोडों की सूची संग्रहीत करती है। पाइथन में, प्रत्येक नोड को आसन्न नोडों की सूची से मैप करने वाले dict का उपयोग करें। साक्षात्कार की समस्याओं में यह सबसे सामान्य निरूपण है: O(V + E) स्थान (विरल ग्राफ़ के लिए कुशल), पड़ोसी नोडों पर पुनरावृत्ति करने के लिए O(degree), और हैश-समुच्चय वाले रूपांतर के साथ आसन्नता जाँचने के लिए औसतन O(1)। LeetCode की अधिकांश ग्राफ़ समस्याएँ इसी प्रारूप का उपयोग करती हैं।

from collections import defaultdict

# Build an undirected graph
def build_undirected(edges):
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)  # both directions
    return graph

edges = [(0,1), (0,2), (1,3), (2,3), (3,4)]
graph = build_undirected(edges)
print(dict(graph))
# {0:[1,2], 1:[0,3], 2:[0,3], 3:[1,2,4], 4:[3]}

# Directed graph: only one direction
def build_directed(edges):
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)  # only u -> v
    return graph

आसन्नता मैट्रिक्स का निरूपण

एक आसन्नता मैट्रिक्स V×V की द्वि-आयामी सारणी होती है, जहाँ matrix[i][j] = 1 (या एज का भार) तब होता है जब i से j तक कोई एज हो, और अन्यथा 0 होता है। यह O(1) में एज खोज उपलब्ध कराती है, लेकिन एजों की संख्या चाहे जो हो, O(V²) स्थान लेती है—विरल ग्राफ़ के लिए यह अपव्ययी है। इसे तब प्राथमिकता दी जाती है जब ग्राफ़ घना हो (बहुत-से एज हों) या एज के अस्तित्व की तेज़ जाँच अत्यंत महत्वपूर्ण हो, जैसे फ्लॉयड-वार्शल के सभी-युग्म सबसे छोटे पथों में।

# Adjacency matrix for 5 nodes
V = 5
matrix = [[0] * V for _ in range(V)]

edges = [(0,1), (0,2), (1,3), (2,3), (3,4)]
for u, v in edges:
    matrix[u][v] = 1
    matrix[v][u] = 1  # undirected

# Print the matrix:
for row in matrix:
    print(row)
# Neighbour check: O(1)
print('Edge 0-2:', bool(matrix[0][2]))  # True
print('Edge 0-4:', bool(matrix[0][4]))  # False

# Space: O(V^2) vs adjacency list O(V+E)
# Dense graph: matrix often better; sparse: list better

एज सूची का निरूपण

एक एज सूची सबसे सरल निरूपण है: केवल (स्रोत, गंतव्य) टपलों की एक सूची, जिसमें वैकल्पिक रूप से भार भी हो सकते हैं। यह O(E) स्थान लेती है और सभी एजों पर पुनरावृत्ति करना आसान बनाती है। हालाँकि, किसी नोड के पड़ोसियों को ढूँढ़ने के लिए सभी एजों को स्कैन करना पड़ता है: O(E)। एज सूचियों का उपयोग उन ग्राफ़ एल्गोरिदम में होता है जो सभी एजों पर ठीक-ठीक पुनरावृत्ति करते हैं, जैसे बेलमैन-फोर्ड (सभी एजों को n-1 बार शिथिल करें) और क्रुस्कल का न्यूनतम विस्तारी वृक्ष एल्गोरिदम।

# Weighted edge list: (source, destination, weight)
edge_list = [
    (0, 1, 4),
    (0, 2, 1),
    (1, 3, 1),
    (2, 3, 5),
    (3, 4, 3)
]

# Useful for:
# Bellman-Ford: iterate all edges n-1 times
# Kruskal's MST: sort by weight then union-find

# Sort by weight for Kruskal:
edge_list_sorted = sorted(edge_list, key=lambda e: e[2])
print('Sorted by weight:', edge_list_sorted)

# Finding neighbours: O(E) scan -- inefficient for traversal
node_0_neighbors = [v for u, v, w in edge_list if u == 0]
print('Node 0 neighbors:', node_0_neighbors)

BFS की तैयारी: कतार और विज़िट किए गए नोडों का समुच्चय

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

from collections import deque

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

from collections import defaultdict
graph = defaultdict(list)
for u, v in [(0,1),(0,2),(1,3),(2,3),(3,4)]:
    graph[u].append(v); graph[v].append(u)

print(bfs(graph, 0))  # [0, 1, 2, 3, 4]

DFS की तैयारी: स्टैक या पुनरावर्तन

DFS (गहराई-प्रथम खोज) पीछे लौटने से पहले प्रत्येक शाखा में जितना संभव हो उतना आगे तक अन्वेषण करता है। इसे पुनरावर्ती रूप से (कॉल स्टैक का उपयोग करके) या पुनरावृत्त रूप से (एक स्पष्ट स्टैक का उपयोग करके) लागू करें। चक्रीय ग्राफ़ के लिए दोनों में विज़िट किए गए नोडों का समुच्चय आवश्यक है। पुनरावृत्त रूप में पड़ोसियों को उल्टे क्रम में स्टैक पर रखा जाता है, ताकि पुनरावर्ती DFS के भ्रमण क्रम से मेल खाए, हालाँकि दोनों कार्यान्वयनों में अन्वेषण का क्रम अलग हो सकता है।

def dfs_recursive(graph, node, visited=None, order=None):
    if visited is None: visited = set(); order = []
    visited.add(node)
    order.append(node)
    for neighbour in graph[node]:
        if neighbour not in visited:
            dfs_recursive(graph, neighbour, visited, order)
    return order

def dfs_iterative(graph, start):
    visited = set()
    stack = [start]
    order = []
    while stack:
        node = stack.pop()
        if node in visited: continue
        visited.add(node)
        order.append(node)
        for neighbour in reversed(graph[node]):  # reverse for same order as recursive
            if neighbour not in visited:
                stack.append(neighbour)
    return order

print('Recursive DFS:', dfs_recursive(graph, 0))
print('Iterative DFS:', dfs_iterative(graph, 0))

BFS और DFS में से कब चुनें

जब आपको भाररहित ग्राफ़ में सबसे छोटा पथ (सबसे कम एजों वाला पथ) चाहिए या नोडों को स्तर-दर-स्तर संसाधित करना हो, तब BFS चुनें। जब आपको सभी पहुँच योग्य नोडों का अन्वेषण करना हो, चक्रों का पता लगाना हो, जुड़े हुए घटक ढूँढ़ने हों, टोपोलॉजिकल क्रमण करना हो या सभी पथों की सूची बनानी हो, तब DFS चुनें। व्यवहार में: BFS ‘सबसे छोटा/न्यूनतम हॉप’ के लिए और DFS ‘अस्तित्व/पहुँच-योग्यता/गणना’ के लिए।

# BFS use cases:
# - Shortest path in unweighted graph (fewest edges)
# - Level-order traversal
# - Word ladder (minimum transformations)
# - Clone graph

# DFS use cases:
# - Connected components (flood fill)
# - Cycle detection
# - Topological sort
# - All paths between two nodes
# - Maze solving (any path)
# - N-queens, Sudoku (backtracking)

# Both: O(V + E) time, O(V) space for visited
print('BFS: shortest hops | DFS: existence and enumeration')

LeetCode के इनपुट प्रारूपों से ग्राफ़

LeetCode की ग्राफ़ समस्याएँ अलग-अलग इनपुट प्रारूपों में आती हैं। एज सूची: [[0,1],[0,2]] — आसन्नता सूची बनाएँ। इंडेक्स-आधारित आसन्नता सूची: graph[i] i के पड़ोसी नोडों की सूची है। ग्रिड/मैट्रिक्स: m×n की द्वि-आयामी सारणी, जहाँ सेल नोड होते हैं और आसन्न सेल (ऊपर/नीचे/बाएँ/दाएँ) पड़ोसी होते हैं। संतानों वाले Node: Node(val, neighbors) जैसी कस्टम क्लासें। इन्हें पहचानें और पहले चरण में आसन्नता सूची में बदलें।

# Format 1: edge list -> adjacency list
def edges_to_adj(n, edges):
    graph = [[] for _ in range(n)]
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)
    return graph

# Format 2: 2D grid -> adjacency (implicit)
# Neighbours of (r, c): (r-1,c), (r+1,c), (r,c-1), (r,c+1)
DIRS = [(-1,0),(1,0),(0,-1),(0,1)]
def grid_neighbours(grid, r, c):
    rows, cols = len(grid), len(grid[0])
    return [(r+dr, c+dc) for dr, dc in DIRS
            if 0 <= r+dr < rows and 0 <= c+dc < cols]

grid = [[1,1,0],[0,1,1],[1,0,0]]
print('Neighbours of (0,0):', grid_neighbours(grid, 0, 0))
print('Neighbours of (1,1):', grid_neighbours(grid, 1, 1))

ग्रिड में विज़िट किए गए सेल चिह्नित करना

ग्रिड समस्याओं में विज़िट किए गए सेल का लेखा रखने के दो तरीके हैं। विकल्प A: (row, col) टपलों का अलग visited समुच्चय उपयोग करें — O(m*n) अतिरिक्त स्थान। विकल्प B: ग्रिड को उसी स्थान पर संशोधित करें और विज़िट किए गए सेल को एक संकेतक मान (जैसे '#' या 2) से चिह्नित करें, और आवश्यकता होने पर बाद में उन्हें पहले जैसा कर दें। उसी स्थान पर संशोधन करने वाला तरीका O(1) अतिरिक्त स्थान लेता है और क्षेत्र-भराव तथा द्वीपों की संख्या वाली समस्याओं में सामान्य है।

def num_islands(grid):
    if not grid:
        return 0
    rows, cols = len(grid), len(grid[0])
    count = 0

    def dfs(r, c):
        if r < 0 or r >= rows or c < 0 or c >= cols:
            return
        if grid[r][c] != '1':
            return
        grid[r][c] = '#'  # mark as visited (in-place)
        dfs(r+1, c); dfs(r-1, c)
        dfs(r, c+1); dfs(r, c-1)

    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == '1':
                dfs(r, c)
                count += 1
    return count

grid = [['1','1','0','0'],
        ['1','1','0','0'],
        ['0','0','1','0'],
        ['0','0','0','1']]
print(num_islands(grid))  # 3

एकाधिक स्रोतों के साथ BFS आरंभ करना

बहु-स्रोत BFS कतार में विज़िट किए गए चिह्न के साथ सभी स्रोत नोडों को आरंभ में जोड़कर एक साथ कई नोडों से शुरू होता है। इसका उपयोग ‘निकटतम 0 से दूरी’, ‘सड़ते संतरे’ और ‘दीवारें और द्वार’ जैसी समस्याओं में किया जाता है, जहाँ आपको किसी भी स्रोत नोड से सबसे छोटी दूरी चाहिए। बहु-स्रोत BFS O(V + E) में चलता है—एकल-स्रोत BFS के समान—क्योंकि प्रत्येक नोड को अब भी अधिकतम एक बार विज़िट किया जाता है।

from collections import deque

def rotting_oranges(grid):
    rows, cols = len(grid), len(grid[0])
    queue = deque()
    fresh = 0
    # Multi-source: all rotten oranges start at time=0
    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == 2:
                queue.append((r, c, 0))  # (row, col, time)
            elif grid[r][c] == 1:
                fresh += 1
    dirs = [(0,1),(0,-1),(1,0),(-1,0)]
    time = 0
    while queue:
        r, c, t = queue.popleft()
        for dr, dc in dirs:
            nr, nc = r+dr, c+dc
            if 0<=nr<rows and 0<=nc<cols and grid[nr][nc]==1:
                grid[nr][nc] = 2  # mark rotten
                fresh -= 1
                queue.append((nr, nc, t+1))
                time = t + 1
    return time if fresh == 0 else -1

print(rotting_oranges([[2,1,1],[1,1,0],[0,1,1]]))  # 4

ग्राफ़ का घनत्व और निरूपण का चुनाव

आसन्नता सूची और मैट्रिक्स में से चुनाव ग्राफ़ के घनत्व—E/V² के अनुपात—पर निर्भर करता है। विरल ग्राफ़ (E << V²) को आसन्नता सूचियों से लाभ होता है: मैट्रिक्स के O(V²) की तुलना में O(V+E) स्थान। घने ग्राफ़ (E ≈ V²) को आसन्नता मैट्रिक्स से लाभ होता है: सूचियों में O(degree) की तुलना में O(1) में एज खोज। साक्षात्कार की समस्याओं में आसन्नता सूचियाँ लगभग हमेशा सही चुनाव होती हैं, क्योंकि अधिकांश समस्याओं में विरल ग्राफ़ शामिल होते हैं।

# Graph density comparison:
# Sparse: social network (V=1B users, avg 200 friends)
#   E = 200 * 1B = 200B << V^2 = 10^18 -> adjacency list
# Dense: complete graph (every node connected to every other)
#   E = V*(V-1)/2 ≈ V^2 -> adjacency matrix

# Interview rule of thumb:
# - Default to adjacency list (defaultdict(list))
# - Use matrix only when asked about dense graph or O(1) edge lookup
# - Grid problems: use implicit adjacency (4-directional neighbours)

print('Sparse graph (E << V^2): use adjacency list')
print('Dense graph (E ~ V^2): consider adjacency matrix')

त्वरित जाँच

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

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

इस पाठ में आपने सीखा: ग्राफ़ के तीन निरूपण (आसन्नता सूची, मैट्रिक्स, एज सूची) और प्रत्येक को कब चुनना है, चक्रीय ग्राफ़ में अनंत लूप से बचने के लिए विज़िट किए गए समुच्चय के साथ BFS और DFS की तैयारी, तथा ग्रिड को उसी स्थान पर चिह्नित करने और बहु-स्रोत BFS जैसे व्यावहारिक प्रतिरूप। अब हम सबसे छोटे पथ और स्तरवार भ्रमण खोजने के लिए BFS लागू करेंगे।

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

एआई शिक्षक के साथ कोडिंग साक्षात्कार की तैयारी सीखें — निःशुल्क

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

पाठ्यक्रम
90
पाठ
360

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

क्या “ग्राफ निरूपण और भ्रमण की तैयारी” पाठ निःशुल्क है?

हाँ—“ग्राफ निरूपण और भ्रमण की तैयारी” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“ग्राफ निरूपण और भ्रमण की तैयारी” में मैं क्या सीखूँगा?

adjacency list से निर्देशित और अनिर्देशित ग्राफ बनाइए, deque से BFS आरंभ कीजिए और स्टैक या पुनरावृत्ति से DFS चलाइए; देखे गए नोडों का रिकॉर्ड भी रखिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ कोडिंग साक्षात्कार की तैयारी का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या कोडिंग साक्षात्कार की तैयारी शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

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

“ग्राफ निरूपण और भ्रमण की तैयारी” पाठ पूरा करने में कितना समय लगता है?

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

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

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

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

  1. ग्राफ निरूपण और भ्रमण की तैयारी
  2. BFS: सबसे छोटा पथ और स्तर-भ्रमण
  3. DFS: जुड़े घटक और Flood Fill
  4. निर्देशित और अनिर्देशित ग्राफ में चक्र पहचान
← कोडिंग साक्षात्कार की तैयारी पर वापस जाएँ