diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md index fc1e3114..aaac4c7c 100644 --- a/problems/0037.解数独.md +++ b/problems/0037.解数独.md @@ -42,9 +42,9 @@ **如果以上这几道题目没有做过的话,不建议上来就做这道题哈!** -[N皇后问题](https://programmercarl.com/0051.N皇后.html)是因为每一行每一列只放一个皇后,只需要一层for循环遍历一行,递归来来遍历列,然后一行一列确定皇后的唯一位置。 +[N皇后问题](https://programmercarl.com/0051.N皇后.html)是因为每一行每一列只放一个皇后,只需要一层for循环遍历一行,递归来遍历列,然后一行一列确定皇后的唯一位置。 -本题就不一样了,**本题中棋盘的每一个位置都要放一个数字(而N换后是一行只放一个皇后),并检查数字是否合法,解数独的树形结构要比N皇后更宽更深**。 +本题就不一样了,**本题中棋盘的每一个位置都要放一个数字(而N皇后是一行只放一个皇后),并检查数字是否合法,解数独的树形结构要比N皇后更宽更深**。 因为这个树形结构太大了,我抽取一部分,如图所示: @@ -75,7 +75,7 @@ bool backtracking(vector>& board) **那么有没有永远填不满的情况呢?** -这个问题我在递归单层搜索逻辑里在来讲! +这个问题我在递归单层搜索逻辑里再来讲! * 递归单层搜索逻辑 @@ -207,7 +207,7 @@ public: 所以我在开篇就提到了**二维递归**,这也是我自创词汇,希望可以帮助大家理解解数独的搜索过程。 -一波分析之后,在看代码会发现其实也不难,唯一难点就是理解**二维递归**的思维逻辑。 +一波分析之后,再看代码会发现其实也不难,唯一难点就是理解**二维递归**的思维逻辑。 **这样,解数独这么难的问题,也被我们攻克了**。 @@ -331,55 +331,56 @@ class Solution: ### Go ```go -func solveSudoku(board [][]byte) { - var backtracking func(board [][]byte) bool - backtracking=func(board [][]byte) bool{ - for i:=0;i<9;i++{ - for j:=0;j<9;j++{ - //判断此位置是否适合填数字 - if board[i][j]!='.'{ - continue - } - //尝试填1-9 - for k:='1';k<='9';k++{ - if isvalid(i,j,byte(k),board)==true{//如果满足要求就填 - board[i][j]=byte(k) - if backtracking(board)==true{ - return true - } - board[i][j]='.' - } - } - return false - } - } - return true - } - backtracking(board) +func solveSudoku(board [][]byte) { + var backtracking func(board [][]byte) bool + backtracking = func(board [][]byte) bool { + for i := 0; i < 9; i++ { + for j := 0; j < 9; j++ { + //判断此位置是否适合填数字 + if board[i][j] != '.' { + continue + } + //尝试填1-9 + for k := '1'; k <= '9'; k++ { + if isvalid(i, j, byte(k), board) == true { //如果满足要求就填 + board[i][j] = byte(k) + if backtracking(board) == true { + return true + } + board[i][j] = '.' + } + } + return false + } + } + return true + } + backtracking(board) } + //判断填入数字是否满足要求 -func isvalid(row,col int,k byte,board [][]byte)bool{ - for i:=0;i<9;i++{//行 - if board[row][i]==k{ - return false - } - } - for i:=0;i<9;i++{//列 - if board[i][col]==k{ - return false - } - } - //方格 - startrow:=(row/3)*3 - startcol:=(col/3)*3 - for i:=startrow;i> targets:unordered_map<出发机场, ma 在遍历 `unordered_map<出发机场, map<到达机场, 航班次数>> targets`的过程中,**可以使用"航班次数"这个字段的数字做相应的增减,来标记到达机场是否使用过了。** -如果“航班次数”大于零,说明目的地还可以飞,如果如果“航班次数”等于零说明目的地不能飞了,而不用对集合做删除元素或者增加元素的操作。 +如果“航班次数”大于零,说明目的地还可以飞,如果“航班次数”等于零说明目的地不能飞了,而不用对集合做删除元素或者增加元素的操作。 **相当于说我不删,我就做一个标记!** @@ -439,68 +439,6 @@ func findItinerary(tickets [][]string) []string { } ``` -### C语言 - -```C -char **result; -bool *used; -int g_found; - -int cmp(const void *str1, const void *str2) -{ - const char **tmp1 = *(char**)str1; - const char **tmp2 = *(char**)str2; - int ret = strcmp(tmp1[0], tmp2[0]); - if (ret == 0) { - return strcmp(tmp1[1], tmp2[1]); - } - return ret; -} - -void backtracting(char *** tickets, int ticketsSize, int* returnSize, char *start, char **result, bool *used) -{ - if (*returnSize == ticketsSize + 1) { - g_found = 1; - return; - } - for (int i = 0; i < ticketsSize; i++) { - if ((used[i] == false) && (strcmp(start, tickets[i][0]) == 0)) { - result[*returnSize] = (char*)malloc(sizeof(char) * 4); - memcpy(result[*returnSize], tickets[i][1], sizeof(char) * 4); - (*returnSize)++; - used[i] = true; - /*if ((*returnSize) == ticketsSize + 1) { - return; - }*/ - backtracting(tickets, ticketsSize, returnSize, tickets[i][1], result, used); - if (g_found) { - return; - } - (*returnSize)--; - used[i] = false; - } - } - return; -} - -char ** findItinerary(char *** tickets, int ticketsSize, int* ticketsColSize, int* returnSize){ - if (tickets == NULL || ticketsSize <= 0) { - return NULL; - } - result = malloc(sizeof(char*) * (ticketsSize + 1)); - used = malloc(sizeof(bool) * ticketsSize); - memset(used, false, sizeof(bool) * ticketsSize); - result[0] = malloc(sizeof(char) * 4); - memcpy(result[0], "JFK", sizeof(char) * 4); - g_found = 0; - *returnSize = 1; - qsort(tickets, ticketsSize, sizeof(tickets[0]), cmp); - backtracting(tickets, ticketsSize, returnSize, "JFK", result, used); - *returnSize = ticketsSize + 1; - return result; -} -``` - ### Javascript ```Javascript @@ -589,6 +527,68 @@ function findItinerary(tickets: string[][]): string[] { }; ``` +### C语言 + +```C +char **result; +bool *used; +int g_found; + +int cmp(const void *str1, const void *str2) +{ + const char **tmp1 = *(char**)str1; + const char **tmp2 = *(char**)str2; + int ret = strcmp(tmp1[0], tmp2[0]); + if (ret == 0) { + return strcmp(tmp1[1], tmp2[1]); + } + return ret; +} + +void backtracting(char *** tickets, int ticketsSize, int* returnSize, char *start, char **result, bool *used) +{ + if (*returnSize == ticketsSize + 1) { + g_found = 1; + return; + } + for (int i = 0; i < ticketsSize; i++) { + if ((used[i] == false) && (strcmp(start, tickets[i][0]) == 0)) { + result[*returnSize] = (char*)malloc(sizeof(char) * 4); + memcpy(result[*returnSize], tickets[i][1], sizeof(char) * 4); + (*returnSize)++; + used[i] = true; + /*if ((*returnSize) == ticketsSize + 1) { + return; + }*/ + backtracting(tickets, ticketsSize, returnSize, tickets[i][1], result, used); + if (g_found) { + return; + } + (*returnSize)--; + used[i] = false; + } + } + return; +} + +char ** findItinerary(char *** tickets, int ticketsSize, int* ticketsColSize, int* returnSize){ + if (tickets == NULL || ticketsSize <= 0) { + return NULL; + } + result = malloc(sizeof(char*) * (ticketsSize + 1)); + used = malloc(sizeof(bool) * ticketsSize); + memset(used, false, sizeof(bool) * ticketsSize); + result[0] = malloc(sizeof(char) * 4); + memcpy(result[0], "JFK", sizeof(char) * 4); + g_found = 0; + *returnSize = 1; + qsort(tickets, ticketsSize, sizeof(tickets[0]), cmp); + backtracting(tickets, ticketsSize, returnSize, "JFK", result, used); + *returnSize = ticketsSize + 1; + return result; +} +``` + ### Swift 直接迭代tickets数组: @@ -709,78 +709,6 @@ for line in tickets { } ``` -### Go -```Go - -// 先排序,然后找到第一条路径即可返回 -func findItinerary(tickets [][]string) []string { - var path []string // 用来保存搜索的路径 - data := make(map[string]ticketSlice) // 用来保存tickets排序后的结果 - - var search func(airport string) bool - search = func(airport string) bool { - if len(path) == len(tickets) { - path = append(path, airport) - return true - } - to := data[airport] - for _, item := range to { - if item.Count == 0 { - // 已用完 - continue - } - - path = append(path, airport) - item.Count-- - if search(item.To) { return true } - item.Count++ - path = path[:len(path) - 1] - } - - return false - } - - // 排序 - // 感觉这段代码有点啰嗦,不知道能不能简化一下 - tmp := make(map[string]map[string]int) - for _, ticket := range tickets { - if to, ok := tmp[ticket[0]]; ok { - if _, ok2 := to[ticket[1]]; ok2 { - to[ticket[1]]++ - } else { - to[ticket[1]] = 1 - } - } else { - tmp[ticket[0]] = map[string]int{ - ticket[1]: 1, - } - } - } - for from, to := range tmp { - var tmp ticketSlice - for to, num := range to { - tmp = append(tmp, &ticketStat{To: to, Count: num}) - } - sort.Sort(tmp) - data[from] = tmp - } - - search("JFK") - return path -} - -type ticketStat struct { - To string - Count int -} -type ticketSlice []*ticketStat - -func (p ticketSlice) Len() int { return len(p) } -func (p ticketSlice) Less(i, j int) bool { return strings.Compare(p[i].To, p[j].To) == -1 } -func (p ticketSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -``` - ### Rust ** 文中的Hashmap嵌套Hashmap的方法因为Rust的所有权问题暂时无法实现,此方法为删除哈希表中元素法 ** ```Rust