记录用python写一些深度搜素的题目
题目链接
岛屿数量
思想:把统计过了岛屿都变成水
有关上下左右的,都可以用这种模板
代码如下:
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
def dfs(x,y):
grid[x][y]='0'
for dx,dy in (1,0),(0,1),(-1,0),(0,-1):
nx,ny = x+dx,y+dy
if 0<=nx<n and 0<=ny<m and grid[nx][ny]=='1':
dfs(nx,ny)
n = len(grid)
m = len(grid[0])
ans = 0
for i in range(n):
for j in range(m):
if grid[i][j] == '1':
dfs(i,j)
ans += 1
return ans
全排列
由于是字符串,所以可以特殊处理,用in来判断有没有重复用过,用列表切片来回溯
代码如下:
def dfs(s,tmp):
global ans
if len(tmp)==len(s):
print(tmp)
for c in s:
if c not in tmp:
tmp+=c
dfs(s,tmp)
tmp=tmp[:-1]
s = input()
dfs(s,'')
日期统计
思路:和全排列不同,所取的为子序列,是有序的,所以每次不需要遍历全部。
注意区分:子段 连续的;子序列: 有序,不连续;子集:无序
代码如下:
def dfs(s,tmp):
if not s:
return # 出口
if len(tmp)==4:
m = int(tmp[:2])
d = int(tmp[2:])
if m == 2 and 0<d<=28:
res.add(tmp)
elif m in [1,3,5,7,8,10,12] and 0<d<=31:
res.add(tmp)
elif m in [4,6,9,11] and 0<d<=30:
res.add(tmp)
return
dfs(s[1:],tmp+s[0])
dfs(s[1:],tmp)
s = """
3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1
0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
"""
s = s.split()
res = set() # 用集合来确保不重复
dfs(s,'')
print(len(res))
优化:可以在判断出口的适合,直接剪枝,包含出口,减少几轮递归
def dfs(s,tmp):
if len(s)+len(tmp)<4:
return # 剪枝
if len(tmp)==4:
m = int(tmp[:2])
d = int(tmp[2:])
if m == 2 and 0<d<=28:
res.add(tmp)
elif m in [1,3,5,7,8,10,12] and 0<d<=31:
res.add(tmp)
elif m in [4,6,9,11] and 0<d<=30:
res.add(tmp)
return
dfs(s[1:],tmp+s[0])
dfs(s[1:],tmp)
s = """
3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1
0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
"""
s = s.split()
res = set() # 用集合来确保不重复
dfs(s,'')
print(len(res))
寒假作业
方法一代码如下:
def f(p):
global ans
if p == 13 and a[10] == a[11]*a[12]:
ans += 1
return
elif p == 4 and a[3] != a[1]+a[2]:
return
elif p == 7 and a[6] != a[4]-a[5]:
return
elif p == 10 and a[9] != a[7]*a[8]:
return
for i in range(1,14):
if not vis[i]:
a[p]=i
vis[i] = 1
f(p+1)
vis[i]=0
a = [0]*14 # 用来装答案
vis = [0]*14 # 用来判断是否去过
ans = 0
f(1)
print(ans)
方法二代码如下:
def dfs(a,tmp):
global ans
if len(tmp) == 13:
if tmp[10] == tmp[11]*tmp[12]:
ans += 1
return # 出口
elif len(tmp) == 4:
if tmp[3] != tmp[1]+tmp[2]:
return #剪枝
elif len(tmp) == 7:
if tmp[6] != tmp[4]-tmp[5]:
return #剪枝
elif len(tmp) == 10:
if tmp[9] != tmp[7]*tmp[8]:
return #剪枝
for x in a:
if x not in tmp:
tmp.append(x)
dfs(a,tmp)
tmp.pop()
ans = 0
a = list(range(1,14))
dfs(a,[0])
print(ans)
李白打酒
方法一代码如下:
def dfs(j,h,d):
global ans
if j==1 and h==1 and d==0:
ans += 1
if h > 0:
dfs(j-1,h-1,d)
if d > 0:
dfs(j*2,h,d-1)
ans = 0
dfs(2,10,5)
print(ans)
方法二代码如下:
def dfs(j,h,d):
global ans
if j==1 and h==1 and d==0:
return 1
elif j<1 or h<1 or d<0:
return 0
else:
return dfs(j-1,h-1,d)+dfs(j*2,h,d-1)
ans = dfs(2,10,5)
print(ans)
第几个辛运数字
宽度优先搜索用队列
代码如下:
from heapq import heappop,heappush
q = [1]
s = 59084709587505
res = set()
while 1:
x = heappop(q)
if x == s:
break
for c in [3,5,7]:
t = x*c
if t not in res:
heappush(q,t)
if x*c <= s:
res.add(t)
print(len(res))