2022-12-04:给定一个由 ‘[‘ ,‘]‘,‘(‘,‘)’ 组成的字符串, 请问最少插入多少个括号就能使这个字符串的所有括号左右配对, 例如当前串是 “([[])“,那么插入一个‘]‘即可满足

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-12-04:给定一个由 ‘[‘ ,‘]‘,‘(‘,‘)’ 组成的字符串, 请问最少插入多少个括号就能使这个字符串的所有括号左右配对, 例如当前串是 “([[])“,那么插入一个‘]‘即可满足相关的知识,希望对你有一定的参考价值。

2022-12-04:给定一个由 ‘[’ ,‘]’,‘(’,‘)’ 组成的字符串,
请问最少插入多少个括号就能使这个字符串的所有括号左右配对,
例如当前串是 “([[])”,那么插入一个’]'即可满足。
输出最少插入多少个括号。

答案2022-12-04:

递归。很多人会想到栈,在这里行不通的。
可能性1,先搞定l+1…r,然后搞定l。
可能性2,先搞定l…r-1,然后搞定r。
可能性3,s[l]和s[r]天然匹配,需要搞定的就是l+1…r-1。
递归这三种可能性取最小值即可。

代码用rust编写。代码如下:

use std::iter::repeat, vec;

fn main() 
    let s = "(])])(])([([[)[)]](((])][)(]]])([)(]()[((]][)(]]][)(]([)[[([[))[[[[";
    let ans = min_add(s);
    println!("", ans);
    let ans = min_add2(s);
    println!("", ans);


fn min_add(s: &str) -> i32 
    let mut n = s.len() as i32;
    let mut dp: Vec<Vec<i32>> = vec![];
    for i in 0..n 
        dp.push(vec![]);
        for _ in 0..n 
            dp[i as usize].push(-1);
        
    
    return process(s, 0, s.len() as i32 - 1, &mut dp);


fn min_add2(s: &str) -> i32 
    let a = min_add_left(s);
    let b = min_add_right(s);
    if a < b 
        a
     else 
        b
    


fn min_add_left(s: &str) -> i32 
    let sc: Vec<char> = s.chars().collect();
    let mut stack: Vec<char> = vec![];
    let mut ans = 0;
    for c in sc.iter() 
        if *c == ']' || *c == ')' 
            loop 
                if stack.len() == 0 
                    ans += 1;
                    break;
                
                if *c == ']' 
                    if stack[stack.len() - 1] == '[' 
                        stack.pop();
                        break;
                    

                    ans += 1;
                    stack.pop();
                 else if *c == ')' 
                    if stack[stack.len() - 1] == '(' 
                        stack.pop();
                        break;
                    

                    ans += 1;
                    stack.pop();
                
            
         else if *c == '[' || *c == '(' 
            stack.push(*c);
        
    
    ans + stack.len() as i32


fn min_add_right(s: &str) -> i32 
    let mut sc: Vec<char> = s.chars().collect();
    sc.reverse();
    let mut stack: Vec<char> = vec![];
    let mut ans = 0;
    for c in sc.iter() 
        if *c == '[' || *c == '(' 
            loop 
                if stack.len() == 0 
                    ans += 1;
                    break;
                
                if *c == '[' 
                    if stack[stack.len() - 1] == ']' 
                        stack.pop();
                        break;
                    
                    ans += 1;
                    stack.pop();
                 else if *c == '(' 
                    if stack[stack.len() - 1] == ')' 
                        stack.pop();
                        break;
                    
                    ans += 1;
                    stack.pop();
                
            
         else if *c == ']' || *c == ')' 
            stack.push(*c);
        
    
    ans + stack.len() as i32


// 让s[l...r]都完美匹配
// 至少需要加几个字符
fn process(s: &str, l: i32, r: i32, dp: &mut Vec<Vec<i32>>) -> i32 
    // 只有一个字符,不管是什么,要想配对,都需要添加一个字符
    if l == r 
        return 1;
    
    // 只有两个字符,
    // 如果是()、[],那什么也不需要添加
    // 否则,都需要添加2个字符
    let sc: Vec<char> = s.chars().collect();
    if l == r - 1 
        if (sc[l as usize] == '(' && sc[r as usize] == ')')
            || (sc[l as usize] == '[' && sc[r as usize] == ']')
        
            return 0;
        
        return 2;
    
    if dp[l as usize][r as usize] != -1 
        return dp[l as usize][r as usize];
    
    // 重点是如下的过程
    // 可能性1,先搞定l+1...r,然后搞定l
    // 比如s[l...r] = ([][]
    // 先搞定[][],需要添加0个,然后搞定(,需要添加1个
    // 整体变成([][])搞定
    // l....r -> l l+1....r ?
    let p1 = 1 + process(s, l + 1, r, dp);
    // 可能性2,先搞定l...r-1,然后搞定r
    // 和可能性1同理
    // l...r -> ? l...r-1 r
    let p2 = 1 + process(s, l, r - 1, dp);
    // l( ...r) l+1..r-1
    // l[    r] l+1..r-1
    // 可能性3,s[l]和s[r]天然匹配,需要搞定的就是l+1..r-1
    // 比如([[),搞定中间的[[,就是最优解了
    let mut p3 = i32::MAX;
    if (sc[l as usize] == '(' && sc[r as usize] == ')')
        || (sc[l as usize] == '[' && sc[r as usize] == ']')
    
        p3 = process(s, l + 1, r - 1, dp);
    

    // l......r
    // l..l   l+1..r
    // l..l+1 l+2..r
    // l...l+2 l+3..r
    // 可能性后续:可能,最优解并不是l....r整体变成最大的嵌套
    // 而是,并列关系!
    // l....split 先变成合法
    // split+1...r 再变成合法
    // 是并列的关系!
    // 比如(())[[]]
    // l...split : (())
    // split+1...r : [[]]
    // 这种并列关系下,有可能出最优解
    // 所以,枚举每一个可能的并列划分点(split)
    let mut ans = get_min(p1, get_min(p2, p3));
    for split in l..r 
        ans = get_min(ans, process(s, l, split, dp) + process(s, split + 1, r, dp));
    
    dp[l as usize][r as usize] = ans;
    return ans;


fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T 
    if a < b 
        a
     else 
        b
    


执行结果如下:


左神java代码

以上是关于2022-12-04:给定一个由 ‘[‘ ,‘]‘,‘(‘,‘)’ 组成的字符串, 请问最少插入多少个括号就能使这个字符串的所有括号左右配对, 例如当前串是 “([[])“,那么插入一个‘]‘即可满足的主要内容,如果未能解决你的问题,请参考以下文章

确定一个点是不是在由具有给定纬度/经度的 3 个点组成的三角形内

检查给定的字符串是不是可以由从杂志文章中截取的一组字符创建

Object.keys 返回由一个给定对象的自身可枚举属性组成的数组

编写php程序,给定一个学号,验证这个学生是不是合法,学号编码规则由九位数组成?

2023-01-06:给定一个只由小写字母组成的字符串str,长度为N, 给定一个只由01组成的数组arr,长度为N, arr[i] == 0表示str中i位置的字符不许修改, arr[i] ==

java 给定三个点由三个点求三角形周长和面积