回溯算法又称为试探发
- 排序问题:
普通方式解决
def solvepermutationbadway(array):
solution = []
for i in range(len(array)):
newsolution1 = solution + [array[i]]
newarray1 = array[:i] + array[i + 1:]
for i in range(len(newarray1)):
newsolution2 = newsolution1 + [newarray1[i]]
newarray2 = newarray1[:i] + newarray1[i + 1:]
for i in range(len(newarray2)):
newsolution3 = newsolution2 + [newarray2[i]]
newarray3 = newarray2[:i] + newarray2[i + 1:]
for i in range(len(newarray3)):
newsolution4 = newsolution3 + [newarray3[i]]
print(newsolution4)
array = ['红', '黄', '蓝', '绿']
solvepermutationbadway(array)
用回溯算法解决:
class Solution():
def solvepermutation(self, array):
self.helper([], array) # 调用helper方法
def helper(self, solution, array):
if len(solution) == 0: # 如果没有剩余排序对象
print(solution) # 输出结果
return # 返回上一次被调用的地方
for i in range(len(array)): # 第一本书的选择
newsolution = solution + [array[i]] # 加入书本
newarray = array[:i] + array[i + 1:] # 删除书本
self.helper(newsolution, newarray) # 寻找剩余对象的排序组合
- 典型问题的组合
class Solution():
def solvecombinationbadway(self, array, n):
solution = []
for i in range(len(array)):
solution1 = solution + [array[i]]
newarray = array[i + 1:]
for i in range(len(newarray)):
solution2 = solution1 + [array[i]]
print(solution2)
Solution().solvecombinationbadway(['数学', '英语', '语文', '计算机'], 2)
# 这是不用回溯的写法,如果N很小,这样写没问题,前提是你知道N是多少,但是,一旦N很大,代码就会变得烦琐。
回溯算法解决:
class Solution():
def solvecombination(self, array, n):
self.helper(array, n, [])
def helper(self, array, n, solution):
if len(solution) == n:
print(solution)
return
for i in range(len(array)):
newsolution = solution + [array[i]]
newarray = array[i + 1:]
self.helper(newarray, n, newsolution)
Solution().solvecombination(['数学', '英语', '语文', '计算机'], 2)
- 查找单词问题
class Solution():
def wordsearch(self, board, word):
for i in range(len(board)):
for j in range(len(board[0])):
if self.helper(board, word, i, j):
return True
return False
def helper(self, board, current, row, column): # helper方法(回溯方法)
if len(current) == 0:
return True
if row > 0 and row < len(board) and column > 0 and column < len(board[0]):
if board[row][column] == current[0]:
board[row][column] = ' '
if self.helper(board, current[1:], row - 1, column): # 上下左右检查剩余字母
return True
if self.helper(board, current[1:], row + 1, column):
return True
if self.helper(board, current[1:], row, column - 1):
return True
if self.helper(board, current[1:], row, column + 1):
return True
board[row][column] = current[0] # 如果没有在上下左右中找到下一个字母就说明不对把字母填回到盘面中
return False
- 八皇后问题
class Solution(object):
def solveNQueens(self, n):
self.helper([-1] * n, 0, n)
def helper(self, columnposition, rowindex, n): # columnposition用来储存保安位置的数组 rowindex记录当前行数 n为区域大小
if rowindex == n:
self.printsolution(columnposition, n)
return
for column in range(n):
columnposition[rowindex] = column # 下标是行,值是列 假设第rowindex行保安的位置
if self.isvalid(columnposition, rowindex): # 如果可行
self.helper(columnposition, rowindex + 1, n) # 行+1,继续假设保安的位置
def isvalid(self, columnposition, rowindex): # 判断函数
for i in range(rowindex): # for i in range(0)没有输出
if columnposition[i] == columnposition[rowindex]: # 检查是否同一列
return False
elif abs(columnposition[i] - columnposition[rowindex]) == rowindex - i: # 检查是否在同一斜线上
return False
return True
def printsolution(self, columnposition, n): # 输出函数
for row in range(n): # N行
line = ' '
for column in range(n): # N列
if columnposition[row] == column: # 如果是保安的位置
line += 'Q'
else: # 不是保安的位置
line += '.'
print(line)
print('\n')
Solution().solveNQueens(8)
- 解数独
class Solution():
def solvesudoku(self, board):
self.helper(board, 0)
def helper(self, board, index):
if index >= 81: # 如果盘面已满
self.printsolution(board) # 输出结果
return # 返回上一格
if board[index] == 0: # 如果是空白的格子
for i in range(1, 10): # 填入数字
if self.isvalid(board, index, i): # 如果检验正确
board[index] = i # 填入数字
self.helper(board, index + 1) # 继续假设下一个
board[index] = 0 # 假设不成立就填回空白
else: # 如果当前格已有数
self.helper(board, index + 1)
def printsolution(self, board):
for i in range(0, 81, 9):
print(board[i:i + 9])
def isvalid(self, board, index, num):
row = index // 9
column = index % 9
for i in range(index + 9, 81, 9): # 检查同列下方的格子是否矛盾
if board[i] == num:
return False
for i in range(index - 9, -1, -9): # 检查同列上方的格子是否矛盾
if board[i] == num:
return False
for i in range(9 * row, 9 * (row + 1)): # 检查同行的格子是否矛盾
if board[i] == num:
return False
for i in range(row - row % 3, 3 + row - row % 3): # 行和列都是0~8,index是从0~80
for j in range(column - column % 3, 3 + column - column % 3):
if board[j + i * 9] == num:
return False
return True
Solution().solvesudoku([4, 1, 0, 0, 0, 7, 8, 5, 0,
8, 0, 6, 0, 0, 0, 0, 0, 9,
0, 2, 0, 0, 9, 0, 6, 0, 0,
0, 0, 4, 0, 0, 0, 0, 1, 2,
2, 0, 0, 5, 8, 0, 0, 7, 0,
0, 0, 0, 0, 0, 0, 5, 0, 0,
0, 0, 0, 7, 0, 2, 0, 0, 0,
0, 0, 8, 0, 1, 0, 0, 0, 0,
0, 7, 0, 0, 6, 0, 0, 0, 0])