一起刷LeetCode——括号生成(递归)

61 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

括号生成

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

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ge…

分析

  • n是要生成括号的对数,那有2n个符号,所以

从排列的角度递归

  • 通过全排列,就可以得出所有的组合,然后再判断当前的组合是否是有效的,也就是符和括号出现顺序,这样解有些暴力,时间复杂度O(2^2n * n)
  • 在生成全排列的时候,可以比较容易的得出递推公式f(n)=f(n-1)+'('或者')',所以比较容易想到使用递归的写法来生成
  • 在生成了所有的排列之后再判断是否有效,有点亡羊补牢的意思,在算法相关的题目中,未雨绸缪永远比亡羊补牢快,因此我们可以在对序列进行的排序的时候,不像全排列那样无脑排下一个,而是判断下一个是左括号还是有括号,以左括号为主,如果右括号数量小于左括号数量就放一个右括号,这样就有效的降低了时间复杂度

代码

const generateParenthesis = (n) => {
  const res = [];

  const go = (l, r, s) => {
    if (s.length === 2 * n) {
      res.push(s);
      return;
    }

    if (l < n) go(l + 1, r, s + '(');
    if (r < l) go(l, r + 1, s + ')');
  };

  go(0, 0, '');
  return res;
};

从生成的括号长度的角度递归

  • 一定是左括号开始的
  • 左括号的个数一定等于右括号,并且在计算下一个位置是左括号还是右括号的时候,左括号个数都应该大于或等于右括号

代码

const generateParenthesis = (n) => {
  const res = [];

  const go = (l, r, s) => { 
    if (l > r) return;
    
    if (l === 0 && r === 0) {
      res.push(s);
      return;
    }

    if (l > 0) go(l - 1, r, s + '(');
    if (r > 0) go(l, r - 1, s + ')');
  };

  go(n, n, '');
  return res;
};

总结

  • 这道题是难度为中等的题目,当在使用递归的时候,更多想到的可能是第一种方法,在关注元素的同时也要多关注元素的另一个属性:位置。就像xy轴,在关注x轴的同时也要想一下y轴,有时候可能思路就会打开了
  • 今天也是有收获的一天