zoukankan      html  css  js  c++  java
  • Leetcode——栈和队列(4)

    有效的括号

    给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

    有效字符串需满足:

    1. 左括号必须用相同类型的右括号闭合。
    2. 左括号必须以正确的顺序闭合。

    注意空字符串可被认为是有效字符串。

    示例 1:

    输入: "()"
    输出: true
    

    示例 2:

    输入: "()[]{}"
    输出: true
    

    示例 3:

    输入: "(]"
    输出: false
    

    示例 4:

    输入: "([)]"
    输出: false
    

    示例 5:

    输入: "{[]}"
    输出: true
    

    需要用一个栈,开始遍历输入字符串,

    如果当前字符为左半边括号时,则将其压入栈中,

    如果遇到右半边括号时,若此时栈为空,则直接返回 false,

    如不为空,则取出栈顶元素,

    若为对应的左半边括号,则继续循环,

    反之返回 false

    class Solution {
    public:
        bool isValid(string s) {
            stack<char> parentheses;
            for (int i = 0; i < s.size(); ++i) {
                if (s[i] == '(' || s[i] == '[' || s[i] == '{') parentheses.push(s[i]);
                else {
                    if (parentheses.empty()) return false;
                    if (s[i] == ')' && parentheses.top() != '(') return false;
                    if (s[i] == ']' && parentheses.top() != '[') return false;
                    if (s[i] == '}' && parentheses.top() != '{') return false;
                    parentheses.pop();
                }
            }
            return parentheses.empty();
        }
    }; 
    

    括号的分数

    给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

    • () 得 1 分。
    • ABA + B 分,其中 A 和 B 是平衡括号字符串。
    • (A)2 * A 分,其中 A 是平衡括号字符串。

    示例 1:

    输入: "()"
    输出: 1
    

    示例 2:

    输入: "(())"
    输出: 2
    

    示例 3:

    输入: "()()"
    输出: 2
    

    示例 4:

    输入: "(()(()))"
    输出: 6
    

    提示:

    1. S 是平衡括号字符串,且只含有 ()
    2. 2 <= S.length <= 50

    递归

    使用一个计数器,

    遇到左括号,计数器自增1,

    反之右括号计数器自减1,

    那么当计数器为0的时候,就是一个合法的字符串了,

    我们对除去最外层的括号的中间内容调用递归,然后把返回值乘以2,

    并和1比较,取二者间的较大值加到结果 res 中,

    这是因为假如中间是空串,那么返回值是0,乘以2还是0,

    但是 "()" 的分值应该是1,所以累加的时候要跟1做比较。

    之后记得要更新i都正确的位置

    class Solution {
    public:
        int scoreOfParentheses(string S) {
        	int res = 0, n = S.size();
        	for (int i = 0; i < n; ++i) {
        		if (S[i] == ')') continue;
    			int pos = i + 1, cnt = 1;
    			while (cnt != 0) {
        			(S[pos++] == '(') ? ++cnt : --cnt;
        		}
        		int cur = scoreOfParentheses(S.substr(i + 1, pos - i - 2));
        		res += max(2 * cur, 1);
        		i = pos - 1;
        	}
        	return res;
        }
    };
    

    遍历字符串S,

    当遇到左括号时,将当前的分数压入栈中,并把当前得分清0,

    若遇到的是右括号,说明此时已经形成了一个完整的合法的括号字符串了,

    而且除去外层的括号,内层的得分已经算出来了,就是当前的结果 res,

    此时就要乘以2,并且要跟1比较,取二者中的较大值,

    然后还要加上栈顶的值,因为栈顶的值是之前合法括号子串的值,跟当前的是并列关系,所以是相加的操作,

    最后不要忘了要将栈顶元素移除即可

    class Solution {
    public:
        int scoreOfParentheses(string S) {
            int res = 0;
            stack<int> st;
            for (char c : S) {
                if (c == '(') {
                    st.push(res);
                    res = 0;
                } else {
                    res = st.top() + max(res * 2, 1); 
                    st.pop();
                }
            }
            return res;
        }
    };
    

    删除最外层的括号

    有效括号字符串为空 ("")"(" + A + ")"A + B,其中 AB 都是有效的括号字符串,+ 代表字符串的连接。例如,"""()""(())()""(()(()))" 都是有效的括号字符串。

    如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语(primitive),其中 AB 都是非空有效括号字符串。

    给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。

    S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S

    示例 1:

    输入:"(()())(())"
    输出:"()()()"
    解释:
    输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
    删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
    

    示例 2:

    输入:"(()())(())(()(()))"
    输出:"()()()()(())"
    解释:
    输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
    删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
    

    示例 3:

    输入:"()()"
    输出:""
    解释:
    输入字符串为 "()()",原语化分解得到 "()" + "()",
    删除每个部分中的最外层括号后得到 "" + "" = ""。
    

    提示:

    1. S.length <= 10000
    2. S[i]"("")"
    3. S 是一个有效括号字符串
    class Solution {
    public:
        string removeOuterParentheses(string S) {
            int L=1, R=0;
            string ans;
            for(int i=1; i<S.size(); i++){
                
                if(S[i] == '(') L++;
                else R++;
                
                if(R != L) ans.push_back(S[i]);
                else {
                    i++;
                    L = 1;
                    R = 0;
                }
                
            }
            return ans;
        }
    };
    

    使括号有效的最少添加

    给定一个由 '('')' 括号组成的字符串 S,我们需要添加最少的括号( '(' 或是 ')',可以在任何位置),以使得到的括号字符串有效。

    从形式上讲,只有满足下面几点之一,括号字符串才是有效的:

    • 它是一个空字符串,或者
    • 它可以被写成 ABAB 连接), 其中 AB 都是有效字符串,或者
    • 它可以被写作 (A),其中 A 是有效字符串。

    给定一个括号字符串,返回为使结果字符串有效而必须添加的最少括号数。

    示例 1:

    输入:"())"
    输出:1
    

    示例 2:

    输入:"((("
    输出:3
    

    示例 3:

    输入:"()"
    输出:0
    

    示例 4:

    输入:"()))(("
    输出:4
    

    提示:

    1. S.length <= 1000
    2. S 只包含 '('')' 字符。

    方法一

    统计出需要添加的左右括号个数,

    这里使用两个变量 left 和 right,分别表示需要的左右括号个数。

    遍历字符串S,

    若遇到左括号,说明此时需要右括号,则 right 自增1;

    若遇到了右括号,

    若此时 right 大于0,说明当前的右括号可以用来匹配之前的左括号,不需要另加右括号,所以此时 right 自减1;

    而若此时 right 为0,说明当前的右括号前面没有左括号可以跟其匹配,则此时 left 自增1,表示需要额外的左括号。

    最后返回 left+right 即为所求

    class Solution {
    public:
        int minAddToMakeValid(string S) {
            int left = 0, right = 0;
            for (char c : S) {
                if (c == '(') {
                    ++right;
                } else if (right > 0) {
                    --right;
                } else {
                    ++left;
                }
            }
            return left + right;
        }
    };
    

    方法二

    只用一个变量 cnt,表示当前左括号的个数。

    遍历字符串S,

    当遇到左括号,而此时 cnt 为负数时,表示此时右括号是多余左括号的,

    而当前遇到的左括号不能匹配之前的右括号,所以将 cnt 的绝对值加到结果 res 中,表示需要这多么的左括号来匹配之前多出的右括号。

    然后此时 cnt 自增1,因为当前遇到的是左括号,

    若当前遇到右括号,则 cnt 自减1,最终返回 res 加上 cnt 的绝对值即为所求

    class Solution {
    public:
        int minAddToMakeValid(string S) {
            int res = 0, cnt = 0;
            for (char c : S) {
                if (c == '(') {
                    if (cnt < 0) {
                        res += abs(cnt);
                        cnt = 0;
                    }
                    ++cnt;
                } else {
                    --cnt;
                }
            }
            return res + abs(cnt);
        }
    };
    

    反转每对括号间的子串

    给出一个字符串 s(仅含有小写英文字母和括号)。

    请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。

    注意,您的结果中 不应 包含任何括号。

    示例 1:

    输入:s = "(abcd)"
    输出:"dcba"
    

    示例 2:

    输入:s = "(u(love)i)"
    输出:"iloveu"
    

    示例 3:

    输入:s = "(ed(et(oc))el)"
    输出:"leetcode"
    

    示例 4:

    输入:s = "a(bcdefghijkl(mno)p)q"
    输出:"apmnolkjihgfedcbq"
    

    提示:

    • 0 <= s.length <= 2000
    • s 中只有小写英文字母和括号
    • 我们确保所有括号都是成对出现的
    class Solution {
    public:
        string reverseParentheses(string s) {
            string res;
            stack<string> stk;
            for (char &c : s) {
                if (c == '(') {
                    stk.push(res);
                    res = "";
                } else if (c == ')') {
                    reverse(res.begin(), res.end());
                    res = stk.top() + res;
                    stk.pop();
                } else {
                    res.push_back(c);
                }
            }
            return res;
        }
    };
    

    移除无效的括号

    给你一个由 '('')' 和小写字母组成的字符串 s

    你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。

    请返回任意一个合法字符串。

    有效「括号字符串」应当符合以下 任意一条 要求:

    • 空字符串或只包含小写字母的字符串
    • 可以被写作 ABA 连接 B)的字符串,其中 AB 都是有效「括号字符串」
    • 可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」

    示例 1:

    输入:s = "lee(t(c)o)de)"
    输出:"lee(t(c)o)de"
    解释:"lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。
    

    示例 2:

    输入:s = "a)b(c)d"
    输出:"ab(c)d"
    

    示例 3:

    输入:s = "))(("
    输出:""
    解释:空字符串也是有效的
    

    示例 4:

    输入:s = "(a(b(c)d)"
    输出:"a(b(c)d)"
    

    提示:

    • 1 <= s.length <= 10^5
    • s[i] 可能是 '('')' 或英文小写字母

    遇到字母一律不用考虑,影响结果的只有括号

    遍历字符串,遇到字母跳过,遇到‘(’入栈其对应的索引,遇到‘)’判断栈里面有没有左括号,如果有则弹出栈顶元素,如果没有那么这个‘)’就必须删除,我们将该位置的‘)’换为*

    遍历完之后,如果此时栈非空,那么栈里面的索引对应的‘(’全要换为 *

    s中的*全删除即的所需字符串。

    class Solution {
    public:
        string minRemoveToMakeValid(string s) {
            stack<int>stk;
            int len = s.size();
            for(int i = 0;i<len;i++){
                if(s[i]=='(')
                    stk.push(i);
                else if(s[i]==')'){
                    if(!stk.empty())stk.pop();
                    else s[i]='*';//标记下待会删掉
                }
            }
            int temp;
            while(!stk.empty()){
                temp=stk.top();
                stk.pop();
                s[temp]='*';
            }
            s.erase(remove(s.begin(),s.end(),'*'),s.end());
            return s;
        }
    };
    
  • 相关阅读:
    使用samba实现linux和windows文件共享
    使用li列举属性表中的某一属性
    popuptemplate的使用
    html中自动分配界面
    div中移除和添加元素
    使用v-html绑定数据,实现图片的动态转换
    使用js下载数据
    使用FeatureTable对FeatureLayer中的数据进行显示
    使用ant的checkboxGroup将列表信息添加为多选框,并根据多选框的转换进行操作
    arcgis api绘制多个点
  • 原文地址:https://www.cnblogs.com/wwj99/p/12971491.html
Copyright © 2011-2022 走看看