python初识搜索DFS,BFS,经典例题

记录用python写一些深度搜素的题目

题目链接

  1. 岛屿数量
  2. 全排列
  3. 日期统计
  4. 寒假作业
  5. 李白打酒
  6. 第几个辛运数字

岛屿数量

思想:把统计过了岛屿都变成水
有关上下左右的,都可以用这种模板
代码如下:

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))
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

peanut666888

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值