golang力扣leetcode 301.删除无效的括号

简介: golang力扣leetcode 301.删除无效的括号

301.删除无效的括号

301.删除无效的括号

题解

题目:给定包含左右括号和字母的字符串,要求删除某些括号后,该字符串括号匹配(字母不删),如果只删1个就能合法,返回所有合法字符串,如果删2个才能合法…总之删除括号的数量越少越好

思路:

dfs+回溯

1.预处理出需要删除的左右括号的个数(rmL,rmR)
2.dfs遍历字符串,如果是左括号,则
        temp := str[:i] + str[i+1:]
        dfs(temp, i, rml-1, rmR)
         右括号同理
  出口:rmL和rmR为0,并且字符串匹配

bfs

1.将字符串s存入队列
2.遍历队列,如果队列中的字符串合法则加入答案,遍历完后退出
3.如果没有合法的,则
  遍历队列,遍历字符串
        遇到括号就去除,加入队列 temp := str[:i] + str[i+1:]

代码

func removeInvalidParentheses(s string) (result []string) {
  mp := make(map[string]bool)
  rmL, rmR := 0, 0
  for _, v := range s {
    if v == '(' {
      rmL++
    } else if v == ')' {
      if rmL == 0 {
        rmR++
      } else {
        rmL--
      }
    }
  }
  var dfs func(str string, idx int, rmL, rmR int)
  dfs = func(str string, idx int, rml, rmR int) {
    if rml == 0 && rmR == 0 && isValid(str) {
      mp[str] = true
      return
    }
    if rml+rmR > len(str)-idx {
      return
    }
    for i := idx; i < len(str); i++ {
      v := str[i]
      if v == '(' && rml > 0 {
        temp := str[:i] + str[i+1:]
        dfs(temp, i, rml-1, rmR)
      }
      if v == ')' && rmR > 0 {
        temp := str[:i] + str[i+1:]
        dfs(temp, i, rml, rmR-1)
      }
    }
  }
  dfs(s, 0, rmL, rmR)
  for k := range mp {
    result = append(result, k)
  }
  return
}
func isValid(str string) bool {
  count := 0
  for _, ch := range str {
    if ch == '(' {
      count++
    } else if ch == ')' {
      count--
      if count < 0 {
        return false
      }
    }
  }
  return count == 0
}
func removeInvalidParentheses(s string) (result []string) {
  cur := make(map[string]bool)
  cur[s] = true
  for {
    for str := range cur {
      if isValid(str) {
        result = append(result, str)
      }
    }
    if len(result) > 0 {
      return result
    }
    next := make(map[string]bool)
    for str := range cur {
      for i, v := range str {
        if v == '(' || v == ')' {
          temp := str[:i] + str[i+1:]
          next[temp] = true
        }
      }
    }
    cur = next
  }
}
func isValid(s string) bool {
  count := 0
  for _, v := range s {
    if v == '(' {
      count++
    } else if v == ')' {
      count--
      if count < 0 {
        return false
      }
    }
  }
  return count == 0
}
type pair struct {
  count, cnt, idx int
  ss              string
}
func removeInvalidParentheses(s string) (result []string) {
  ans := 0
  n := len(s)
  mp := make(map[int][]string)
  mpSet := make(map[string]bool)
  vis := make(map[pair]bool)
  var dfs func(count, cnt, idx int, ss string) //count是左右括号匹配,cnt是还剩多少个字符
  dfs = func(count, cnt, idx int, ss string) {
    p := pair{count, cnt, idx, ss}
    if !vis[p] {
      vis[p] = true
    } else {
      return
    }
    if count == 0 && idx == n {
      if cnt > ans {
        ans = cnt
        mpSet[ss] = true
        mp[ans] = append(mp[ans], ss)
      } else if cnt == ans {
        if !mpSet[ss] {
          mp[ans] = append(mp[ans], ss)
          mpSet[ss] = true
        }
      }
    }
    if count < 0 || cnt == -1 || idx == n {
      return
    }
    //去除当前
    dfs(count, cnt-1, idx+1, ss)
    //不去除
    if s[idx] == '(' {
      count++
    } else if s[idx] == ')' {
      count--
    }
    dfs(count, cnt, idx+1, ss+string(s[idx]))
  }
  dfs(0, n, 0, "")
  //左右是否匹配 还剩多少个字符 idx现在到哪了 字符串
  for _, v := range mp[ans] {
    result = append(result, v)
  }
  return
}
目录
相关文章
|
5月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
221 1
|
5月前
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
213 1
|
5月前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
158 0
|
5月前
|
算法 Go 索引
【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)
本文深入解析了LeetCode上的两道经典回溯算法题:**22. 括号生成**与**39. 组合总和**。括号生成通过维护左右括号数量,确保路径合法并构造有效组合;组合总和则允许元素重复选择,利用剪枝优化搜索空间以找到所有满足目标和的组合。两者均需明确路径、选择列表及结束条件,同时合理运用剪枝策略提升效率。文章附有Go语言实现代码,助你掌握回溯算法的核心思想。
195 0
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
239 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
164 6
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
346 2
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
243 3
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
323 1
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
322 7

推荐镜像

更多