leetcode10 Regular Expression Matching @python

leetcode里一道hard难度的题(第10题),

题主已经栽死在里面,借鉴了别人优秀的思想用python实现了,经典的东西要保留。

感谢@Vosky,出处链接http://blog.csdn.net/hk2291976/article/details/51165010


题目描述:

Implement regular expression matching with support for ‘.’ and ‘*’.

‘.’ Matches any single character. 
‘*’ Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be: 
bool isMatch(const char *s, const char *p)

Some examples: 
isMatch(“aa”,”a”) → false 
isMatch(“aa”,”aa”) → true 
isMatch(“aaa”,”aa”) → false 
isMatch(“aa”, “a*”) → true 
isMatch(“aa”, “.*”) → true 
isMatch(“ab”, “.*”) → true 
isMatch(“aab”, “c*a*b”) → true

这题最难的就是对‘*’的判断,情况多到超出你我想象,

但是有一点,”*”不会单独出现,它一定是和前面一个字母或”.”配成一对。看成一对后”X*”,它的性质就是:要不匹配0个,要不匹配连续的“X”。

题目的关键就是如何把这一对放到适合的位置。

考虑一个特殊的问题: 
情况1: 
“aaaaaaaaaaaaaaaa” 
“a*aa*”

情况2: 
“aaaaaaaaaaaaaaaa” 
“a*ab*”

在不知道后面的情况的时候,我如何匹配a*?

  • 最长匹配 
    显然不合适,这样后面的a就无法匹配上了

  • 匹配到和后面长度一样的位置,比如情况1,就是留3个a不匹配,让后面3个字母尝试去匹配。 
    这样看似合适,但是遇到情况2就不行了。

  • 回溯,每种”*”的情况,看哪种情况能成功,如果其中出现了问题,马上回溯,换下一种情况

下面题主考虑两种方法。(DP太难,题主已弃)


法一:回溯法(暴力法):考虑所有结果

如果“*”不好判断,那我大不了就来个暴力的算法,把“*”的所有可能性都测试一遍看是否有满足的,用两个指针i,j来表明当前s和p的字符。

我们采用从后往前匹配,为什么这么匹配,因为如果我们从前往后匹配,每个字符我们都得判断是否后面跟着“*”,而且还要考虑越界的问题。但是从后往前没这个问题,一旦遇到“*”,前面必然有个字符。

 

如果j遇到 ”*”,我们判断s[i] 和p[j-1]是否相同,

如果相同我们可以先尝试匹配掉s的这个字符,i–,然后看之后能不能满足条件,满足条件,太棒了!我们就结束了,如果中间出现了一个不满足的情况,马上回溯到不匹配这个字符的状态。

不管相同不相同,都不匹配s的这个字符,j-=2 (跳过“*”前面的字符)

还是递归哦

if ((i > -1) and (p[j-1] == '.' or p[j-1] == s[i])):
    if (self.myMatch(s,i-1,p,j)):
      return True
else:
   return self.myMatch(s,i,p,j-2)

如果j遇到的不是“*”,那么我们就直接看s[i]和p[j]是否相等,不相等就说明错了,返回。

if (p[j] == '.' or p[j] == s[i]):
    return self.myMatch(s,i-1,p,j-1)

再考虑退出的情况

如果j已经<0了说明p已经匹配完了,这时候,如果s匹配完了,说明正确,如果s没匹配完,说明错误。

如果i已经<0了说明s已经匹配完,这时候,s可以没匹配完,只要它还有”*”存在,我们继续执行代码。

class Solution(object):
    def isMatch(self, s, p):
        return self.myMatch(s,len(s)-1,p,len(p)-1)
    def myMatch(self, s, i, p, j):
        if j == -1:
            if i == -1:
                return True
            else:
                return False

        if (p[j] == '*'):
            if ((i > -1) and (p[j-1] == '.' or p[j-1] == s[i])):
                if (self.myMatch(s,i-1,p,j)):
                    return True
            else:
                return self.myMatch(s,i,p,j-2)
        if (p[j] == '.' or p[j] == s[i]):
            return self.myMatch(s,i-1,p,j-1)
        return False

二、用python正则库re直接解决

import re
class Solution(object):
    def isMatch(self,s,p):
        return re.match(p,s) != None


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于LeetCode上的问题994.腐烂的橘子,你可以使用Python来解决。下面是一个示例代码: ```python from collections import deque def orangesRotting(grid): # 记录网格的行数和列数 row, col = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 使用队列来保存腐烂的橘子的位置 queue = deque() # 记录新鲜橘子的数量 fresh_count = 0 # 遍历整个网格,初始化队列和新鲜橘子的数量 for i in range(row): for j in range(col): if grid[i][j] == 2: # 腐烂的橘子 queue.append((i, j)) elif grid[i][j] == 1: # 新鲜橘子 fresh_count += 1 # 如果新鲜橘子的数量为0,直接返回0 if fresh_count == 0: return 0 # 初始化分钟数 minutes = 0 # 开始进行BFS,直到队列为空 while queue: # 记录当前分钟数下,队列中的元素数量 size = len(queue) # 遍历当前分钟数下的所有腐烂的橘子 for _ in range(size): x, y = queue.popleft() # 遍历四个方向 for dx, dy in directions: nx, ny = x + dx, y + dy # 判断新位置是否在网格内,并且是新鲜橘子 if 0 <= nx < row and 0 <= ny < col and grid[nx][ny] == 1: # 将新鲜橘子变为腐烂状态 grid[nx][ny] = 2 # 将新鲜橘子的位置加入队列 queue.append((nx, ny)) # 新鲜橘子的数量减1 fresh_count -= 1 # 如果当前分钟数下,没有新鲜橘子了,结束循环 if fresh_count == 0: break # 每遍历完一层,分钟数加1 minutes += 1 # 如果最后还有新鲜橘子,返回-1,否则返回分钟数 return -1 if fresh_count > 0 else minutes ``` 你可以将给定的网格作为参数传递给`orangesRotting`函数来测试它。请注意,该代码使用了BFS算法来遍历橘子,并计算腐烂的分钟数。希望能对你有所帮助!如果有任何疑问,请随时问我。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值