算法刷题笔记——括号生成

请你写一个算法,输入是一个正整数 n,输出是 n 对儿括号的所有合法组合,

比如说,输入 n=3,输出为如下 5 个字符串:

"((()))", "(()())", "(())()", "()(())", "()()()"

 

C++:

#include <vector>
#include <string>
#include <iostream>
using namespace std;



// 可用的左括号数量为 left 个,可用的右括号数量为 rgiht 个
void backtrack(int left, int right, string& track, vector<string>& res) 
{
		// 若左括号剩下的多,说明不合法
		if (right < left) return;
		// 数量小于 0 肯定是不合法的
		if (left < 0 || right < 0) return;
		// 当所有括号都恰好用完时,得到一个合法的括号组合
		if (left == 0 && right == 0) {
			res.push_back(track);
			return;
		}

		// 尝试放一个左括号
		track.push_back('('); // 选择
		backtrack(left - 1, right, track, res);
		track.pop_back(); // 撤消选择

		// 尝试放一个右括号
		track.push_back(')'); // 选择
		backtrack(left, right - 1, track, res);
		track.pop_back();   // 撤消选择
}

vector<string> generateParenthesis(int n) {
	
	// 记录所有合法的括号组合
	vector<string> res;
	if (n == 0) 
		return res;
	// 回溯过程中的路径
	string track;
	// 可用的左括号和右括号数量初始化为 n
	backtrack(n, n, track, res);
	return res;
}

void main()
{
	vector<string> res;
	res = generateParenthesis(3);
	for (int i=0;i<res.size();i++)
	{
		cout << res[i] << endl;
	}
}

 

Java:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Solution01 {
    public int generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        // 特判
        if (n == 0) {
            return res.size();
        }

        // 执行深度优先遍历,搜索可能的结果
        dfs("", n, n, res);
        return res.size();
    }

    /**
     * @param curStr 当前递归得到的结果
     * @param left   左括号还有几个没有用掉
     * @param right  右边的括号还有几个没有用掉
     * @param res    结果集
     */
    private void dfs(String curStr, int left, int right, List<String> res) {
        // 因为是递归函数,所以先写递归终止条件
        if (left == 0 && right == 0) {
            res.add(curStr);
            return;
        }

        // 因为每一次尝试,都使用新的字符串变量,所以没有显式的回溯过程
        // 在递归终止的时候,直接把它添加到结果集即可,与「力扣」第 46 题、第 39 题区分

        // 如果左边还有剩余,继续递归下去
        if (left > 0) {
            // 拼接上一个左括号,并且剩余的左括号个数减 1
            dfs(curStr + "(", left - 1, right, res);
        }
        // 什么时候可以用右边?例如,((((((),此时 left < right,
        // 不能用等号,因为只有先拼了左括号,才能拼上右括号
        if (right > 0 && left < right) {
            // 拼接上一个右括号,并且剩余的右括号个数减 1
            dfs(curStr + ")", left, right - 1, res);
        }
    }

    public static void main(String[] args) {
        Solution01 s1 = new Solution01();
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        System.out.println(s1.generateParenthesis(n));
    }
}

Python

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:

        res = []
        def backtrack(left,right,sub_res):
            if left == 0 and right ==0:
                res.append("".join(sub_res[:]))
                return 
            if left > right or left < 0 or right < 0:
                return
            sub_res.append('(')
            backtrack(left-1,right,sub_res)
            sub_res.pop()

            sub_res.append(')')
            backtrack(left,right-1,sub_res)
            sub_res.pop()
        
        backtrack(n,n,[])
        return res

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值