【算法數據結構】leetcode37 解數獨


37. 解數獨 - 力扣(LeetCode)

題目描述:

題目要求每一行 ,每一列,每個3*3 的子框只能出現一次。每個格子的數字范圍1-9.

需要遍歷每個空格填入可能的數字,并驗證符合規則。如果符合就填入,不符合就回溯。

解法:?

回溯算法通常用于解決這種需要試錯的問題。當發現當前路徑無解時候,返回上一步重新選擇。

需要遍歷每個空格,找到需要填寫的空格,對每個空格嘗試填入1-9,檢查這個數字是否滿足行,列 ,子框的要求。如果滿足就填入這個數字,遞歸進行下一個空格,如果后續處理中,發現無法填入下去,就需要回溯。恢復這個空格的狀態,嘗試下一個可能的數字。

檢查某個數字是否可以填入當前位置

對于 位置(i,i)需要檢查i 行,j 列,所在的子框是否有這個數字,屬于第幾個子框可以用 (i/3 )*3,(j/3 )*3來確定 。i=4? ?4/3=1? ? 1*3=3?? ?,起始行是3 ,遍歷這個3*3的子框。

對于每個空格最多檢查1-9個數字。,每個數字需要檢查三個方向,最壞情況可能出現重復檢查。

優化方法

用哈希表或者數據記錄行,列,子框。已經出現的數字。用3個二維數組,記錄rowi 表示第i行是否存在數組num,colj 表示第j 列是否存在數據num,boxk 表示第k 個子框中是否存咋這個數字num,

k 可以通過? i//3*3 +j//3 來計算?

i=0 ,j=0? ?,k=0

i=3,j=3 ,k=4? 在第四個子框。

預處理這三個數組,遍歷整個數獨,對這個對每個非空的格子,將對應的行列,子框中蓋數字標記為存在。比如broad_i 為5 ,那么需要row_i? 設置為true ,col_j 設置為true ,box_k (k為子框的索引)設置為true。

對每個空格嘗試填入1-9 數字中的一個,

初始化? 9X10 數組 其中索引 0不用?

步驟

1. 預處理三個數組row、col、box,記錄每個行、列、子框中已經存在的數字。

2. 收集所有需要填寫的空格的位置,存入一個列表spaces。

3. 編寫一個回溯函數,參數是當前處理到spaces中的第pos個位置。當pos等于spaces的長度時,說明已經填完所有空格,返回True。

4. 對于當前處理的空格位置(i,j),嘗試填入1到9中的一個數字d。如果該數字滿足row[i][d]、col[j][d]、box[k][d]都為False,那么將該數字填入,并更新這三個數組的狀態。然后遞歸處理pos+1的位置。如果遞歸返回True,說明后續的填寫都成功,那么當前的選擇是正確的,直接返回True。如果遞歸返回False,則說明后續無法完成,需要回溯,恢復三個數組的狀態,并將board[i][j]恢復為'.',然后嘗試下一個數字。

5. 如果所有數字都嘗試過且都不行,則返回False,觸發上一層遞歸的回溯。

這樣,當遞歸函數返回True時,說明已經找到解,此時board已經被正確填充。

    # 初始化 3個數組row = [[False] * 10 for i in range(9)]print(row)  # 每行十個元素col = [[False] * 10 for i in range(9)]box = [[False] * 10 for i in range(9)]

[[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False]]

?遍歷數組填充已經有的數字 spaces 用于記錄空格的位置

# 遍歷整個數組 記錄每個行 ,列子框中已經存在的數字spaces = []for i in range(9):for j in range(9):if board[i][j] != '.':d = int(board[i][j])row[i][d] = Truecol[j][d] = Truek = (i // 3) * 3 + (j // 3)box[k][d] = True  # 第k 個箱子的d 是否存在# 保存空格的位置到spaceselse:spaces.append((i, j))print("空格的位置", spaces)

空格的位置 [(0, 2), (0, 3), (0, 5), (0, 6), (0, 7), (0, 8), (1, 1), (1, 2), (1, 6), (1, 7), (1, 8), (2, 0), (2, 3), (2, 4), (2, 5), (2, 6), (2, 8), (3, 1), (3, 2), (3, 3), (3, 5), (3, 6), (3, 7), (4, 1), (4, 2), (4, 4), (4, 6), (4, 7), (5, 1), (5, 2), (5, 3), (5, 5), (5, 6), (5, 7), (6, 0), (6, 2), (6, 3), (6, 4), (6, 5), (6, 8), (7, 0), (7, 1), (7, 2), (7, 6), (7, 7), (8, 0), (8, 1), (8, 2), (8, 3), (8, 5), (8, 6)]


d = int(board[i][j])? 填充的數字作為下標

? row:? row[i][d]=True

[[False, False, False, True(3), False, True(5), False, True(7), False, False],[False, True(1), False, False, False, True(5), True(6), False, False, True(9)],[False, False, False, False, False, False, True(6), False, True(8), True(9)], 
[False, False, False, True(3), False, False, True(6), False, True(8), False],[False, True(1), False, True(3), True(4), False, False, False, True(8), False],[False, False, True(2), False, False, False, True(6), True(7), False, False], 
[False, False, True(2), False, False, False, True(6), False, True(8), False],[False, True(1), False, False, True(4), True(5)), False, False, False, True(9)],[False, False, False, False, False, False, False, True(7), True(8), True(9)]]

col : col[j][d]=true? ?縱坐標作為 行 d作為列?

第一列? ?4 5? 6 7 8

?[False, False, False, False, True(4), True(5), True(6), True(7), True(8), False]

[[False, False, False, False, True(4), True(5), True(6), True(7), True(8), False], 
[False, False, False, True, False, False, True, False, False, True], 
[False, False, False, False, False, False, False, False, True, False],[False, True, False, False, True, False, False, False, True, False],[False, True, True, False, False, False, True, True, True, True], 
[False, False, False, True, False, True, False, False, False, True],[False, False, True, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, True, True, True, False], 
[False, True, False, True, False, True, True, False, False, True]]

? ?box :? ? ? k = (i // 3) * 3 + (j // 3)
? ? ? ? ? ? ? ? box[k][d] = True ?# 第k 個箱子的d 是否存在

? 例如? board[4][3]=8? ?k=(4//3)*3 +(3//1) =4? 第4個子框? 第8個標記為true

[[False, False, False, True, False, True, True, False, True, True], 
[False, True, False, False, False, True, False, True, False, True],[False, False, False, False, False, False, True, False, False, False], 
[False, False, False, False, True, False, False, True, True, False],[False, False, True, True, False, False, True, False, True(8), False], 
[False, True, False, True, False, False, True, False, False, False],[False, False, False, False, False, False, True, False, False, False],[False, True, False, False, True, False, False, False, True, True], 
[False, False, True, False, False, True, False, True, True, True]]

定義回溯

# 定義回溯def backtrack(pos):print("pos", pos)if pos == len(spaces):  # 當pos 等于spaces長度時候說明已經填寫完 ,返回trueprint("結果", board)return Truei, j = spaces[pos]k = (i // 3) * 3 + (j // 3)for d in range(1, 10):  # 對這個位置嘗試填充1-9if not row[i][d] and not col[j][d] and not box[k][d]:  # 滿足為false 時候填入row[i][d] = Truecol[j][d] = Truebox[k][d] = Trueboard[i][j] = str(d)if backtrack(pos + 1):return True# 回溯row[i][d] = Falsecol[j][d] = Falsebox[k][d] = Falseboard[i][j] = '.'  # 恢復空格return Falsebacktrack(0)

代碼?

class Solution:def solveSudoku(self, board: List[List[str]]) -> None:"""Do not return anything, modify board in-place instead."""# 初始化三個數組row=[[False] *10 for _ in range(9)]col=[[False] *10 for _ in range(9)]box=[[False] *10 for _ in range(9)]spaces=[] # 記錄空格位置# 遍歷數組填充已經有的數字for i in range(9):for j in range(9):if board[i][j]!='.':d=int(board[i][j])row[i][d]=Truecol[j][d]=Truek=(i//3)*3+(j//3)box[k][d]=Trueelse:spaces.append((i,j)) # 記錄空格的坐標def  backtrack(pos):if pos ==len(spaces):#遍歷完了所有空格return Truei,j=spaces[pos] # 取出當前位置的空格坐標k=(i//3)*3+(j//3)for d in range(1,10):  # 嘗試對該位置填充1-9if row[i][d]==False and col[j][d]==False and box[k][d]==False:row[i][d]=Truecol[j][d]=Truebox[k][d]=Trueboard[i][j]=str(d)if backtrack(pos+1):return True#不滿足  回溯row[i][d]=Falsecol[j][d]=Falsebox[k][d]=Falseboard[i][j]='.' return Falsebacktrack(0)

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

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

相關文章

Vector的學習

vector簡介 vector的相關文檔對于想深入了解的同學可以參考這個文檔進行學習。 vector是表示可變大小數組的序列容器。 就像數組一樣,vector也采用的連續存儲空間來存儲元素。也就是意味著可以采用下標對vector的元素進行訪問,和數組一樣高效。但是又不…

Vue常用指令入門

1. v-for 作用&#xff1a;用于遍歷對象或數組 注意&#xff1a;需要提供key屬性&#xff0c;可以提高性能和避免渲染錯誤&#xff0c;值通常為index或item.id <li v-for"(item, index) in items" :key"index">{{ item }} </li>2. v-if,v-el…

在機器視覺檢測中為何選擇線陣工業相機?

線陣工業相機&#xff0c;顧名思義是成像傳感器呈“線”狀的。雖然也是二維圖像&#xff0c;但極寬&#xff0c;幾千個像素的寬度&#xff0c;而高度卻只有幾個像素的而已。一般在兩種情況下使用這種相機&#xff1a; 1. 被測視野為細長的帶狀&#xff0c;多用于滾筒上檢測的問…

線性DP:最長上升子序列(子序列可不連續,子數組必須連續)

目錄 Q1&#xff1a;簡單遍歷 Q2&#xff1a;變式&#xff08;加大數據量&#xff09; Q1&#xff1a;簡單遍歷 Dp問題 狀態表示 f(i,j) 集合所有以第i個數結尾的上升子序列集合-f(i,j)的值存的是什么序列長度最大值max- 狀態計算 &#xff08;其實質是集合的劃分&#xff09;…

【Web前端技術】第二節—HTML標簽(上)

hello&#xff01;好久不見—— 做出一個屬于自己的網站&#xff01; 云邊有個稻草人-個人主頁 Web前端技術—本篇文章所屬專欄 目錄 一、HTML 語法規范 1.1 基本語法概述 1.2 標簽關系 二、HTML 基本結構標簽 2.1 第一個 HTML 網頁 2.2 基本結構標簽總結 三、網頁開發…

論文降重GPT指令-實側有效從98%降低到8%

步驟1&#xff1a;文本接收 指令&#xff1a; 請用戶提供需要優化的文本內容。 對文本進行初步分析&#xff0c;識別文本的基本結構和風格。 操作&#xff1a; 接收并分析用戶提交的文本。 步驟2&#xff1a;文本優化 2.1 連接詞處理 指令&#xff1a; 刪除或替換連接詞&#x…

Jsp技術入門指南【九】詳細講解JSTL

Jsp技術入門指南【九】詳細講解JSTL 前言一、什么是JSTL&#xff1f;&#xff08;JavaServer Pages Standard Tag Library&#xff09;二、使用JSTL前的準備三、核心標簽庫常用標簽詳解1. <c:out>&#xff1a;輸出內容&#xff08;替代<% %>&#xff09;2. <c:i…

Linux操作系統--進程的創建和終止

目錄 1.進程創建 1.1fork()函數初識 1.2寫時拷貝 1. 提升系統效率 2. 隔離錯誤影響 3. 支持并行計算 2.進程終止&#xff1a; 2.1進程退出場景&#xff1a; 2.2進程常見退出方法&#xff1a; 2.3_exit()系統調用接口 2.4exit函數 2.5return退出 1.進程創建 1.1for…

OSPF綜合實驗——企業邊界路由器、LSA收斂

IP劃分粗略記號&#xff0c;方便后續配置 配置IP和環回--->ISP的IP配置和cheat認證---->配置OSPF和RIP---->企業邊界路由網段匯總---->特殊區域---> 缺省路由&#xff0c;重分發---->nat配置---->實現全網通 路由器配置IP和環回地址 <Huawei>sys…

Java【網絡原理】(4)HTTP協議

目錄 1.前言 2.正文 2.1自定義協議 2.2HTTP協議 2.2.1抓包工具 2.2.2請求響應格式 2.2.2.1URL 2.2.2.2urlencode 2.2.3認識方法 2.2.3.1GET與POST 2.2.3.2PUT與DELETE 2.2.4請求頭關鍵屬性 3.小結 1.前言 哈嘍大家好啊&#xff0c;今天來繼續給大家帶來Java中網絡…

Android學習總結之APK打包流程

一、預處理階段&#xff08;編譯前準備&#xff09; 1. AIDL 文件處理&#xff08;進程間通信基礎&#xff09; 流程&#xff1a; 用于實現 Android 系統中不同進程間的通信&#xff08;IPC&#xff09;。在項目構建時&#xff0c;AIDL 編譯器會將 .aidl 文件編譯為 Java 接口…

BDO分廠積極開展“五個一”安全活動

BDO分廠為規范化學習“五個一”活動主題&#xff0c;按照“上下聯動、分頭準備 、差異管理、資源共享”的原則&#xff0c;全面激活班組安全活動管理新模式&#xff0c;正在積極開展班組安全活動&#xff0c;以單元班組形式對每個班組每周組織一次“五個一”安全活動。 丁二醇單…

【音視頻】FLV格式分析

FLV概述 FLV(Flash Video)是Adobe公司推出的?種流媒體格式&#xff0c;由于其封裝后的?視頻?件體積?、封裝簡單等特點&#xff0c;?常適合于互聯?上使?。?前主流的視頻?站基本都?持FLV。采?FLV格式封裝的?件后綴為.flv。 FLV封裝格式是由?個?件頭(file header)和…

Java表達式1.0

Java開發工具 在當今的Java開發領域&#xff0c;IntelliJ IDEA已然成為了眾多開發者心目中的首選利器&#xff0c;它被廣泛認為是目前Java開發效率最快的IDE工具。這款備受矚目的開發工具是由JetBrains公司精心打造的&#xff0c;而JetBrains公司總部位于風景如畫的捷克共和國首…

Map遍歷

第一種遍歷方式鍵找值&#xff1a; 增強for循環&#xff1a; 通過獲取元素中的鍵&#xff0c;get到對應的值&#xff0c;通過增強for循環獲取集合里的鍵&#xff0c;然后用get方法通過鍵獲取值 代碼演示&#xff1a; import java.text.ParseException; import java.util.*;…

內網穿透服務器—FRP

某天某刻空閑的時候跟同事聊的本地的存儲服務如果我想讓其他公網內的用戶使用&#xff08;這個存儲服務只是一個臨時文件傳遞站&#xff0c;碎文件&#xff0c;安全低的&#xff09;&#xff0c;然后我們就探討到了FRP一個比較久遠的技術&#xff0c;來做內網穿透&#xff0c;下…

力扣每日打卡16 781. 森林中的兔子(中等)

力扣 781. 森林中的兔子 中等 前言一、題目內容二、解題方法1. 哈希函數&#xff08;來自評論區大佬的解題方法&#xff09;2.官方題解2.1 方法一&#xff1a;貪心 前言 這是刷算法題的第十六天&#xff0c;用到的語言是JS 題目&#xff1a;力扣 781. 森林中的兔子 (中等) 一、…

基于深度學習的線性預測:創新應用與挑戰

一、引言 1.1 研究背景 深度學習作為人工智能領域的重要分支&#xff0c;近年來在各個領域都取得了顯著的進展。在線性預測領域&#xff0c;深度學習也逐漸興起并展現出強大的潛力。傳統的線性預測方法在處理復雜數據和動態變化的情況時往往存在一定的局限性。而深度學習憑借…

黑馬點評redis改 part 3

優惠券秒殺 全局唯一id 每個店鋪都可以發布優惠券&#xff1a; 當用戶搶購時&#xff0c;就會生成訂單并保存到tb_voucher_order這張表中&#xff0c;而訂單表如果使用數據庫自增ID就存在一些問題&#xff1a;實際開發中數據庫ID一般不會參與業務邏輯 增加一個訂單號字段就好…

低代碼開發平臺:企業數字化轉型的加速器

一、引言 在數字化時代&#xff0c;企業的轉型需求日益迫切。為了在激烈的市場競爭中保持領先地位&#xff0c;企業需要快速響應市場變化、優化業務流程、提升運營效率。然而&#xff0c;傳統的軟件開發模式往往面臨開發周期長、成本高、靈活性差等問題&#xff0c;難以滿足企業…