【回溯算法】回溯与二叉树:再谈括号生成问题

括号生成问题

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:

输入:n = 3
输出:[
       "((()))",
       "(()())",
       "(())()",
       "()(())",
       "()()()"
     ]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/generate-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处

继昨天归纳了回溯的一些题目之后,今天又重新做了一下“括号生成”,有新的感觉。

思考方向

参考全排列那道题的思路:
【回溯算法】回溯与二叉树:再谈括号生成问题_第1张图片

我也自己去画了张图,丑是丑了点
【回溯算法】回溯与二叉树:再谈括号生成问题_第2张图片
然后我就去实现

第一代版本


void kuohaoDFS(int left,int right,string temp, vector<string>& ret) {
	//剪枝(应该是没那机会了)
	if (left > right)
		return;

	//返回条件
	if (left == 0 && right == 0) {
		ret.push_back(temp);
		return;
	}

	//如果有左括号
	if (left > 0) {
		temp.push_back('(');
		left-=1;
		kuohaoDFS(left, right, temp , ret);
	}
		
	//如果有右括号
	if (right > 0) {
		temp.push_back(')');
		right-=1;
		kuohaoDFS(left, right, temp , ret);
	}
}

vector<string> kuohao(int n) {
	vector<string> ret;
	kuohaoDFS(n, n,"",ret);
	return ret;
}

果不其然,失败了。

我觉得是因为left-1right-1放早了,就像二叉树的谦虚遍历,也没见先root = root->left之后再传root为参的。

因为调试一下之后发现:当回溯的时候,对于括号数量的计数总会多一个出来,于是我就修改了代码。

第二代版本


void kuohaoDFS(int left,int right,string temp, vector<string>& ret) {
	//剪枝(应该是没那机会了)
	if (left > right)
		return;

	//返回条件
	if (left == 0 && right == 0) {
		ret.push_back(temp);
		return;
	}

	//如果有左括号
	if (left > 0) {
		temp.push_back('(');
		//left-=1;
		kuohaoDFS(left-1, right, temp , ret);
	}
		
	//如果有右括号
	if (right > 0) {
		temp.push_back(')');
		//right-=1;
		kuohaoDFS(left, right-1, temp , ret);
	}
}

vector<string> kuohao(int n) {
	vector<string> ret;
	kuohaoDFS(n, n,"",ret);
	return ret;
}

修改之后,还是没能彻底解决问题我就想,是不是因为字符串的问题,因为在函数进入下一层的时候,状态就已经被改变了,所以回退之后是回退到状态改变之后的样子,就引起了断层。
于是我又改了代码。

第三个版本


void kuohaoDFS(int left,int right,string temp, vector<string>& ret) {
	//剪枝(应该是没那机会了)
	if (left > right)
		return;

	//返回条件
	if (left == 0 && right == 0) {
		ret.push_back(temp);
		return;
	}

	//如果有左括号
	if (left > 0) {
		kuohaoDFS(left - 1, right,temp+'(',ret);
	}
		
	//如果有右括号
	if (right > 0) {
		kuohaoDFS(left, right - 1,temp+')',ret);
	}
}

vector<string> kuohao(int n) {
	vector<string> ret;
	kuohaoDFS(n, n,"",ret);
	return ret;
}

这个版本终于是稳定了。

后来

后来我想了好久,确实就是二叉树的便利,剪枝,并读取叶子节点的内容。

不一样的是在遍历的过程中要对树进行构造。

我又想了其他的题目,其他题目就是对多叉树的遍历,或取叶子,或取路径,或每个节点都要。

回溯算法入门推荐

【回溯算法】从入门到入土,七道试题精选、精讲、精练

你可能感兴趣的:(算法/数构,算法)