鱼C论坛

 找回密码
 立即注册
查看: 331|回复: 5

leetcode困难题深度优先遍历

[复制链接]
发表于 2024-11-4 18:08:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. class Solution:
  2.     def removeInvalidParentheses(self, s: str) -> List[str]:
  3.         lens = len(s)
  4.         
  5.         l = r = 0
  6.         for c in s:
  7.             if c == '(':
  8.                 l += 1
  9.             elif c == ')':
  10.                 if l:
  11.                     l -= 1
  12.                 else:
  13.                     r += 1

  14.         res = []
  15.         # idx:当前字符的索引
  16.         # cl:保留的左括号数量
  17.         # cr:保留的右括号数量
  18.         # dl:需要移除的左括号数量
  19.         # dr:需要移除的右括号数量
  20.         # path:保留下来的字符串

  21.         from functools import lru_cache
  22.         @lru_cache(maxsize=None)
  23.         def dfs(idx, cl, cr, dl, dr, path):
  24.             if idx == lens:
  25.                 if not dl and not dr:
  26.                     res.append(path)
  27.                 return

  28.             # 若当前保留的右括号大于左括号,那必然部合法了
  29.             # 移除的左括号,右括号超出了,那不行
  30.             if cr>cl or dl<0 or dr<0:
  31.                 return

  32.             c = s[idx]

  33.             # 移除'(',dfs下去看看行不行
  34.             if c == '(':
  35.                 dfs(idx+1, cl, cr, dl-1, dr, path)
  36.             # 移除')',dfs下去看看行不行
  37.             elif c == ')':
  38.                 dfs(idx+1, cl, cr, dl, dr-1, path)
  39.             
  40.             # '(', ')', 小写字母均不删除
  41.             dfs(idx+1, cl+(c=='('), cr+(c==')'), dl, dr, path+c)


  42.         dfs(0, 0, 0, l, r, '')

  43.         # 如果不想最后去重,可在dfs前加记忆话搜索:@lru_cache(None)
  44.         # return list(set(res))

  45.         return res
复制代码


其中,
  1. # 若当前保留的右括号大于左括号,那必然部合法了
  2.             # 移除的左括号,右括号超出了,那不行
  3.             if cr>cl or dl<0 or dr<0:
  4.                 return
复制代码


左括号右括号超出了是什么情况
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-4 18:08:16 | 显示全部楼层
看起来你在尝试解决一个 LeetCode 的困难题,使用深度优先搜索(DFS)来移除无效的括号。你已经开始实现了一个 `dfs` 函数,并使用了 `lru_cache` 来优化递归调用。以下是一些建议,帮助你完成这个问题:

1. **初始化结果列表**:在 `res = ` 处,你需要初始化一个空列表来存储结果。

2. **DFS 递归函数**:在 `dfs` 函数中,你需要处理以下几种情况:
   - 当前字符是左括号 `'('`:你可以选择保留或移除。
   - 当前字符是右括号 `')'`:同样可以选择保留或移除。
   - 当前字符是其他字符:直接保留。

3. **递归终止条件**:当索引 `idx` 达到字符串末尾时,检查是否所有需要移除的括号都已移除。如果是,则将当前路径 `path` 添加到结果中。

4. **合法性检查**:在递归过程中,确保右括号的数量不超过左括号的数量。

以下是一个完整的实现思路:

  1. from typing import List
  2. from functools import lru_cache

  3. class Solution:
  4.     def removeInvalidParentheses(self, s: str) -> List[str]:
  5.         lens = len(s)
  6.         
  7.         l = r = 0
  8.         for c in s:
  9.             if c == '(':
  10.                 l += 1
  11.             elif c == ')':
  12.                 if l:
  13.                     l -= 1
  14.                 else:
  15.                     r += 1

  16.         res = []

  17.         @lru_cache(maxsize=None)
  18.         def dfs(idx, cl, cr, dl, dr, path):
  19.             if idx == lens:
  20.                 if not dl and not dr:
  21.                     res.append(path)
  22.                 return

  23.             if cr > cl or dl < 0 or dr < 0:
  24.                 return

  25.             char = s[idx]
  26.             if char == '(':
  27.                 dfs(idx + 1, cl + 1, cr, dl, dr, path + char)  # 保留
  28.                 dfs(idx + 1, cl, cr, dl - 1, dr, path)        # 移除
  29.             elif char == ')':
  30.                 dfs(idx + 1, cl, cr + 1, dl, dr, path + char)  # 保留
  31.                 dfs(idx + 1, cl, cr, dl, dr - 1, path)        # 移除
  32.             else:
  33.                 dfs(idx + 1, cl, cr, dl, dr, path + char)      # 保留其他字符

  34.         dfs(0, 0, 0, l, r, "")
  35.         return res
复制代码


这个实现通过递归遍历每个字符,选择保留或移除括号,最终生成所有可能的合法字符串。希望这能帮助你解决问题!如果有其他问题,欢迎继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-4 23:40:35 | 显示全部楼层
FishC 发表于 2024-11-4 18:08
看起来你在尝试解决一个 LeetCode 的困难题,使用深度优先搜索(DFS)来移除无效的括号。你已经开始实现了 ...

上述dfs遍历时,char=s[4]=')'的时候,递归遍历结果是怎么样的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-4 23:40:44 | 显示全部楼层
Terence888 发表于 2024-11-04 23:40
上述dfs遍历时,char=s=')'的时候,递归遍历结果是怎 ...


当 `char == ')'` 时,`dfs` 函数的递归遍历会分成两种情况:

1. **保留当前右括号**:
   - 如果选择保留当前的右括号,则会增加保留的右括号计数 `cr`。
   - 递归调用下一步时,自然会更新索引 `idx + 1`,路径 `path` 加上当前的字符 `char`。

2. **移除当前右括号**:
   - 如果选择移除当前的右括号,则需要减少需要移除的右括号计数 `dr`。
   - 递归继续进行,但路径 `path` 不加上当前的字符,而且 `idx` 仍然增加 1。

这两种选择的递归结果都会被进一步处理,直到整个字符串 `s` 被遍历完。

实际执行时,根据不同的字符串内容和移除规则(如 `dl` 和 `dr` 不为零),路径会产生不同的变化,最终将形成多个合法字符串(路径)供选择。

以下是关于 `char == ')'` 的代码片段的详细说明:

  1. if char == ')':
  2.     # 保留当前右括号,增加已保留的右括号计数
  3.     dfs(idx + 1, cl, cr + 1, dl, dr, path + char)
  4.    
  5.     # 移除当前右括号,减少需要移除的右括号计数
  6.     dfs(idx + 1, cl, cr, dl, dr - 1, path)
复制代码


在这种策略下,当遍历整个字符串 `s` 完成之后,你将得到所有可能的、经过合法处理的路径(字符串)。这些结果添加到最终的 `res` 列表中,作为输出返回。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-5 10:05:54 | 显示全部楼层
FishC 发表于 2024-11-4 23:40
当 `char == ')'` 时,`dfs` 函数的递归遍历会分成两种情况:

1. **保留当前右括号**:

帮我逐一遍历每个字母解读一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-5 10:06:08 | 显示全部楼层
Terence888 发表于 2024-11-05 10:05
帮我逐一遍历每个字母解读一下


可以的,我们逐步解读每个字符在 DFS 中的遍历过程,以字符串 `s = "()())()"` 为例。字符串中有不匹配的括号,我们需要移除这些多余的括号,使字符串合法。

### 初始设置

- 需要移除的左括号(`l`)和右括号(`r`)数量初始化:通过扫描字符串,`l = 0, r = 1`。
  
### 递归处理逐个字符

1. **第一个字符 `'('` (index 0)**:
   - **保留**:`cl = 1, cr = 0, path = "("`
   - **移除**:`dl = 0, dr = 1, path = ""` (由于不需要移除左括号,这是不必要的)

2. **第二个字符 `')'` (index 1)**:
   - 选择保留前面 `'('`:
     - **保留**:`cl = 1, cr = 1, path = "()"` (此路径是合法括号表达式)
     - **移除**:`cl = 1, cr = 0, path = "("`
   - 选择移除前面 `'('`:
     - **保留**:`cl = 0, cr = 1, path = ")"`(非法,不会继续递归)
     - **移除**:`cl = 0, cr = 0, path = ""`(保持空)

3. **第三个字符 `'('` (index 2)**:
   - 前一个路径保留的情况 "()":
     - **保留**:`cl = 2, cr = 1, path = "()("`
     - **移除**:`cl = 1, cr = 1, path = "()"`(保留路径不变)
   
4. **第四个字符 `')'` (index 3)**:
   - 前一个路径保留 "()":
     - **保留**:`cl = 1, cr = 2, path = "())"`(非法,后续不考虑)
     - **移除**:`cl = 1, cr = 1, path = "()"`(重合路径)

   - 前一个路径保留 "()(":
     - **保留**:`cl = 2, cr = 2, path = "()()"`(是否合法路径,后续可能用来剪枝)
     - **移除**:`cl = 2, cr = 1, path = "()("`

5. **第五个字符 `')'` (index 4)**:
   - 对于路径 `()()`:
     - **跳过**:`res.append(path)`(无变化,因为路径合法性已固定)

   - 对路径 `()(`:
     - **跳过** :`cr=cl -> res.extend(path)`(无作用)

6. **第六个字符 `'('` (index 5)**:
   - 此时,多组路径下一个 ')' 具有保留和移除设置,形成:
     - **保留新'('**:`cl = ?, ?,path = "任选有效路径"`(合法范围搜索)

7. **第七个字符 `')'` (index 6)**:
   - 类似步骤进行对比生成最终合法字符串。

### 总结

上步骤有详例,最终合法字符串 `["()()()", "(())()"]`。每当满足合法条件时,结果都存入 `res`,并返回给调用者。DFS 深度遍历尽可能多路径,但判定依据不变,即是否合法且字符是否必定保留。

如果有更多问题欢迎提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-18 17:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表