Bootstrap搭建一個簡易的圖書管理系統頁面
阿新 • • 發佈:2020-11-22
參考:https://zhuanlan.zhihu.com/p/302415065
目錄關於回溯
回溯是遞迴的“副產品”,並非高效演算法,通過剪枝可以跳過非必要的搜尋。
回溯演算法能解決如下問題:
- 組合問題:N個數裡面按一定規則找出k個數的集合;
- 排列問題:N個數按一定規則全排列,有幾種排列方式;
- 切割問題:一個字串按一定規則有幾種切割方式;
- 子集問題:一個N個數的集合裡有多少符合條件的子集;
- 棋盤問題:N皇后,解數獨等等。
注:「組合是不強調元素順序的,排列是強調元素順序」
回溯函式的虛擬碼模板
def backtracking(self, 引數列表):
# 定義遞迴出口
if 終止條件:
儲存結果
return
for i in range(n):
處理
self.dfs(引數)
處理回退
以組合問題舉例
一句話總結:for迴圈橫向遍歷,遞迴縱向遍歷,回溯不斷調整結果集。
例題:力扣77題:給定兩個整數n和k,返回1...n中所有可能的k個數的組合。思路如下圖:
程式碼如下:
class Solution(object): def __init__(self): self.res = [] def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ nums = [i for i in range(1, n+1)] sizeN = len(nums) self.dfs(nums, sizeN, k, 0, []) return self.res def dfs(self, nums, sizeN, k, begin, temp): # 定義遞迴出口:長度為k if len(temp) == k: self.res.append(temp) for i in range(begin, sizeN): if len(temp) > k: break # 遞迴 self.dfs(nums, sizeN, k, i+1, temp+[nums[i]])
上述例題是在一個集合中求組合,需要用到“begin”這個變數來控制for迴圈的起始位置。
那麼對於組合問題,什麼時候需要此變數呢?
如果是一個集合來求組合,就需要begin,例如:力扣39、40、77等題;
如果是多個集合取組合,各個集合之間相互不影響,那麼就不需要begin,例如:力扣17題。
做題中總結的一個模板
class Solution():
# 返回值,定義為全域性變數
def __init__(self):
self.res = []
def function(self, string):
n = len(string)
temp = []
visit = [0 for _ in range(n)]
self.dfs(string, temp, visit, n)
return self.res
def dfs(self, string, temp, visit, n):
# 定義遞迴出口
if len(temp) == len(string):
self.res.append("".join(temp))
else:
# for迴圈橫向遍歷
for i in range(n):
# 當且僅當當前字元未被訪問
if not visit[i]:
# 用temp記錄當前訪問
temp.append(string[i])
visit[i] = 1
# 遞迴呼叫,縱向遍歷
self.dfs(string, temp, visit, n)
# 回退
temp.pop(-1)
visit[i] = 0