在一般情况下,符号三角形的第一行有
n
n
n个符号,符号三角形问题要求对于给定的
n
n
n,计算有多少个不同的符号三角形,使其所含的“
+
+
+”和“
−
-
−”的个数相同
回溯法
对于符号三角形问题,用
n
n
n元组
x
[
1
:
n
]
x[1 : n]
x[1:n]表示符号三角形的第一行的
n
n
n个符号,由于
x
[
i
]
x[i]
x[i]是二值的,所以在用回溯法解符号三角形问题时,可以用一棵完全二叉树来表示其解空间
在符号三角形的第一行的前
i
i
i个符号
x
[
1
:
i
]
x[1 : i]
x[1:i]确定后,就确定了一个由
i
(
i
+
1
)
/
2
i (i + 1) / 2
i(i+1)/2个符号组成的符号三角形,下一步确定
x
[
i
+
1
]
x[i + 1]
x[i+1]的值后,只要在前面已确定的符号三角形的右边加一条边,就可以扩展为
x
[
1
:
i
+
1
]
x[1 : i + 1]
x[1:i+1]相应的符号三角形
最终由
x
[
1
:
n
]
x[1 : n]
x[1:n]所确定的符号三角形中包含的“
+
+
+”个数与“
−
-
−”个数同为
n
(
n
+
1
)
/
4
n (n + 1) / 4
n(n+1)/4,因此在回溯搜索过程中,可用当前符号三角形所包含的“
+
+
+”个数与”
−
-
−“个数均不超过
n
(
n
+
1
)
/
4
n (n + 1) / 4
n(n+1)/4作为可行性约束,用于剪去不满足约束的子树
当
i
=
n
i = n
i=n时,算法搜索至叶节点,得到一个新的“
+
+
+”个数与“
−
-
−”个数相同的符号三角形,当前已找到符号三角形数
s
u
m
sum
sum增
1
1
1
当
i
<
n
i < n
i<n时,当前扩展结点
Z
Z
Z是解空间中的内部结点,对当前扩展结点
Z
Z
Z的每个儿子结点,计算其相应的符号三角形中“
+
+
+”个数与“
−
-
−”个数,并以深度优先的方式递归地对可行子树进行搜索,或剪去不可行子树
对于给定的
n
n
n,当
n
(
n
+
1
)
/
2
n (n + 1) / 2
n(n+1)/2为奇数时,显然不存在所包含的“
+
+
+”个数与“
−
-
−”个数相同的符号三角形,此时可以通过简单的判断加以处理
时间复杂性
更新符号三角形矩阵需要
O
(
n
)
O(n)
O(n)时间,在最坏情况下,有
O
(
2
n
)
O(2^{n})
O(2n)个结点需要更新符号三角形矩阵
所以解符号三角形问题的回溯算法所需的计算时间为
O
(
n
2
n
)
O(n 2^{n})
O(n2n)
Python实现
defsymbol_triangle(n):if(n *(n +1)//2)%2:return0
half = n *(n +1)//4
count =0# 记录符合条件的符号三角形数量# 初始化符号三角形矩阵
path =[['']* n for _ inrange(n)]defbacktrack(row, col, path, plus_count, minus_count):nonlocal count
# 边界条件: 当列数等于 n 时, 表示已经生成了符号三角形的一种排列if col == n:if plus_count == minus_count:
count +=1print(path)return# 尝试当前位置为 +
path[row][col]='+'
plus_count +=1# 更新符号三角形矩阵
cur_col = col
for i inrange(1, cur_col +1):if path[i -1][cur_col -1]== path[i -1][cur_col]:
path[i][cur_col -1]='+'
plus_count +=1else:
path[i][cur_col -1]='-'
minus_count +=1
cur_col -=1# 检查是否满足条件, 继续生成下一行的符号if plus_count <= half and minus_count <= half:
backtrack(row, col +1, path, plus_count, minus_count)# 恢复回溯之前状态
cur_col = col
for i inrange(cur_col +1):if path[i][cur_col]=='+':
path[i][cur_col]=''
plus_count -=1else:
path[i][cur_col]=''
minus_count -=1
cur_col -=1# 尝试当前位置为 -
path[row][col]='-'
minus_count +=1# 更新符号三角形矩阵
cur_col = col
for i inrange(1, cur_col +1):if path[i -1][cur_col -1]== path[i -1][cur_col]:
path[i][cur_col -1]='+'
plus_count +=1else:
path[i][cur_col -1]='-'
minus_count +=1
cur_col -=1# 检查是否满足条件, 继续生成下一行的符号if plus_count <= half and minus_count <= half:
backtrack(row, col +1, path, plus_count, minus_count)
backtrack(0,0, path,0,0)return count
n =4print('满足条件的符号三角形如下:')
count = symbol_triangle(n)print(f'符号三角形数量: {count}')
一、慢查询日志
描述:通过慢查询日志等定位那些执行效率较低的SQL语句
查看
# 慢查询是否开启
show variables like slow_query_log%;
# 慢查询超时时间
show variables like long_query_time%;执行SQL
开启慢查询日志
set global slow_query_log ON;设置慢查…