关于字符串中的括号

Posted

技术标签:

【中文标题】关于字符串中的括号【英文标题】:About parentheses in a string 【发布时间】:2016-02-17 09:22:51 【问题描述】:

在一次采访中,我被要求解决以下问题。

给定一个字符串,计算其中括号对的数量。例如,如果字符串是s = "()()",则有3对:

s[0], s[1]
s[0], s[3]
s[2], s[3]

我写了以下代码:

int count(char* s) 
  int left = 0;
  int pair = 0;
  for (int i = 0; i < strlen(s); i++) 
    char c = s[i];
    if (c == '(') 
      left++;
     else if (c == ')') 
      pair += left;
    
  
  return pair;

然后又出现了一个问题:

给定长度 L 和计数 N,用 strlen(s) == Lcount(s) == N 确定字符串 scount 是我上面写的函数;s 应该只包含括号)。例如,如果 L 为 4,N 为 3,则字符串为“()()”。

我发现,在示例中,s 也可以是“((()”或“()))”。最好把符合要求的字符串全部打印出来。

谁能解决第二个问题?谢谢你。如果你写java或者c/c++代码来解决就好了。

【问题讨论】:

你知道滑动窗口技术吗? 是的。可以在这里使用吗?你能解释一下吗? 很好,请稍等。 您是否正在尝试查找长度正确且计数正确的字符串?还是该长度的字符串数量正确? 嗯,对不起,我误解了这个问题:( 【参考方案1】:

用正确的计数生成正确长度的字符串是一项数学练习。

首先让k 成为N 平方根的底。将生成k<sup>2</sup> 字符串的最短字符串的长度为2k。看起来像(...()...)

生成k<sup>2</sup>+k 字符串的最短字符串长度为2k+1。您只需将一个 ) 附加到前一个字符串。对于介于k<sup>2</sup>k<sup>2</sup>+k 之间的N,您只需将最左侧的) 滑动到右侧数量的( 括号上。

生成k<sup>2</sup>+2k 字符串的最短字符串长度为2k+2。您只需将另一个 ) 附加到前一个字符串。对于介于k<sup>2</sup>+kk<sup>2</sup>+2k 之间的N,您只需将最左侧的) 滑动到右侧数量的( 括号上即可。

如果N 大于k<sup>2</sup>+2k,那么您没有计算平方根的下限。 :-)

如果L 比这个长度短,那么没有解决方案。如果L 大于此长度,则只需编写此解决方案并将正确数量的( 附加到末尾即可。


找到解数的正确方法是使用动态规划。你为所有长度为i 的事物建立了一个表格,有多少解决方案有j 开括号和m 总对。 (如果您愿意,可以通过标准方法将此动态编程解决方案转换为列出解决方案的方式。但列表通常会很长。)

【讨论】:

我明白了你的数学想法。请您检查一下您在第 4 段中是否有错别字? “k^2+k 个字符串的长度为 2k+1”应该是“k^2+2k 个字符串的长度为 2k+2”吗? @shengbinmeng 是的,未经修正的剪切和粘贴。对不起。【参考方案2】:

以下是用 Java 编写的动态编程解决方案。主要思想是递归地构建满足给定条件的所有可能字符串。通过添加)(,从头到尾构建字符串。让我们用

表示
public static List<String> rec(int len, int n, int r)

一个接受三个参数的方法:len 是字符串中仍有待构造的部分的长度,ncount 函数的值,r 是右括号的数量到目前为止在构建字符串的过程中使用。例如,如果我们要查找所有形式为“_ _ _ ( ) )”的字符串,则为 len = 3r = 2。很容易检查:

rec(len, n, r) =  rec(len - 1, n, r + 1), rec(len - 1, n - r, r) 

请注意,我们基本上考虑两种情况 - 添加右括号时得到的字符串(在这种情况下,r 递增),以及在当前字符串中添加左括号时得到的字符串(在那个case n 变为 n - r,因为这个新的左括号匹配到目前为止放置的所有右括号。

我们正在寻找的最终解决方案显然是rec(len, n, 0)

代码:

    private static HashMap<String, List<String>> cache = new HashMap<String, List<String>>();

    public static List<String> solution(int len, int n) 
        return rec(len, n, 0);
    

    public static List<String> rec(int len, int n, int r) 
        String key = len + "#" + n + "#" + r;
        if (cache.containsKey(key))
            return cache.get(key);
        List<String> retVal = new ArrayList<String>();
        if (len == 1) 
            if (n == r)
                retVal.add("(");
            if (n == 0)
                retVal.add(")");
            return retVal;
        
        List<String> rightParenSet = rec(len - 1, n, r + 1);
        List<String> leftParenSet = rec(len - 1, n - r, r);

        for (String s : rightParenSet)
            retVal.add(s + ")");
        for (String s : leftParenSet)
            retVal.add(s + "(");

        cache.put(key, retVal);

        return retVal;
    

    public static void main(String[] args) 
        List<String> strings = solution(4, 3);
        for(String s : strings)
            System.out.println(s);
    

两个观察结果:

缓存用于防止重复计算相同的字符串 并降低时间复杂度 这是一个自上而下的解决方案;自下而上的方法将是均匀的 更高效

【讨论】:

solution(1, 0) return "(" only, ")" is missing

以上是关于关于字符串中的括号的主要内容,如果未能解决你的问题,请参考以下文章

Python爬虫应用实战案例-jsonpath在爬虫中的应用,爬取照片信息

替换字符串中的括号和方括号

关于python的字符串格式化

正则表达式匹配括号或括号内的字符串中的数字

Oracle SQL 获取括号中的最后一个字符串(也可能包含括号)

如何在 c++ 中将字符串拆分为左括号和右括号之间的字符串列表?