删除无效的括号【php版】

47 篇文章 1 订阅

在这里插入图片描述

代码如下,注释已经很详尽,思路就是,先计算左右括号应该至少删除的数量,然后对于每一个位置的括号而言,可删可不删就有两种情况,递归回溯

class Solution {

	private $ans = [];

	/**
	 * @param String $s
	 * @return String[]
	 */
	function removeInvalidParentheses($s) {
		$len = strlen($s);
		// 计算左右括号应该至少删除的数量
		$leftRemove = 0;
		$rightRemove = 0;

		for ($i=0; $i<$len; $i++) {
			if ($s[$i] == '(') {
				$leftRemove++;
				continue;
			}
			if ($s[$i] == ')') {
				if ($leftRemove > 0) {
					$leftRemove--;
				} else if ($leftRemove == 0) {
					$rightRemove++;
				}
			}
		}
		// 用于暂存遍历过的字符序列
		$tempArr = [];
		// 深度遍历s
		$this->dfs($s, 0, 0, 0, $leftRemove, $rightRemove, $tempArr);
		// 返回结果数组
		return array_keys($this->ans);
	}

	/**
	 * @param $s string 原字符串
	 * @param $idx int 当前处理的字符索引
	 * @param $leftCnt int 加入tempArr中的左括号计数
	 * @param $rightCnt int 加入tempArr中的右括号计数
	 * @param $leftRemove int 剩余应删除的左括号数目
	 * @param $rightRemove int 剩余应删除的右括号数目
	 * @param $tempArr array 临时数组
	 */
	function dfs($s, $idx, $leftCnt, $rightCnt, $leftRemove, $rightRemove, &$tempArr) {
		// 已经遍历完,检验结果是否符合题意,如果符合,则加入结果数组
		if ($idx == strlen($s)) {
			if ($leftRemove == 0 && $rightRemove == 0) {
				// 这儿将结果以键名的形式存储,可天然去重
				$this->ans[implode('', $tempArr)] = 1;
			}
			return;
		}

		// 对于当前字符(左右括号)的处理有两种情况:
		// 1. 去除不要
		if ($s[$idx] == '(' && $leftRemove > 0) {
			$this->dfs($s, $idx+1, $leftCnt, $rightCnt, $leftRemove-1, $rightRemove, $tempArr);
		} else if ($s[$idx] == ')' && $rightRemove > 0) {
			$this->dfs($s, $idx+1, $leftCnt, $rightCnt, $leftRemove, $rightRemove-1, $tempArr);
		}

		// 2. 需要,加入结果数组
		array_push($tempArr, $s[$idx]);

		if ($s[$idx] == '(') {
			// 2.1 左括号怎么都可加入
			$this->dfs($s, $idx+1, $leftCnt+1, $rightCnt, $leftRemove, $rightRemove, $tempArr);
		} else if ($s[$idx] == ')') {
			// 2.2 右括号在左括号数目大于右括号数目的时候可以加入
			if ($leftCnt > $rightCnt) {
				$this->dfs($s, $idx+1, $leftCnt, $rightCnt+1, $leftRemove, $rightRemove, $tempArr);
			}
		} else {
			// 其他字符直接加入
			$this->dfs($s, $idx+1, $leftCnt, $rightCnt, $leftRemove, $rightRemove, $tempArr);
		}

		// 回溯,将加入到结果数组中的字符删除
		array_pop($tempArr);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值