678. 有效的括号字符串
贪心
只有左右括号,本质上还根据
最后左括号数量=右括号数量,且遍历到当前下标时,左括号数量一定得大于或者等于右括号数量
class Solution {
public boolean checkValidString(String s) {
int min = 0, max = 0; // 维护当前左括号的数量范围:[min, max]
char[] chars = s.toCharArray();
for(char i : chars) {
if(i == '(') {
min++;
max++;
}else if(i == ')') {
//min > 0才--
if(min > 0) min--;
if(max-- == 0) return false;
}else {
//min > 0才--
if(min > 0) min--;
max++;
}
}
return min == 0;
}
}
作者:codeppx
链接:https://leetcode.cn/problems/valid-parenthesis-string/solution/codepi-pi-xia-shuang-zhan-tan-xin-si-lu-bua32/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
6059. 检查是否有合法括号字符串路径
回溯:超时
class Solution(object):
def hasValidPath(self, grid):
"""
:type grid: List[List[str]]
:rtype: bool
"""
def check(alist):
stack = [alist[0]]
for i in range(1, len(alist)):
if stack and alist[i] == stack[-1]:
stack.append(alist[i])
else:
if stack:
stack.pop()
else:
stack.append(alist[i])
if len(stack) == 0:
return True
return False
directions = [(1,0),(0,1)]
def dfs(start_x,start_y,left,right):
if right > left:
return False
if start_x == len(grid)-1 and start_y == len(grid[0])-1:
print(path)
if check(path):
return True
else:
return False
for direction in directions:
new_x = start_x + direction[0]
new_y = start_y + direction[1]
if new_x >= 0 and new_x <=len(grid)-1 and new_y >=0 and new_y <=len(grid[0])-1:
path.append(grid[new_x][new_y])
if grid[new_x][new_y] == "(":
left += 1
if grid[new_x][new_y] == ")":
right += 1
if dfs(new_x,new_y,left,right):
return True
path.pop()
return False
#特殊情况
path = []
path.append(grid[0][0])
if grid[0][0] == "(":
return dfs(0,0,1,0)
if grid[0][0] == ")":
return False
回溯+括号判断
只要不是带有list的回溯,是可以用lru_cache的。
注意一定要回溯,因为是在for循环里对值进行加减的
for direction in directions:
new_x = start_x + direction[0]
new_y = start_y + direction[1]
if new_x >= 0 and new_x <= len(grid) - 1 and new_y >= 0 and new_y <= len(grid[0]) - 1:
if grid[new_x][new_y] == "(":
left_count += 1
if grid[new_x][new_y] == ")":
right_count += 1
不回溯的话for循环会对left_count和right_count进行覆盖。
class Solution:
def hasValidPath(self, grid: List[List[str]]) -> bool:
directions = [(1,0),(0,1)]
@lru_cache(None)
def dfs(start_x,start_y,left_count,right_count):
if right_count > left_count:
return False
if start_x == len(grid) - 1 and start_y == len(grid[0]) - 1:
if left_count == right_count:
return True
else:
return False
for direction in directions:
new_x = start_x + direction[0]
new_y = start_y + direction[1]
if new_x >= 0 and new_x <= len(grid) - 1 and new_y >= 0 and new_y <= len(grid[0]) - 1:
if grid[new_x][new_y] == "(":
left_count += 1
if grid[new_x][new_y] == ")":
right_count += 1
if dfs(new_x, new_y, left_count,right_count):
return True
if grid[new_x][new_y] == "(":
left_count -= 1
if grid[new_x][new_y] == ")":
right_count -= 1
return False
if grid[0][0] == ")":
return False
return dfs(0,0,1,0)
记忆化深搜+括号判断
只有圆括号的情况下,不必用栈。判断方法是
左括号的数量最后与右括号相等,并且任意位置左括号数量一定不小于右括号数量。
不用回溯写法的话,不能在for循环里改变dfs的参数值
class Solution:
def hasValidPath(self, grid: List[List[str]]) -> bool:
@lru_cache(None)
def dfs(i, j, c):
if c < 0 or i == m or j == n:#当数量小于0或者超出边界则不合法
return False
c = c + 1 if grid[i][j] == "(" else c - 1#更新数量
return c == 0 if i == m - 1 and j == n - 1 else dfs(i + 1, j, c) or dfs(i, j + 1, c) #如果已经到了右下角则根据数量返回是否合法,否则继续深搜
m, n = len(grid), len(grid[0])
return dfs(0, 0, 0)
作者:qin-qi-shu-hua-2
链接:https://leetcode-cn.com/problems/check-if-there-is-a-valid-parentheses-string-path/solution/python-ji-yi-hua-shen-sou-by-qin-qi-shu-5yhnr/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
301 删除无效括号
没通过所有case的解法
#先统计出左右括号的数量,列举出需要删除的左括号和右括号,然后枚举需要删除的左括号和右括号
#注意回溯的时候要保证括号有效
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
def cal_delete(s):
left_count = 0
right_count = 0
for i in range(len(s)):
if s[i] == "(":
left_count += 1
elif s[i] == ")":
right_count += 1
return left_count, right_count
def isvalid(s):
left = 0
for i in range(len(s)):
if s[i] == "(":
left += 1
elif s[i] == ")":
left -= 1
if left < 0:
return False
return left == 0
def cal_path(path):
cur_res = []
for i in range(len(s)):
if i not in path:
cur_res.append(s[i])
return "".join(cur_res)
# flag为1表示需要删除左括号,为0表示需要删除右括号
def dfs(index, need_del_count, flag):
if need_del_count == 0:
cur_res = cal_path(path)
if isvalid(cur_res) and cur_res not in res:
res.append(cur_res)
for i in range(index, len(s)):
if flag == 1:
if s[i] == "(" and need_del_count > 0:
path.append(i)
dfs(i + 1, need_del_count - 1, flag)
path.pop()
else:
dfs(i + 1, need_del_count, flag)
if flag == 0:
if s[i] == ")" and need_del_count > 0:
path.append(i)
dfs(i + 1, need_del_count - 1, flag)
path.pop()
else:
dfs(i + 1, need_del_count, flag)
res = []
path = []
left_count, right_count = cal_delete(s)
if left_count > right_count:
need_del_count = left_count - right_count
flag = 1
else:
need_del_count = right_count - left_count
flag = 0
dfs(0, need_del_count, flag)
if len(res) == 0:
return [""]
return res
回溯+括号判断
class Solution(object):
def removeInvalidParentheses(self, s):
"""
:type s: str
:rtype: List[str]
"""
# 统计需要删除的左括号数量和右括号数量,
# 注意不能统计左右括号数量然后两者相减,因为比如")("这种情况。一定要考虑先后顺序
def del_count(s):
left_remove = 0
right_remove = 0
for i in range(len(s)):
if s[i] == "(":
left_remove += 1
elif s[i] == ")":
if left_remove > 0:
left_remove -= 1
else:
right_remove += 1
return left_remove, right_remove
def is_valid(s):
left = 0
for i in range(len(s)):
if s[i] == "(":
left += 1
elif s[i] == ")":
left -= 1
if left < 0:
return False
return left == 0
left_remove, right_remove = del_count(s)
path = []
res = []
def dfs(index, left_remove, right_remove, diff):
if diff < 0:
return
if left_remove == 0 and right_remove == 0 and index == len(s):
cur_res = "".join(path[:])
if is_valid(cur_res) and cur_res not in res:
res.append(cur_res)
return
if index == len(s):
return
if s[index] == "(":
# 要当前的左括号
path.append(s[index])
dfs(index + 1, left_remove, right_remove, diff + 1)
path.pop()
# 不要当前的左括号
if left_remove > 0:
dfs(index + 1, left_remove - 1, right_remove, diff)
elif s[index] == ")":
# 要当前的右括号
path.append(s[index])
dfs(index + 1, left_remove, right_remove, diff - 1)
path.pop()
# 不要当前的右括号
if right_remove > 0:
dfs(index + 1, left_remove, right_remove - 1, diff)
else:
path.append(s[index])
dfs(index + 1, left_remove, right_remove, diff)
path.pop()
dfs(0, left_remove, right_remove, 0)
return res