首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >golang刷leetcode:检查是否有合法括号字符串路径

golang刷leetcode:检查是否有合法括号字符串路径

作者头像
golangLeetcode
发布于 2022-08-02 19:45:34
发布于 2022-08-02 19:45:34
1.7K0
举报

一个括号字符串是一个 非空 且只包含 '(' 和 ')' 的字符串。如果下面 任意 条件为 真 ,那么这个括号字符串就是 合法的 。

字符串是 () 。

字符串可以表示为 AB(A 连接 B),A 和 B 都是合法括号序列。

字符串可以表示为 (A) ,其中 A 是合法括号序列。

给你一个 m x n 的括号网格图矩阵 grid 。网格图中一个 合法括号路径 是满足以下所有条件的一条路径:

路径开始于左上角格子 (0, 0) 。

路径结束于右下角格子 (m - 1, n - 1) 。

路径每次只会向 下 或者向 右 移动。

路径经过的格子组成的括号字符串是 合法 的。

如果网格图中存在一条 合法括号路径 ,请返回 true ,否则返回 false 。

示例 1:

输入:grid = [["(","(","("],[")","(",")"],["(","(",")"],["(","(",")"]]

输出:true

解释:上图展示了两条路径,它们都是合法括号字符串路径。

第一条路径得到的合法字符串是 "()(())" 。

第二条路径得到的合法字符串是 "((()))" 。

注意可能有其他的合法括号字符串路径。

示例 2:

输入:grid = [[")",")"],["(","("]]

输出:false

解释:两条可行路径分别得到 "))(" 和 ")((" 。由于它们都不是合法括号字符串,我们返回 false 。

提示:

m == grid.length

n == grid[i].length

1 <= m, n <= 100

grid[i][j] 要么是 '(' ,要么是 ')' 。

解题思路:

1,看到这个题,首先想到的是递归,位置i,j的值由i-1,j和i,j-1位置的值决定

2,但是问题来了,每一个位置并不能确定最终是否合法。

3,每一个位置i,j,如果左括号数<0,显然不合法,它最多可以累积i+j+1个左括号,所以这里隐含了第三维变量即累积的括号数。

4,对于每一个位置,当我们遇到左括号,+1;遇到右括号-1;当这个位置的值是负数的时候,没有必要继续了,它已经不合法了

5,当左括号的数>剩余位置数的时候,即:即使以后都是右括号,也没法配对,所以出现这种情况也不合法。

6,因此可以认为:当前位置是否合法是由左边或者上边累积括号数+1或者-1决定的:

如果i,j位置为左括号 dp[i][j][k]=dp[i-1][j][k-1] ||dp[i][j-1][k-1]

如果i,j位置为右括号 dp[i][j][k]=dp[i-1][j][k+1] ||dp[i][j-1][k+1]

7,边界情况dp[0][0][0]=1

8,解:dp[m-1][n-1][0]=0

解法一:dfs加剪枝

代码语言:javascript
复制
func hasValidPath(grid [][]byte) bool {
  m, n := len(grid), len(grid[0])
  if (m+n)%2 == 0 || grid[0][0] == ')' || grid[m-1][n-1] == '(' { // 剪枝
    return false
  }

  vis := make([][][]bool, m)
  for i := range vis {
    vis[i] = make([][]bool, n)
    for j := range vis[i] {
      vis[i][j] = make([]bool, m+n)
    }
  }
  var dfs func(x, y, c int) bool
  dfs = func(x, y, c int) bool {
    if c > m-x+n-y-1 { // 剪枝:即使后面都是 ')' 也不能将 c 减为 0
      return false
    }
    if x == m-1 && y == n-1 { // 终点
      return c == 1 // 终点一定是 ')'
    }
    if vis[x][y][c] { // 重复访问
      return false
    }
    vis[x][y][c] = true
    if grid[x][y] == '(' {
      c++
    } else if c--; c < 0 { // 非法括号字符串
      return false
    }
    return x < m-1 && dfs(x+1, y, c) || y < n-1 && dfs(x, y+1, c) // 往下或者往右
  }
  return dfs(0, 0, 0) // 起点
}

解法二:dp

代码语言:javascript
复制
func hasValidPath(grid [][]byte) bool {
    m, n := len(grid), len(grid[0])
    if (m+n)%2 == 0 || grid[0][0] == ')' || grid[m-1][n-1] == '(' {
        return false
    }
    dp := make([][][]bool, m)
    for i := range dp {
        dp[i] = make([][]bool, n)
        for j := range dp[i] {
            dp[i][j] = make([]bool, m+n)
        }
    }
    dp[0][0][1] = true
    for i := 0; i < m; i++ {
        for j := 0; j < n; j ++ {
            t := 1
            if grid[i][j] == ')' {
                t = -1
            }
            for k := 0; k < m+n; k ++ {
                kk := k - t
                if kk < 0 || kk >= m+n{
                    continue
                }
                if i > 0 {
                    dp[i][j][k] = dp[i][j][k] || dp[i-1][j][kk]
                }
                if j > 0 {
                    dp[i][j][k] = dp[i][j][k] || dp[i][j-1][kk]
                }
            }
        }
    }
    return dp[m-1][n-1][0]
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档