N-क्वीन्स और प्रतिबंध प्रसार
स्तंभों और विकर्णों के सेट का उपयोग करके O(1) प्रतिबंध-जाँच के साथ N×N बोर्ड पर N रानियाँ रखिए, और समाधानों को गिनने तथा सूचीबद्ध करने के अंतर पर चर्चा कीजिए।
N-क्वीन्स और प्रतिबंध प्रसार, CoddyKit पर कोडिंग साक्षात्कार की तैयारी का एक निःशुल्क पाठ है। यह 4 में से 4वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह कोडिंग साक्षात्कार की तैयारी सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
N-रानियों की समस्या
N-रानियों की समस्या (LeetCode 51/52) में N रानियों को N×N शतरंज-बिसात पर इस तरह रखना होता है कि कोई भी दो रानियाँ एक-दूसरे पर आक्रमण न कर सकें। रानियाँ पंक्तियों, स्तंभों और दोनों विकर्णों पर आक्रमण करती हैं। N=4 के लिए ठीक 2 समाधान हैं। N=8 (क्लासिक रूप) के लिए 92 समाधान हैं। यह शर्त-जाँच वाली बैकट्रैकिंग समस्या का आदर्श उदाहरण है, जो खोज-क्षेत्र को काफ़ी कम कर देती है।
# N-Queens constraints:
# 1. Exactly one queen per row
# 2. No two queens in the same column
# 3. No two queens on the same diagonal (top-left to bottom-right)
# 4. No two queens on the same anti-diagonal (top-right to bottom-left)
# For N=4, the 2 solutions:
sol1 = ['.Q..', '...Q', 'Q...', '..Q.']
sol2 = ['..Q.', 'Q...', '...Q', '.Q..']
print('N=4 solutions:')
for row in sol1: print(row)
print()
for row in sol2: print(row)प्रत्येक पंक्ति में एक रानी रखना
चूँकि कोई भी दो रानियाँ एक ही पंक्ति में नहीं हो सकतीं, इसलिए हम प्रत्येक पंक्ति में ठीक एक रानी रखते हैं। बैकट्रैकिंग पंक्ति-दर-पंक्ति चलती है और प्रत्येक पंक्ति के लिए एक स्तंभ चुनती है। इससे प्रत्येक रानी के लिए N² विकल्पों के बजाय प्रत्येक पंक्ति में केवल N स्तंभ रह जाते हैं, जिससे आरंभिक शाखाएँ N^N होती हैं — लेकिन शर्तें इस संख्या को बहुत कम कर देती हैं। पुनरावृत्ति की गहराई N होती है (प्रत्येक पंक्ति के लिए एक स्तर), और शाखा-गुणक अधिकतम N होता है।
def solve_n_queens(n):
results = []
queens = [] # queens[row] = column of queen in that row
def backtrack(row):
if row == n:
# Build the board representation
board = []
for r in range(n):
board.append('.' * queens[r] + 'Q' + '.' * (n - queens[r] - 1))
results.append(board)
return
for col in range(n):
if is_valid(row, col):
queens.append(col) # CHOOSE
backtrack(row + 1) # EXPLORE
queens.pop() # UNCHOOSE
def is_valid(row, col):
for r, c in enumerate(queens):
if c == col: return False # same column
if abs(row - r) == abs(col - c): return False # diagonal
return True
backtrack(0)
return results
print(len(solve_n_queens(4)), 'solutions for N=4') # 2
print(len(solve_n_queens(8)), 'solutions for N=8') # 92समुच्चयों से O(1) शर्त-जाँच
रखी गई सभी रानियों को स्कैन करके वैधता जाँचने में प्रत्येक संभावित स्थिति के लिए O(N) समय लगता है, जिससे सबसे खराब स्थिति में कुल एल्गोरिद्म O(N² × N!) हो जाता है। हम तीन समुच्चय बनाए रखकर प्रत्येक वैधता-जाँच को O(1) तक घटा सकते हैं: cols (व्यस्त स्तंभ), diag (ऊपरी-बाएँ से निचले-दाएँ विकर्णों के लिए पंक्ति-स्तंभ मान), और anti_diag (ऊपरी-दाएँ से निचले-बाएँ विकर्णों के लिए पंक्ति+स्तंभ मान)। एक ही विकर्ण पर स्थित रानियों के लिए पंक्ति − स्तंभ समान होता है; एक ही प्रति-विकर्ण पर स्थित रानियों के लिए पंक्ति + स्तंभ समान होता है।
def solve_n_queens_fast(n):
results = []
cols = set() # occupied columns
diag = set() # row - col (positive diagonal)
anti = set() # row + col (negative diagonal)
queens = []
def backtrack(row):
if row == n:
board = ['.' * c + 'Q' + '.' * (n-c-1) for c in queens]
results.append(board)
return
for col in range(n):
if col in cols or (row-col) in diag or (row+col) in anti:
continue # PRUNE: constraint violated
# CHOOSE
cols.add(col); diag.add(row-col); anti.add(row+col); queens.append(col)
backtrack(row + 1) # EXPLORE
# UNCHOOSE
cols.remove(col); diag.remove(row-col); anti.remove(row+col); queens.pop()
backtrack(0)
return results
print(len(solve_n_queens_fast(8))) # 92विकर्ण के अपरिवर्तांक की व्याख्या
विकर्ण से जुड़ी मुख्य बात: ऊपर-बाएँ से नीचे-दाएँ जाने वाले एक ही विकर्ण के सभी खानों में row - col का मान समान होता है। उदाहरण के लिए, (0,0), (1,1), (2,2) सभी में पंक्ति − स्तंभ = 0 होता है। एक ही प्रति-विकर्ण के सभी खानों में row + col समान होता है: (0,2), (1,1), (2,0) सभी में पंक्ति + स्तंभ = 2 होता है। ये स्थिर-अवस्था वाले अपरिवर्तांक हैं, जिनसे O(N) रैखिक स्कैन के बजाय O(1) समुच्चय-खोज द्वारा विकर्ण टकराव जाँचे जा सकते हैं।
# Visualise the diagonal invariants for a 4x4 board
n = 4
print('row-col values (same diagonal):')
for r in range(n):
print([r-c for c in range(n)])
print('row+col values (same anti-diagonal):')
for r in range(n):
print([r+c for c in range(n)])
# Verify: (0,0) and (2,2) share diag value 0
print('(0,0) diag:', 0-0, '| (2,2) diag:', 2-2) # both 0
# Verify: (0,2) and (2,0) share anti-diag value 2
print('(0,2) anti:', 0+2, '| (2,0) anti:', 2+0) # both 2समाधानों की गिनती: N-रानियाँ II
N-रानियाँ II (LeetCode 52) में केवल संख्या माँगी जाती है, बोर्ड नहीं। इससे थोड़ा अनुकूलन संभव होता है: बोर्ड बनाने का चरण छोड़कर केवल एक गणक बढ़ाएँ। समुच्चयों के बजाय बिट-मास्क का उपयोग करने से प्रत्येक क्रिया की गति लगभग-O(1) तक बढ़ाई जा सकती है। समाधानों की संख्या एक ही क्रम में नहीं बढ़ती: 1(N=1), 0(N=2), 0(N=3), 2(N=4), 10(N=5), 4(N=6), 40(N=7), 92(N=8)।
def total_n_queens(n):
count = [0]
cols = set(); diag = set(); anti = set()
def backtrack(row):
if row == n:
count[0] += 1
return
for col in range(n):
if col in cols or (row-col) in diag or (row+col) in anti:
continue
cols.add(col); diag.add(row-col); anti.add(row+col)
backtrack(row + 1)
cols.remove(col); diag.remove(row-col); anti.remove(row+col)
backtrack(0)
return count[0]
for n in range(1, 11):
print(f'N={n}: {total_n_queens(n)} solutions')गति के लिए बिट-मास्क N-रानियाँ
बहुत बड़े N के लिए बिट-मास्क वाला कार्यान्वयन काफ़ी तेज़ चलता है। तीन पूर्णांकों को बिट-मास्क के रूप में उपयोग करें: cols, left_diag (प्रत्येक पंक्ति पर बाईं ओर खिसकता है), right_diag (दाईं ओर खिसकता है)। उपलब्ध स्तंभ हैं ((1<<n)-1) & ~(cols|left_diag|right_diag)। प्रत्येक उपलब्ध स्तंभ को bit = available & -available (सबसे कम सेट बिट) से निकालें, फिर पुनरावृत्ति करें। बिट-स्तरीय क्रियाओं से प्रत्येक शर्त-जाँच के लिए O(1) समय प्राप्त होता है।
def total_n_queens_bitmask(n):
full = (1 << n) - 1 # all n columns set
count = [0]
def bt(cols, left_diag, right_diag):
if cols == full:
count[0] += 1
return
available = full & ~(cols | left_diag | right_diag)
while available:
bit = available & -available # lowest set bit
available &= available - 1 # remove lowest bit
bt(cols | bit,
(left_diag | bit) << 1,
(right_diag | bit) >> 1)
bt(0, 0, 0)
return count[0]
for n in range(1, 13):
print(f'N={n}: {total_n_queens_bitmask(n)}')बाधा प्रसार की अवधारणा
बाधा प्रसार साधारण छँटाई से आगे की प्रक्रिया है: किसी रानी को रखने के बाद, भविष्य की पंक्तियों में मौजूद सभी अमान्य स्थानों का तुरंत निष्कर्ष निकालकर उन्हें हटा दिया जाता है। यह हर उम्मीदवार की वैधता जाँचने से अधिक आक्रामक तरीका है — शाखा बनाने से पहले ही आप खोज क्षेत्र को सक्रिय रूप से सीमित कर देते हैं। इसका सबसे प्रसिद्ध उदाहरण SAT और सुडोकू समाधानकर्ताओं में आर्क संगति है, जहाँ एक अंक रखने पर उसी पंक्ति, स्तंभ और 3×3 खाने के विकल्प हट जाते हैं।
# Constraint propagation in Sudoku:
# After placing 5 in cell (0,0):
# - Row 0: no other cell can have 5
# - Column 0: no other cell can have 5
# - Box (0,0)-(2,2): no other cell can have 5
# This is propagated BEFORE branching further
# Simple demo: remaining valid columns after placing queens
def remaining_columns(n, queens):
cols = set(q for q in queens)
diags = set(r - q for r, q in enumerate(queens))
anti_diags = set(r + q for r, q in enumerate(queens))
row = len(queens)
return [c for c in range(n)
if c not in cols
and (row-c) not in diags
and (row+c) not in anti_diags]
print(remaining_columns(8, [0])) # valid cols for row 1 after placing col 0 in row 0सुडोकू समाधानकर्ता
सुडोकू बाधा प्रसार की मानक समस्या है। प्रत्येक खाली खाने में वैध अंकों के विकल्प वे होते हैं जो उसी पंक्ति, स्तंभ या 3×3 खाने में पहले से मौजूद नहीं हैं। बैकट्रैकिंग समाधानकर्ता पहले खाली खाने को ढूँढ़ता है, प्रत्येक वैध अंक को आज़माता है और पुनरावर्ती रूप से आगे बढ़ता है। यदि कोई विरोधाभास मिलता है (ऐसा खाली खाना जिसमें कोई वैध अंक न हो), तो पीछे लौटें। अच्छे सुडोकू समाधानकर्ता बैकट्रैकिंग से पहले बाधा प्रसार (पेंसिल चिह्न) भी लागू करते हैं।
def solve_sudoku(board):
def is_valid(r, c, num):
for i in range(9):
if board[r][i] == num: return False # row
if board[i][c] == num: return False # col
br, bc = (r//3)*3, (c//3)*3
for i in range(3):
for j in range(3):
if board[br+i][bc+j] == num: return False # box
return True
def backtrack():
for r in range(9):
for c in range(9):
if board[r][c] == '.':
for d in '123456789':
if is_valid(r, c, d):
board[r][c] = d
if backtrack(): return True
board[r][c] = '.'
return False # no valid digit found
return True # no empty cells: solved
backtrack()
return board
# Mini test with a solvable board (simplified)
print('Sudoku solver implemented')सर्वाधिक-बाधित चर की अनुमानी विधि
बाधा-संतुष्टि समस्याओं के लिए एक महत्वपूर्ण अनुकूलन यह है कि अगला चयन हमेशा सर्वाधिक-बाधित चर का करें (अर्थात् वह खाना जिसमें वैध विकल्पों की संख्या सबसे कम हो)। सुडोकू में, यदि किसी खाने में केवल 1 वैध अंक है, तो उसे तुरंत भरना अनिवार्य है — बैकट्रैकिंग की आवश्यकता नहीं होती। ऐसे खानों को पहले चुनने से खोज-वृक्ष की गहराई बहुत कम हो जाती है। यह AI बाधा प्रोग्रामिंग की न्यूनतम शेष मान (MRV) अनुमानी विधि है।
def solve_sudoku_mrv(board):
'''Find cell with fewest valid choices (MRV heuristic).'''
def valid_choices(r, c):
nums = set('123456789')
for i in range(9):
nums.discard(board[r][i])
nums.discard(board[i][c])
br, bc = (r//3)*3, (c//3)*3
for i in range(3):
for j in range(3):
nums.discard(board[br+i][bc+j])
return nums
def find_mrv():
best = (10, -1, -1, set()) # (choices_count, r, c, choices)
for r in range(9):
for c in range(9):
if board[r][c] == '.':
choices = valid_choices(r, c)
if len(choices) < best[0]:
best = (len(choices), r, c, choices)
return best[1], best[2], best[3]
def backtrack():
r, c, choices = find_mrv()
if r == -1: return True # no empty cells
for d in choices:
board[r][c] = d
if backtrack(): return True
board[r][c] = '.'
return False
backtrack()
return boardN-क्वीन्स समाधानों की संख्या की तालिका
N-क्वीन्स समाधानों की संख्या इस प्रसिद्ध क्रम का अनुसरण करती है: N=1: 1, N=2: 0, N=3: 0, N=4: 2, N=5: 10, N=6: 4, N=7: 40, N=8: 92, N=9: 352, N=10: 724। किसी बंद-रूप सूत्र की जानकारी नहीं है; संख्या की गणना करनी पड़ती है। N=27 के लिए लगभग 2.34 × 10^17 समाधान मौजूद हैं। साक्षात्कार के प्रश्नों में आमतौर पर N ≤ 9 पूछा जाता है। घातांकीय वृद्धि को समझने से यह स्पष्ट होता है कि बड़े N के लिए बिटमास्क अनुकूलन क्यों महत्वपूर्ण है।
def count_queens(n):
'''O(1) per constraint check using sets.'''
count = [0]
cols = set(); diag = set(); anti = set()
def bt(row):
if row == n: count[0] += 1; return
for col in range(n):
if col in cols or (row-col) in diag or (row+col) in anti: continue
cols.add(col); diag.add(row-col); anti.add(row+col)
bt(row+1)
cols.discard(col); diag.discard(row-col); anti.discard(row+col)
bt(0)
return count[0]
sequence = [count_queens(n) for n in range(1, 12)]
print('N-Queens counts:', sequence)
# [1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680]N-क्वीन्स बोर्ड का निर्माण
जब साक्षात्कारकर्ता वास्तविक बोर्ड लौटाने के लिए कहे (LeetCode 51), तो प्रत्येक बोर्ड को queens सूची से बनाएँ, जहाँ queens[r] पंक्ति r में रानी के स्तंभ को दर्शाता है। स्ट्रिंग का निर्माण: प्रत्येक पंक्ति के लिए '.' * col + 'Q' + '.' * (n - col - 1)। यह O(n²) निर्माण केवल पुनरावृत्ति-वृक्ष की पत्तियों पर किया जाता है (जब सभी N रानियाँ रखी जा चुकी हों), इसलिए यह समग्र जटिलता को प्रभावित नहीं करता।
def n_queens_boards(n):
results = []
queens = []
cols = set(); diag = set(); anti = set()
def build_board():
return ['.' * c + 'Q' + '.' * (n-c-1) for c in queens]
def bt(row):
if row == n:
results.append(build_board())
return
for col in range(n):
if col in cols or (row-col) in diag or (row+col) in anti: continue
cols.add(col); diag.add(row-col); anti.add(row+col); queens.append(col)
bt(row+1)
cols.remove(col); diag.remove(row-col); anti.remove(row+col); queens.pop()
bt(0)
return results
for board in n_queens_boards(4):
for row in board: print(row)
print()त्वरित जाँच
इस पाठ में दिए गए डेटा संरचनाओं और एल्गोरिदम — कोडिंग साक्षात्कार की तैयारी से जुड़े विचारों की अपनी समझ जाँचें।
पाठ का पुनरावलोकन
इस पाठ में आपने सीखा: N-क्वीन्स में प्रत्येक पंक्ति में एक रानी रखी जाती है और स्तंभों, विकर्णों (पंक्ति-स्तंभ) तथा प्रतिविकर्णों (पंक्ति+स्तंभ) के लिए समुच्चयों का उपयोग करके O(1) में बाधा जाँच की जाती है, बिटमास्क बाधा जाँच को और तेज़ करते हैं और लगभग O(1) प्रति क्रिया में सभी व्यवस्थाओं को खोजने देते हैं, तथा बाधा प्रसार (MRV अनुमानी विधि) हर बार सबसे अधिक बाधित चर को पहले चुनकर खोज को कम करता है। आगे हम लालची और DP तरीकों की तुलना करेंगे और सीखेंगे कि किसे कब लागू करना चाहिए।
एआई शिक्षक के साथ कोडिंग साक्षात्कार की तैयारी सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 90
- पाठ
- 360
अक्सर पूछे जाने वाले प्रश्न
क्या “N-क्वीन्स और प्रतिबंध प्रसार” पाठ निःशुल्क है?
हाँ—“N-क्वीन्स और प्रतिबंध प्रसार” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“N-क्वीन्स और प्रतिबंध प्रसार” में मैं क्या सीखूँगा?
स्तंभों और विकर्णों के सेट का उपयोग करके O(1) प्रतिबंध-जाँच के साथ N×N बोर्ड पर N रानियाँ रखिए, और समाधानों को गिनने तथा सूचीबद्ध करने के अंतर पर चर्चा कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ कोडिंग साक्षात्कार की तैयारी का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या कोडिंग साक्षात्कार की तैयारी शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर कोडिंग साक्षात्कार की तैयारी शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 4वाँ पाठ है।
“N-क्वीन्स और प्रतिबंध प्रसार” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस कोडिंग साक्षात्कार की तैयारी पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर कोडिंग साक्षात्कार की तैयारी पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- Backtracking साँचा: चुनें, खोजें, चयन हटाएँ
- उपसमुच्चय और पावर सेट
- क्रमचय और संचय
- N-क्वीन्स और प्रतिबंध प्रसार