1. 程式人生 > >列印n對括號的全部有效組合

列印n對括號的全部有效組合

這道題最基本的思路是求出n對括號的全排列,然後對每種排列方式判定是否有效。判定方法如下:

bool IsMatch(string& str)
{
	if(str.size() % 2 != 0)
		return false;
	int result = 0;	
	for(string::iterator it = str.begin(); it != str.end(); ++it)
	{
		if(*it == '(')
			++result;
		else if(*it == ')')
			--result;
		else
			return false;
			
		if(result < 0)
			return false;
	}
	return result == 0;
}
但是括號只有左括號和右括號,排列組合時有大量重複的匹配排列,每生成一次排列都要排查是不是重複,效率較低。

另一種思路是構造字串:假設當前插入一個字元,那麼有兩種選擇,插入左括號或者右括號,什麼時候可以安全的插入呢?

(1)左括號:插入左括號總是安全的,只有左括號沒有使用完,都可以插入左括號。

(2)右括號:插入右括號的時候需要注意,只有當已插入的右括號個數小於左括號的個數時,才可以插入右括號,否則永遠無法匹配。

因此函式需要分別記錄餘下的左括號和右括號數,插入左括號,下面步驟遞迴插入。或者,插入一個右括號,然後再遞迴插入,程式碼如下:

void AddParen(vector<string>& vec, int leftRem, int rightRem, string& str, int index)
{
	if(leftRem == 0 && rightRem == 0)
		vec.push_back(str);
	else
	{
		if(leftRem > 0)
		{
			str[index] = '(';
			AddParen(vec, leftRem-1, rightRem, str, index+1);
		}
		if(rightRem > leftRem)
		{
			str[index] = ')';
			AddParen(vec, leftRem, rightRem-1, str, index+1);
		}
	}
}
	
void GenerateParens(int count)
{
	if(count < 1)
		return;
			
	vector<string> vec;
	string str(count*2, ' ');
	AddParen(vec, count, count, str, 0);
	for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it)
		cout << *it << " ";
			
	cout << endl;
}