[leetcode]高级算法——回溯算法

分割回文串

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

Input: "aab"
Output:
[
  ["aa","b"],
  ["a","a","b"]
]

Code(By myself):

class Solution(object):
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """
        res = []
        if not s:
            return res
        for i in range(len(s)):
            if self.isPalindrome(s[:i+1]):
                temp = [s[:i+1]]
                p = self.partition(s[i+1:])
                if p:
                    for j in p:
                        res.append(temp + j)
                else:
                    res.append(temp)
        return res
        
        
    def isPalindrome(self,s):
        if s == s[::-1]:
            return True
        else:
            return False

Code(others):

class Solution(object):
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """
        def search(s,i,path,res):
            if i==len(s):
                res.append(path[:])
                return
            if len(path)>=1 and path[-1]==s[i]:
                a=path[-1]
                c=a+a
                path[-1]=c
                search(s,i+1,path,res)
                path[-1]=a
            if len(path)>1 and path[-2]==s[i]:
                a,b=path[-2:]
                path.pop()
                c=a+b+a
                path[-1]=c
                search(s,i+1,path,res)
                path[-1]=a
                path.append(b)
            path.append(s[i])
            search(s,i+1,path,res)
            path.pop()
        path=[]
        res=[]
        search(s,0,path,res)
        return res
class Solution(object):
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """
        
        l = len(s)
        matrix = [[False for _ in range(l)] for _ in range(l)]
        ans = [[[]]] + [[] for _ in range(l)]
        
        for i in range(l):
            for j in range(i+1):
                if (s[j] == s[i]) and ((j + 1 > i - 1) or matrix[j+1][i-1]):
                    matrix[j][i] = True
                    for k in ans[j]:
                        tmp = k + [s[j: i+1]]
                        ans[i+1].append(tmp)
        return ans[-1]    

总结:

dfs算法

单词搜索Ⅱ

Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

Example:

Input: 
words = ["oath","pea","eat","rain"] and board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]

Output: ["eat","oath"]

Code(By myself):

class Trie(object):
    def __init__(self,value):
        self.value = value
        self.children = {}
        self.end = False

class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        res = []
        if not board or not words:
            return res
        root = Trie(None)
        
        def builtTrie(root,word):
            temp = root
            for i in word:
                if i in temp.children:
                    temp = temp.children[i]
                else:
                    node = Trie(i)
                    temp.children[i] = node
                    temp = node
            temp.end = True
        
        def search(board,root,i,j,result):
            result += board[i][j]
            if root.end:
                res.append(result)
            if not root.children:
                return
            val = board[i][j]
            board[i][j] = 'F'
            if i > 0 and board[i-1][j] in root.children:
                search(board,root.children[board[i-1][j]],i-1,j,result)
            if i < len(board)-1 and board[i+1][j] in root.children:
                search(board,root.children[board[i+1][j]],i+1,j,result)
            if j > 0 and board[i][j-1] in root.children:
                search(board,root.children[board[i][j-1]],i,j-1,result)
            if j < len(board[0])-1 and board[i][j+1] in root.children:
                search(board,root.children[board[i][j+1]],i,j+1,result)
            board[i][j] = val
            return
            
        for word in words:
            builtTrie(root,word)
        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] in root.children:
                    result = ''
                    search(board,root.children[board[i][j]],i,j,result)
        return list(set(res))

Code(others):

class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        if not board:
            return False

        # 构建Trie树
        trie = {}
        for w in words:
            t = trie
            for c in w:
                if c not in t:
                    t[c] = {}
                t = t[c]
            t['#'] = '#'

        # DFS
        self.res = set()
        self.visited = [ [False] * len(board[0]) for i in range(len(board))]
        for i in range(len(board)):
            for j in range(len(board[0])):
                self.DFS(board, i, j, trie, '')
        return list(self.res)

    def DFS(self, board, i, j, trie, pre):
        # 所有字母都存在
        if '#' in trie:
            self.res.add(pre)
        if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]):
            return
            
        if not self.visited[i][j] and board[i][j] in trie:
            tmp = board[i][j]               # 第一个字母匹配,接着判断剩下的
            self.visited[i][j] = True       # 代表已经访问过哦
            self.DFS(board, i + 1, j, trie[tmp], pre + tmp) 
            self.DFS(board, i - 1, j, trie[tmp], pre + tmp)
            self.DFS(board, i, j + 1, trie[tmp], pre + tmp) 
            self.DFS(board, i, j - 1, trie[tmp], pre + tmp)
            self.visited[i][j] = False 

总结:

为单词表建立前缀树Trie,再在字典之中匹配,可以参考单词搜索Ⅰ,dfs算法和kahn算法,实现的是dfs算法

删除无效括号

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

Example:

Input: "()())()"
Output: ["()()()", "(())()"]

Code(By myself):

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        res = []
        if not s:
            return ['']
            
        def count(s):
            right = 0
            left = 0
            for i in s:
                if i == '(':
                    left += 1
                if left == 0:
                    if i == ')':
                        right += 1
                else:
                    if i == ')':
                        left -= 1
            return [left,right]
        
        def isInvalid(s):
            stark = []
            for i in s:
                if i == '(':
                    stark.append('(')
                if i == ')':
                    if not stark:
                        return False
                    else:
                        stark.pop()
            if stark:
                return False
            else:
                return True
            
        def delete(s,start,left,right):
            if left == 0 and right == 0:
                if isInvalid(s):
                    res.append(s)
                return
            for i in range(start,len(s)):
                if i != start and s[i] == s[i-1]:
                    continue
                if left > 0 and s[i] == '(':
                    delete(s[:i]+s[i+1:],i,left-1,right)
                if right > 0 and s[i] == ')':
                    delete(s[:i]+s[i+1:],i,left,right-1)
                
        
        num = count(s)
        delete(s,0,num[0],num[1])
        return 
Code(others):
class Solution(object):
    
    def __init__( self  ) :

        self._result  = []
        
        
    def removeValid(self,  s, last_i,   last_j, keys  )  :
        '''
            @s :  string for target 
            @last_i  :  上一次统计的开始位置
            @last_j :  上一次删除的位置
            @keys : ('(', ')')  先匹配左号  ( ')','(' )   先匹配右括号

        '''

        cnt = 0
        i = last_i 


        #统计keys[0] 
        while i < len( s ) :

            if s[i] == keys[0] :  cnt += 1

            elif  s[i] == keys[1]  : cnt -= 1


            #keys[0] 数量大于等于 keys[1] 不进行字符串删除操作  需要做反向统计
            if cnt >= 0 : 
                i += 1
                continue

        
            j = last_j
            while j <= i :


                #删除符合条件的括号 比如 ()))  ---> 只需删除第一个右括号的就可以了  后面的不用再操作 或者 当前删除字符就是第一个需要删除字符
                if keys[1] == s[j] and (   j == last_j  or s[j] != s[j-1]  ) :

                    newString   = s[:j] + s[j+1:]
                    #print( newString, i, j ,"new string ")
                    self.removeValid(newString, i, j, keys )

                j += 1

            return 





        newString = s[::-1]


        if keys[0] == '(' :

            self.removeValid(newString, 0, 0, (')','(') )

            
        #反转后的结果
        else :  self._result.append(  newString )
            
        
        
        
        
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        
        
        
        self.removeValid( s, 0, 0, ('(',')' ) )
        return self._result 

总结:

三种方法,可参考https://www.cnblogs.com/grandyang/p/4944875.html

通配符匹配

Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

Example:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Code(By myself):

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        sBegin = None
        pBegin = None
        i = 0
        j = 0
        while i < len(s):
            if j < len(p) and (s[i] == p[j] or p[j] == '?'):
                i += 1
                j += 1
            elif j < len(p) and p[j] == '*':
                sBegin = i
                pBegin = j
                j += 1
            elif pBegin != None:
                sBegin += 1
                i = sBegin
                j = pBegin
            else:
                return False
        while j < len(p) and p[j] == '*':
            j += 1
        return j == len(p)
Code(others):
class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        si, pi = 0, 0;
        sn, pn = len(s), len(p)
        
        while pn > 0 and p[pn-1]!='*' :
            if sn>0 and pn>0 and (s[sn-1]==p[pn-1] or p[pn-1]=='?'):
                sn -= 1
                pn -= 1
            else: 
                return False
            
        while si<sn:
            if pi==pn : return False
            
            if s[si]==p[pi] or p[pi]=='?':
                si += 1
                pi += 1
                continue
                
            if p[pi]=='*':
                while pi<pn and p[pi]=='*': pi+=1
                if pi==pn: return True
                
                # find block
                ppos = pi
                while ppos<pn and (p[ppos]!='*'and p[ppos]!='?'): ppos+=1
            
                while si<sn and pi<pn:
                    i, j = si, pi
                    
                    if s[i]!=p[j] and p[j]!='?' : 
                        si += 1
                        continue
                    
                    while i<sn and j<pn and (s[i]==p[j] or p[j]=='?'):
                        i += 1
                        j += 1
                        
                    if i==sn or j==pn or p[j]=='*':
                        si = i
                        pi = j
                        break
                    else:
                        si += 1
            else: return False
        
        while pi < pn and p[pi]=='*': pi+=1
        if pi == pn : return True
        else : return False

总结:

可使用贪心算法,遇到*记录其位置,从匹配0个开始往上加匹配个数,若匹配失败返回并多匹配一个字符

正则表达式匹配

Given an input string (s) and a pattern (p), 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).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *.

Example:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Code(By myself):

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        i = 0
        if not p:
            return (not s)
        if (1 < len(p) and p[1] != '*') or len(p) == 1:
            if i < len(s) and (s[i] == p[0] or p[0] == '.'):
                return self.isMatch(s[i+1:],p[1:])
        elif len(p) > 1 and p[1] == '*':
            while i < len(s) and (s[i] == p[0] or p[0] == '.'):
                if self.isMatch(s[i:],p[2:]):
                    return True
                i += 1
            return self.isMatch(s[i:],p[2:])
        return False
Code(others):
class Solution(object):
    def isMatch(self, text, pattern):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """

        dp = [[False] * (len(pattern) + 1) for _ in range(len(text) + 1)]

        dp[-1][-1] = True
        for i in range(len(text), -1, -1):
            for j in range(len(pattern) - 1, -1, -1):
                first_match = i < len(text) and pattern[j] in {text[i], '.'}
                if j+1 < len(pattern) and pattern[j+1] == '*':
                    dp[i][j] = dp[i][j+2] or first_match and dp[i+1][j]
                else:
                    dp[i][j] = first_match and dp[i+1][j+1]

        return dp[0][0]

总结:

利用空间换时间,dp[i][j]用来存储是s[i]和p[j]之后的部分是否能够匹配上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值