leetcode51.N皇后:回溯算法與沖突檢測的核心邏輯

一、題目深度解析與N皇后問題本質

題目描述

n皇后問題研究的是如何將n個皇后放置在n×n的棋盤上,并且使皇后彼此之間不能相互攻擊。給定一個整數n,返回所有不同的n皇后問題的解決方案。每一種解法包含一個明確的n皇后問題的棋子放置方案,該方案中'Q''.'分別代表了皇后和空位。

核心特性分析

  1. 攻擊規則:皇后可以攻擊同一行、同一列、同一斜線上的棋子
  2. 約束條件:每行、每列、每條對角線上只能有一個皇后
  3. 解的形式:每個解是棋盤的一種合法布局,需返回所有可能解

二、回溯解法的核心實現與沖突檢測

完整回溯代碼實現

class Solution {List<List<String>> res = new ArrayList<>();  // 存儲所有合法布局public List<List<String>> solveNQueens(int n) {char[][] chessBoard = new char[n][n];  // 初始化棋盤for (char[] c : chessBoard) {Arrays.fill(c, '.');  // 填充空位}backtracking(n, 0, chessBoard);  // 從第0行開始回溯return res;}public void backtracking(int n, int row, char[][] chessBoard) {if (row == n) {  // 所有行處理完畢,找到一個解res.add(arrayToList(chessBoard));  // 轉換為List并存儲return;}for (int i = 0; i < n; i++) {  // 遍歷當前行的每一列if (isValid(n, row, i, chessBoard)) {  // 檢查當前位置是否合法chessBoard[row][i] = 'Q';  // 放置皇后backtracking(n, row + 1, chessBoard);  // 遞歸處理下一行chessBoard[row][i] = '.';  // 回溯:撤銷放置}}}// 將棋盤轉換為List<String>格式public List<String> arrayToList(char[][] chessBoard) {List<String> chessList = new ArrayList<>();for (char[] c : chessBoard) {chessList.add(String.copyValueOf(c));}return chessList;}// 檢查當前位置(row, col)是否可以放置皇后public boolean isValid(int n, int row, int col, char[][] chessBoard) {// 檢查列沖突:當前列上方是否有皇后for (int i = 0; i < row; i++) {if (chessBoard[i][col] == 'Q') {return false;}}// 檢查左上對角線沖突for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {if (chessBoard[i][j] == 'Q') {return false;}}// 檢查右上對角線沖突for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {if (chessBoard[i][j] == 'Q') {return false;}}return true;  // 無沖突,位置合法}
}

核心組件解析:

  1. 棋盤表示

    • 使用二維字符數組char[][] chessBoard表示棋盤
    • '.'表示空位,'Q'表示皇后
  2. 回溯函數

    • backtracking函數遞歸處理每一行
    • 每行選擇一個合法位置放置皇后,然后遞歸處理下一行
  3. 沖突檢測

    • isValid函數檢查當前位置是否與已放置的皇后沖突
    • 檢查范圍:當前列、左上對角線、右上對角線

三、回溯邏輯的核心流程與剪枝策略

1. 回溯算法的執行流程

關鍵步驟:
  1. 行優先處理:從第0行開始,逐行放置皇后
  2. 列遍歷選擇:對當前行的每一列進行檢查
  3. 合法性驗證:通過isValid函數檢查沖突
  4. 遞歸與回溯
    • 合法位置:放置皇后,遞歸處理下一行
    • 回溯操作:撤銷當前選擇,嘗試下一列
示例流程(n=4):
初始棋盤:
....
....
....
....處理第0行:
Q...  合法,遞歸處理第1行

2. 沖突檢測的核心邏輯

檢查范圍:
  • 列沖突:當前列上方是否有皇后
  • 左上對角線:從當前位置向左上方檢查
  • 右上對角線:從當前位置向右上方檢查
代碼實現:
// 列沖突檢查
for (int i = 0; i < row; i++) {if (chessBoard[i][col] == 'Q') return false;
}// 左上對角線檢查
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {if (chessBoard[i][j] == 'Q') return false;
}// 右上對角線檢查
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {if (chessBoard[i][j] == 'Q') return false;
}
為什么不檢查下方?
  • 由于回溯是按行處理,當前行下方的行尚未放置皇后,因此無需檢查

四、回溯過程深度模擬:以n=4為例

關鍵遞歸路徑:

  1. 初始狀態

    ....
    ....
    ....
    ....
    
    • 處理第0行,選擇第0列放置皇后
    Q...
    ....
    ....
    ....
    
    • 遞歸處理第1行
  2. 處理第1行

    • 第0列沖突(列沖突)
    • 第1列沖突(左上對角線沖突)
    • 第2列合法,放置皇后
    Q...
    ..Q.
    ....
    ....
    
    • 遞歸處理第2行
  3. 處理第2行

    • 所有列均沖突,回溯到第1行
  4. 回溯到第1行

    • 撤銷第1行第2列的皇后,選擇第3列
    Q...
    ...Q
    ....
    ....
    
    • 遞歸處理第2行
  5. 處理第2行

    • 第1列合法,放置皇后
    Q...
    ...Q
    .Q..
    ....
    
    • 遞歸處理第3行
  6. 處理第3行

    • 所有列均沖突,回溯到第2行
  7. 最終找到解

    .Q..
    ...Q
    Q...
    ..Q.
    
    ..Q.
    Q...
    ...Q
    .Q..
    

五、算法復雜度分析

1. 時間復雜度

  • O(n!)
    • 最壞情況下需要嘗試所有可能的排列
    • 每個解需要O(n)時間驗證合法性

2. 空間復雜度

  • O(n2)
    • 主要用于存儲棋盤狀態
    • 遞歸棧深度為O(n)

六、核心技術點總結:回溯與沖突檢測的協同設計

1. 回溯算法的關鍵點

  • 行優先策略:逐行處理,避免行沖突
  • 選擇與撤銷:合法位置放置皇后,回溯時撤銷選擇
  • 剪枝優化:通過合法性檢查提前排除無效路徑

2. 沖突檢測的高效實現

  • 三維約束檢查:列、左上對角線、右上對角線
  • 方向優化:僅檢查當前位置上方的區域,避免重復檢查

3. 解的轉換與存儲

  • 棋盤轉換:二維數組轉換為List
  • 深度復制:每次找到解時復制棋盤狀態,避免后續修改

七、常見誤區與優化建議

1. 忽略對角線檢查方向

  • 錯誤做法:檢查對角線時遍歷整個棋盤
    // 錯誤:檢查范圍過大
    for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {// ...檢查邏輯}
    }
    
  • 正確做法:僅檢查當前位置上方的對角線

2. 未進行深度復制

  • 錯誤做法:直接添加棋盤引用
    res.add(Arrays.asList(chessBoard)); // 錯誤:所有解指向同一對象
    
  • 正確做法:轉換為不可變List
    res.add(arrayToList(chessBoard)); // 正確:復制棋盤內容
    

3. 優化建議:位運算加速

// 使用三個整數表示列、左對角線、右對角線的占用情況
private void backtrack(int row, int cols, int diag1, int diag2) {if (row == n) {// 生成解的邏輯return;}// 計算當前行所有合法位置int availablePositions = ((1 << n) - 1) & (~(cols | diag1 | diag2));while (availablePositions != 0) {int p = availablePositions & (-availablePositions);availablePositions &= availablePositions - 1;int col = Integer.bitCount(p - 1);// 遞歸處理下一行backtrack(row + 1, cols | p, (diag1 | p) << 1, (diag2 | p) >> 1);}
}
  • 優勢:位運算將沖突檢測時間從O(n)降至O(1)
  • 適用場景:n較大時性能提升明顯

八、總結:回溯算法在約束滿足問題中的應用

本算法通過回溯法系統枚舉所有可能的皇后放置方案,核心在于:

  1. 回溯框架:逐行處理,選擇合法位置,遞歸下一行,回溯撤銷選擇
  2. 沖突檢測:高效檢查列、左上對角線、右上對角線沖突
  3. 解的收集:找到合法解時進行深度復制并存儲

理解這種解法的關鍵是把握回溯過程中狀態的變化路徑,以及如何通過沖突檢測剪枝無效路徑。N皇后問題是回溯算法在約束滿足問題中的典型應用,這種思路可擴展到數獨、八數碼等其他約束滿足問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86011.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86011.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

算法-每日一題(DAY9)楊輝三角

1.題目鏈接&#xff1a; 118. 楊輝三角 - 力扣&#xff08;LeetCode&#xff09; 2.題目描述&#xff1a; 給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。 在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。 示例 1: 輸入: numRo…

【MATLAB代碼】制導方法介紹與例程——追蹤法,適用于二維平面,目標是移動的|附完整源代碼

追蹤法(追蹤導引法)是一種常見的導彈導引方式,其基本原理是保持導彈的速度矢量始終指向目標。在追蹤法中,導彈的加速度可以表示為指向目標的加速度。 本文給出二維平面下,移動目標的追蹤法導引的介紹、公式與matlab例程 訂閱專欄后,可以直接查看完整源代碼 文章目錄 運行…

小白的進階之路系列之十八----人工智能從初步到精通pytorch綜合運用的講解第十一部分

從零開始的NLP:使用序列到序列網絡和注意力機制進行翻譯 我們將編寫自己的類和函數來預處理數據以完成我們的 NLP 建模任務。 在這個項目中,我們將訓練一個神經網絡將法語翻譯成英語。 [KEY: > input, = target, < output]> il est en train de peindre un table…

SSL安全證書:數字時代的網絡安全基石

SSL安全證書&#xff1a;數字時代的網絡安全基石 在當今數字化浪潮中&#xff0c;網絡通信安全已成為個人、企業和組織不可忽視的核心議題。SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接層&#xff09;安全證書作為保障數據傳輸安全的關鍵技術&#xff0c;通過加…

LLM-201: OpenHands與LLM交互鏈路分析

一、核心交互鏈路架構 #mermaid-svg-ZBqCSQk1PPDkIXNx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-icon{fill:#552222;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-text{fill:#552222;strok…

【項目】仿muduo庫one thread one loop式并發服務器SERVER模塊(下)

&#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f152; C 語言 | &#x1f310; 計算機網絡 |&#x1f5c3;? mysql 項目文章&#xff1a; 仿muduo庫one thread one loop式并發服務器…

數據庫索引結構 B 樹、B + 樹與哈希索引在不同數據查詢場景下的適用性分析

一、數據庫索引結構B樹 樹概述 樹是一種多路平衡查找樹&#xff0c;廣泛應用于數據庫和文件系統中。B樹的節點可以存儲多個數據元素&#xff0c;并且保持樹的平衡&#xff0c;以提高查詢效率。 適用性分析 在數據量較大&#xff0c;范圍查找較多的場景下&#xff0c;B樹的查詢效…

Linux進程間通信——信號

1.信號的介紹 信號( Signal )是 Unix, 類Unix以及其他POSIX兼容的操作系統中進程間通信的一種有限制的手段。 1&#xff09;信號是在軟件層面上對中斷機制的一種模擬&#xff0c;是一種異步通信方式。2&#xff09;信號可以直接進行用戶空間進程和內核進程之間的交互&#xff…

Bytemd@Bytemd/react詳解(編輯器實現基礎AST、插件、跨框架)

ByteMD Markdown編輯器詳細解釋&修改編輯器默認樣式&#xff08;高度300px) AST樹詳解 [ByteMD 插件系統詳解(https://blog.csdn.net/m0_55049655/article/details/148811248?spm1001.2014.3001.5501) Sevelet編寫的Bytemd如何適配到React中 ??1?? 背景概述 Byte…

《Redis》事務

文章目錄 Redis中的原子性Redis的事物和MySQL事務的區別Redis實現事務什么場景下&#xff0c;會使用事務? Redis事務相關命令watch命令的實現原理 總結 Redis中的原子性 Redis的原子性不同于MySQL的原子性。 Redis的事物和MySQL事務的區別 但是注意體會Redis的事務和MySQL…

Elasticsearch Kibana (一)

一、官方文檔 elasticsearch官網&#xff1a;elasticsearch官網 elasticsearch源碼&#xff1a;elasticsearch源碼 ik分詞器&#xff1a; ik分詞器 ik分詞器下載&#xff1a;ik分詞器下載 elasticsearch 版本選擇&#xff1a;elasticsearch 版本選擇 官方推薦Elasticsearch和j…

[linux] Ubuntu 24軟件下載和安裝匯總(自用)

經常重裝系統&#xff0c;備份下&#xff0c;有用的也可以參考。 安裝圖形界面 apt install ubuntu-desktop systemctl set-default graphical.target reboot 安裝chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt insta…

分布變化的模仿學習算法

與傳統監督學習不同,直接模仿學習在不同時刻所面臨的數據分布可能不同.試設計一個考慮不同時刻數據分布變化的模仿學習算法 import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset from…

arm-none-eabi-ld: cannot find -lm

arm-none-eabi-ld -Tuser/hc32l13x.lds -o grbl_hc32l13x.elf user/interrupts_hc32l13x.o user/system_hc32l13x.o user/main.o user/startup_hc32l13x.o -lm -Mapgrbl_hc32l13x.map arm-none-eabi-ld: cannot find -lm makefile:33: recipe for target link failed 改為在gcc…

【Python辦公】Excel文件批量樣式修改器

目錄 專欄導讀1. 背景介紹2. 項目概述3. 庫的安裝4. 核心架構設計① 類結構設計② 數據模型1) 文件管理2) 樣式配置5. 界面設計與實現① 布局結構② 動態組件生成6. 核心功能實現① 文件選擇與管理② 顏色選擇功能③ Excel文件處理核心邏輯完整代碼結尾專欄導讀 ?? 歡迎來到P…

QT的一些介紹

//雖然下面一行代碼進行widget和ui的窗口關聯&#xff0c;但是如果發生窗口大小變化的時候&#xff0c;里面的布局不會隨之變化ui->setupUi(this);//通過下面這行代碼進行顯示說明&#xff0c;讓窗口變化時&#xff0c;布局及其子控件隨之變化this->setLayout(ui->ver…

RISC-V向量擴展與GPU協處理:開源加速器設計新范式——對比NVDLA與香山架構的指令集融合方案

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;H卡級別算力&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生專屬優惠 當開源指令集遇上異構計算&#xff0c;RISC-V向量擴展&#xff08;RVV&#xff09;正重塑加速…

自動恢復網絡路由配置的安全腳本說明

背景 兩個文章 看了就明白 Ubuntu 多網卡路由配置筆記&#xff08;內網 外網同時通 可能有問題&#xff0c;以防萬一可以按照個來恢復 sudo ip route replace 192.168.1.0/24 dev eno8403 proto kernel scope link src <你的IP>或者恢復腳本! 如下 誤操作路由時&…

創建 Vue 3.0 項目的兩種方法對比:npm init vue@latest vs npm init vite@latest

創建 Vue 3.0 項目的兩種方法對比&#xff1a;npm init vuelatest vs npm init vitelatest Vue 3.0 作為當前主流的前端框架&#xff0c;官方提供了多種項目創建方式。本文將詳細介紹兩種最常用的創建方法&#xff1a;Vue CLI 方式 (npm init vuelatest) 和 Vite 方式 (npm in…

Java求職者面試指南:Spring, Spring Boot, Spring MVC, MyBatis技術點深度解析

Java求職者面試指南&#xff1a;Spring, Spring Boot, Spring MVC, MyBatis技術點深度解析 面試官與程序員JY的三輪提問 第一輪&#xff1a;基礎概念問題 1. 請解釋一下Spring框架的核心容器是什么&#xff1f;它有哪些主要功能&#xff1f; JY回答&#xff1a;Spring框架的…