python-leetcode 61.N皇后

題目:

按照國際象棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。

n?皇后問題?研究的是如何將?n?個皇后放置在?n×n?的棋盤上,并且使皇后彼此之間不能相互攻擊

給你一個整數?n?,返回所有不同的?n?皇后問題?的解決方案

每一種解法包含一個不同的?n 皇后問題?的棋子放置方案,該方案中?'Q'?和?'.'?分別代表了皇后和空位。


每個皇后必須位于不同行和不同列,因此將 N 個皇后放置在 N×N 的棋盤上,一定是每一行有且僅有一個皇后,每一列有且僅有一個皇后,且任何兩個皇后都不能在同一條斜線上。基于上述發現,可以通過回溯的方式尋找可能的解。

回溯的具體做法是:使用一個數組記錄每行放置的皇后的列下標,依次在每一行放置一個皇后。每次新放置的皇后都不能和已經放置的皇后之間有攻擊:即新放置的皇后不能和任何一個已經放置的皇后在同一列以及同一條斜線上,并更新數組中的當前行的皇后列下標。當?N?個皇后都放置完畢,則找到一個可能的解。當找到一個可能的解之后,將數組轉換成表示棋盤狀態的列表,并將該棋盤狀態的列表加入返回列表。

由于每個皇后必須位于不同列,因此已經放置的皇后所在的列不能放置別的皇后。第一個皇后有 N 列可以選擇,第二個皇后最多有 N?1 列可以選擇,第三個皇后最多有 N?2 列可以選擇(如果考慮到不能在同一條斜線上,可能的選擇數量更少),因此所有可能的情況不會超過?N!?種,遍歷這些情況的時間復雜度是?O(N!)。

為了降低總時間復雜度,每次放置皇后時需要快速判斷每個位置是否可以放置皇后,顯然,最理想的情況是在 O(1) 的時間內判斷該位置所在的列和兩條斜線上是否已經有皇后。

方法一:基于集合的回溯

為了判斷一個位置所在的列和兩條斜線上是否已經有皇后,使用三個集合 columns、diagonals?
1和 diagonals2分別記錄每一列以及兩個方向的每條斜線上是否有皇后。

列的表示法很直觀,一共有?N?列,每一列的下標范圍從?0?到?N?1,使用列的下標即可明確表示每一列。

如何表示兩個方向的斜線呢?對于每個方向的斜線,需要找到斜線上的每個位置的行下標與列下標之間的關系。

方向一的斜線為從左上到右下方向,同一條斜線上的每個位置滿足行下標與列下標之差相等,例如 (0,0) 和 (3,3) 在同一條方向一的斜線上。因此使用行下標與列下標之差即可明確表示每一條方向一的斜線。

方向二的斜線為從右上到左下方向,同一條斜線上的每個位置滿足行下標與列下標之和相等,例如 (3,0) 和 (1,2) 在同一條方向二的斜線上。因此使用行下標與列下標之和即可明確表示每一條方向二的斜線。

每次放置皇后時,對于每個位置判斷其是否在三個集合中,如果三個集合都不包含當前位置,則當前位置是可以放置皇后的位置。

class Solution(object):def solveNQueens(self, n):""":type n: int:rtype: List[List[str]]"""def generateBoard():  #生成棋盤board=[]  #用于存儲棋盤的每一行for i in range(n):  #遍歷所有行,按queens[i]記錄的位置放至Qrow[queens[i]]="Q"  #row 是 [".", ".", ".", "."](初始化的空白行)#queens[i]是皇后在當前行i的索引#在queens[i]位置放Q,queens[0] = 1(表示皇后在第 0 行的 第 1 列)#row = [".", "Q", ".", "."]board.append("".join(row))#將列表轉換為字符串,作為棋盤格的一行row[queens[i]]="."  #恢復row為初始狀態return board  #作為當前皇后排列的字符串表示def dfs(row):  #當前正在處理的行號(從 0 到 n-1)if row==n:  #所有行都放置完畢board=generateBoard() # 生成一個合法的棋盤solutions.append(board) #保存else:for i in range(n): #遍歷當前行 row 的所有列 iif i in columns or row-i in diagonal1 or row+i in diagonal2:#皇后的列, 記錄右下↘對角線 ,記錄左下↙對角線continue #若 i 被占用,直接跳過該列queens[row]=i  #錄當前行皇后放置的列號columns.add(i) #記錄當前列被占用diagonal1.add(row-i)#記錄對角線被占用diagonal2.add(row+i) #記錄對角線被占用dfs(row+1)#遞歸嘗試下一行的皇后擺放columns.remove(i)#回溯,撤銷當前位置的皇后diagonal1.remove(row-i)#回溯,撤銷對角線的占用狀態diagonal2.remove(row+i)solutions=[] #存儲所有合法的 N 皇后解法queens=[-1]*n #記錄每一行皇后的位置,初始化-1表示未放置columns=set([])#記錄被占用的列diagonal1=set([])diagonal2=set([])row=["."]*n         #用于構造棋盤,初始時所有行都是 "...." dfs(0)return solutions

時間復雜度:O(N!)其中?N?是皇后數量

空間復雜度:O(N)


方法二:基于位運算的回溯

方法一使用三個集合記錄分別記錄每一列以及兩個方向的每條斜線上是否有皇后,每個集合最多包含 N 個元素,因此集合的空間復雜度是 O(N)。如果利用位運算記錄皇后的信息,就可以將記錄皇后信息的空間復雜度從 O(N) 降到 O(1)。

具體做法是,使用三個整數 columns、diagonals?1?和 diagonals?2分別記錄每一列以及兩個方向的每條斜線上是否有皇后,

每個整數有?N?個二進制位。棋盤的每一列對應每個整數的二進制表示中的一個數位,其中棋盤的最左列對應每個整數的最低二進制位,最右列對應每個整數的最高二進制位。用?0?代表可以放置皇后的位置,1?代表不能放置皇后的位置。

棋盤的邊長和皇后的數量?N=8。如果棋盤的前兩行分別在第?2?列和第?4?列放置了皇后(下標從?0?開始),則棋盤的前兩行如下圖所示。

如果要在下一行放置皇后,哪些位置不能放置呢?我們用?0?代表可以放置皇后的位置,1?代表不能放置皇后的位置。新放置的皇后不能和任何一個已經放置的皇后在同一列,因此不能放置在第?2?列和第?4?列,對應?columns=00010100(2)?。

新放置的皇后不能和任何一個已經放置的皇后在同一條方向一(從左上到右下方向)的斜線上,因此不能放置在第 4 列和第 5 列,對應 diagonals?1??=00110000?(2)。其中,第?4?列為其前兩行的第?2?列的皇后往右下移動兩步的位置,第?5?列為其前一行的第?4?列的皇后往右下移動一步的位置。

新放置的皇后不能和任何一個已經放置的皇后在同一條方向二(從右上到左下方向)的斜線上,因此不能放置在第 0 列和第 3 列,對應 diagonals?2?=00001001。其中,第?0?列為其前兩行的第?2?列的皇后往左下移動兩步的位置,第?3?列為其前一行的第?4?列的皇后往左下移動一步的位置。

由此可以得到三個整數的計算方法:

  • 初始時,三個整數的值都等于?0,表示沒有放置任何皇后
  • 在當前行放置皇后,如果皇后放置在第?i?列,則將三個整數的第?i?個二進制位(指從低到高的第?i?個二進制位)的值設為?1
  • 進入下一行時,columns?的值保持不變,diagonals1??左移一位,diagonals2??右移一位,

    由于棋盤的最左列對應每個整數的最低二進制位,即每個整數的最右二進制位,因此對整數的移位操作方向和對棋盤的移位操作方向相反(對棋盤的移位操作方向是 diagonals 1?右移一位,diagonals?2?左移一位)。

?每次放置皇后時,三個整數的按位或運算的結果即為不能放置皇后的位置,其余位置即為可以放置皇后的位置。

class Solution(object):def solveNQueens(self, n):""":type n: int:rtype: List[List[str]]"""def generateBoard():  # 生成當前解對應的棋盤布局board = []  # 創建一個空列表用于存儲最終的棋盤解法for i in range(n):row[queens[i]] = "Q"board.append("".join(row))row[queens[i]] = "."return boarddef solve(row, columns, diagonals1, diagonals2):  # 當前正在放置皇后的行號, 已被占據的列,兩條對角線if row == n:  # 遞歸終止條件,說明所有皇后已放置完畢board = generateBoard()  # 生成棋盤布局,并存入 solutionssolutions.append(board)else:# (1 << n) - 1 生成 n 位全 1,表示所有列都可用,并計算當前可選的列availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2))while availablePositions:  # 遍歷所有可選的位置position = availablePositions & (-availablePositions)  # 取 availablePositions 的最低位 1,即當前可選的最左側列availablePositions = availablePositions & (availablePositions - 1)  # 移除當前選擇的位置,以便下次循環選擇下一個位置column = bin(position - 1).count("1")  # 計算當前皇后應放置的列索引,統計 1 的個數,得到列索引queens[row] = column  # 記錄 row 行的皇后放置在 column 列solve(row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1)  # 遞歸進入下一行,更新列和主副對角線solutions = []  # 存儲所有可能的 N 皇后解法queens = [-1] * n  # 記錄每行皇后的列索引,初始化為 -1 表示未放置row = ["."] * n  # 構造棋盤行,初始時所有單元格都是 "."solve(0, 0, 0, 0)  # 遞歸從第 0 行開始嘗試放置皇后,初始時所有列和對角線都是可用的return solutions

時間復雜度:O(N!)

空間復雜度:O(N)

作者:力扣官方題解
?


?

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

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

相關文章

Mybatis_Plus中的常用注解

目錄 1、TableName TableId TableId的type屬性 TableField 1、TableName 經過以上的測試&#xff0c;在使用MyBatis-Plus實現基本的CRUD時&#xff0c;我們并沒有指定要操作的表&#xff0c;只是在 Mapper接口繼承BaseMapper時&#xff0c;設置了泛型User&#xff0c;而操…

JavaScript函數知識點總結

JavaScript函數是一種可重復使用的代碼塊,它接受輸入值(參數)、執行特定任務,并返回輸出值。 1. 聲明函數 function greet(name) {return "Hello, " + name + "!"; }console.log(greet("Alice")); // 輸出: Hello, Alice! console.log( t…

分布式計算Ray框架面試題及參考答案

目錄 簡述 Ray 的架構設計核心組件及其協作流程 全局控制存儲(GCS)在 Ray 中的作用是什么?如何實現高可用性? 對比 Ray 的任務(Task)與 Actor 模型,說明各自適用場景 解釋 Ray 的 Object Store 如何實現跨節點數據共享與零拷貝傳輸 Ray 的分布式調度器如何實現毫秒級…

GitHub熱門RAG框架:讓大語言模型更智慧

檢索增強生成(RAG):提升大型語言模型能力的全新思路 隨著人工智能應用的不斷深入發展,如何讓大型語言模型(LLM)具備更強的上下文理解和實時響應能力成為了關鍵問題。檢索增強生成(Retrieval-Augmented Generation,RAG)正是在這一背景下應運而生的技術,它巧妙地結合了…

HTTP協議講解

概念&#xff1a; Hyper Text Transfer Protocol 超文本傳輸協議&#xff0c;規定了瀏覽器和服務器之間的數據傳輸規則 特點 基于TCP協議&#xff0c;面向連接&#xff0c;安全基于請求-響應模型的&#xff0c;一次請求對應一次響應無狀態的&#xff0c;對于事物沒有記憶能力…

全國節能宣傳周線上知識競賽

線上知識競賽|節能降碳知識知多少 引言 全國節能宣傳周舉辦的主題是“綠色低碳&#xff0c;節能先行”。國家節能中心會同相關單位共同打造了一款線上知識競賽小程序&#xff0c;學習節能知識&#xff0c;爭做節能達人。 1.小程序規則&#xff1a; 體力規則&#xff1a;每位…

【區塊鏈安全 | 第十八篇】類型之引用類型(二)

文章目錄 引用類型數組切片結構體 引用類型 數組切片 數組切片是對數組中連續部分的一個視圖。它的語法為 x[start:end]&#xff0c;其中 start 和 end 是表達式&#xff0c;結果類型為 uint256&#xff08;或者可以隱式轉換為 uint256&#xff09;。切片的第一個元素是 x[st…

GitHub上免費學習工具的精選匯總

以下是GitHub上免費學習工具的精選匯總&#xff0c;涵蓋編程語言、開發框架、數據科學、面試準備等多個方向&#xff0c;結合工具的功能特點、社區活躍度及適用場景進行分類推薦&#xff1a; 一、編程語言與開發框架 Web Developer Roadmap 簡介&#xff1a;為開發者提供全棧學…

[leetcode]2685. 統計完全連通分量的數量

題目鏈接 題意 給定無向圖&#xff0c;求完全連通分量 連通分量就是一個連通塊的意思 完全連通分量&#xff1a;就是一個連通塊中 &#xff0c;所有點之間都兩兩有邊相連 思路 一個完全聯通分量有n個點 那么應該有 C n 2 C_n^2 Cn2?條邊 并查集維護連通塊 檢查每個聯通分量…

使用LangChain Agents構建Gradio及Gradio Tools(3)——使用Langchain agents構建Gradio UI

使用LangChain Agents構建Gradio及Gradio Tools(3)——使用Langchain agents構建Gradio UI 本篇摘要16. 使用LangChain Agents構建Gradio及Gradio Tool16.3 使用Langchain agents構建Gradio UI16.3.1 創建代理16.3.2 創建Gradio UI16.3.3 運行demo參考文獻本章目錄如下: 《使…

項目實戰 - 用戶列表

用戶列表想要實現這樣的效果&#xff1a; 渲染數據&#xff1a; import React,{useState,useEffect} from react; import { Button,Table, Tag,Modal,Popover, Switch } from antd; import { EditOutlined,DeleteOutlined,ExclamationCircleOutlined } from ant-design/icons…

吾愛破解安卓逆向學習筆記(4p)

學習目標&#xff0c;了解安卓四大組件&#xff0c;activity生命周期&#xff0c;同時了解去除部分廣告和更新提示。 廣告類型 1.啟動頁廣告 2.更新廣告 3.橫幅廣告 安卓四大組件 組件描述Activity(活動)在應用中的一個Activity可以用來表示一個界面&#xff0c;意思可以…

【目標檢測】【深度學習】【Pytorch版本】YOLOV1模型算法詳解

【目標檢測】【深度學習】【Pytorch版本】YOLOV1模型算法詳解 文章目錄 【目標檢測】【深度學習】【Pytorch版本】YOLOV1模型算法詳解前言YOLOV1的模型結構YOLOV1模型的基本執行流程YOLOV1模型的網絡參數YOLOV1模型的訓練方式 YOLOV1的核心思想前向傳播階段網格單元(grid cell)…

Vue項目中Vuex在util引入,斷點存在default

示例代碼 // src/store/index.js import Vue from vue; import Vuex from vuex; ……Vue.use(Vuex); export default new Vuex.Store({…… })// src/utils/index.js import store from /store // 導入默認導出的 store export async function getDict() {store.state.userInf…

FALL靶機滲透實戰:從信息收集到特權升級的完整鏈分析

1.下載靶機&#xff0c;并在虛擬機中打開 2.用kali來確定該靶機的IP kali的IP&#xff1a;192.168.139.152 arp-scan -l 3.掃描端口 nmap -O 192.168.139.172 4.掃目錄 gobuster dir -u http://192.168.139.172 -x php,txt,html -w /usr/share/dirbuster/wordlists/directo…

談談常見的數據結構(如數組、鏈表、棧、隊列、哈希表、樹、圖)及其應用場景

一、數組&#xff08;Array&#xff09; 定義&#xff1a;連續存儲相同類型數據的線性結構&#xff0c;支持隨機訪問。 應用場景&#xff1a;列表渲染、數據緩存、算法處理 代碼示例&#xff1a; // 數組基本操作 const arr [1, 2, 3, 4]; arr.push(5); // O(1) 平均時間復雜…

Kafka 的高可用性

Kafka 的高可用性主要通過副本機制、ISR&#xff08;In-Sync Replicas&#xff09;列表和控制器 Broker 來實現。這些機制共同確保了 Kafka 集群在部分節點故障時仍然可以正常運行&#xff0c;數據不會丟失&#xff0c;并且服務不會中斷。 1. 副本機制 Kafka 的副本機制是其高…

力扣HOT100之矩陣:54. 螺旋矩陣

這道題之前在代碼隨想錄里刷過類似的&#xff0c;還有印象&#xff0c;我就按照當初代碼隨想錄的思路做了一下&#xff0c;結果怎么都做不對&#xff0c;因為按照代碼隨想錄的邊界條件設置&#xff0c;當行數和列數都為奇數時&#xff0c;最后一個元素無法被添加到數組中&#…

快速構建個人本地知識庫管理系統與實現RAG問答

文章目錄 摘要一、RAG 和知識庫簡介1、RAG2、知識庫 二、 工作流程三、系統架構設計文件結構知識庫構建模塊RAG 模塊用戶交互模塊 四、技術實現細節五、系統使用案例結論未來改進方向致謝 摘要 在當今信息爆炸的時代&#xff0c;快速準確地獲取知識變得尤為重要。本地 RAG&…

使用DeepSeek API進行情感分析:超簡單

文章目錄 1. 引言1.1 情感分析概述1.2 為什么選擇DeepSeek API1.3 本文目標 2. 技術方案對比2.1 傳統情感分析方法2.2 基于LLM的方法DeepSeek API優勢 3. DeepSeek 情感分析實戰3.1 Few-shot Learning方法3.2 完整的DeepSeek API調用示例3.3 案例演示 4. DeepSeek開發情感分析工…