栈 队列

**

使括号有效的最少添加

**

** 问题描述 😗*

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

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

它是一个空字符串,或者

它可以被写成 AB (A 与 B 连接), 其中 A 和 B 都是有效字符串,或者

它可以被写作 (A),其中 A 是有效字符串。

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

示例 1:

输入:"())"

输出:1

示例 2:

输入:"((("

输出:3

示例 3:

输入:"()"

输出:0

示例 4:

输入:"()))(("

输出:4

输入说明 :

输入一个由 ‘(’ 和 ‘)’ 括号组成的字符串 S

输出说明 :

输出一个整数,表示为使结果字符串有效而必须添加的最少括号数
!](https://img-blog.csdnimg.cn/20200717080715849.png)

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int num(string str){
    stack <char> s;
    int len=str.length();
    for(int i=0;i<len;i++){
       if(s.size()==0)//如果栈为空,直接入栈
        s.push(str[i]);
       else{
            if(s.top()=='('&&str[i]==')')//如果栈顶是'(',此时字符为' )',凑成一个括号,将栈顶弹出
                s.pop();
            else
                s.push(str[i]);
       }
    }
    return s.size();//此时栈的大小就是无法配成括号的字符数,也就需要添加栈大小个括号
}
int main(){
    string s;
    getline(cin,s);
    cout<<num(s)<<endl;
    return 0;
}

**

反转每对括号间的子串

**

问题描述 :

给出一个字符串 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 中只有小写英文字母和括号

我们确保所有括号都是成对出现的

输入说明 :

输入仅含有小写英文字母和括号的字符串

输出说明 :

输出一行,表示结果

输入范例 :

(u(love)i)
iloveu

//思路:不需要栈,根本在于记录( 出现的下标,当出现 ) 时,利用reverse 将这期间的字符串进行反转,一次遍历字符串的过程中,边遍历边反转,最后再处理字符串中()的问题
#include<iostream>
#include<stack>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
 string reverseParentheses(string str) {
    vector <int> index;
    int len=str.length();
    int i;
    for( i=0;i<len;i++){
        if(str[i]=='('){
            index.push_back(i);//记录( 出现的位置
           }
        if(!index.empty()&&str[i]==')'){  //出现)之后,将( 到 ) 期间的字符串进行反转
            reverse(str.begin()+index.back()+1,str.begin()+i);
            index.pop_back();
        }
      }
      //反转结束,处理括号问题
     for(i=0;i<len;i++){
        if(str[i]=='(' || str[i]==')'){
            str.erase(str.begin()+i);
            i--;
        }
     }
     return str;
    }
int main(){
    string s;
    getline(cin,s);
    s=trans(s);
    cout<<s<<endl;
    return 0;
}


字符串解码

问题描述 :

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:

输入:s = “3[a]2[bc]”

输出:“aaabcbc”

示例 2:

输入:s = “3[a2[c]]”

输出:“accaccacc”

示例 3:

输入:s = “2[abc]3[cd]ef”

输出:“abcabccdcdcdef”

示例 4:

输入:s = “abc3[cd]xyz”

输出:“abccdcdcdxyz”

输入说明 :

输入一行,表示经过编码的字符串

输出说明 :

输出一行,表示解码后的字符串

输入范例 :

在这里插入图片描述

//这个一开始偶觉得和上题有点大同小异,记录[ 出现的下标,将[  到 ] 之间的字符串赋值某次,在插入字符串中,可是这时候还要处理此时遍历的下标问题,就另辟一个结果string来存储
//小窍门,我觉得利用vector来模拟栈简直太爽,少记一个容器的方法使用真好,queue虽然也可利用vector,但是优先队列(大根堆、小根堆)就没法用vector了
#include<iostream>
#include<string>
#include<stack>
#include<vector>
using namespace std;
string decodeString(string str){
    int len=str.length();
   
    string res="";
    stack <string> s;
    stack <int> k;
     int i,num=0;
    for(i=0;i<len;i++){
        
       if(isdigit(str[i])){
           num+=num*10+str[i]-'0';
        }
         else if(isalpha(str[i])){
            res+=str[i];
        }
        else if(str[i]=='['){
            k.push(num);
            num=0;
            s.push(res);
            res="";
        }
        else if(str[i]==']'){
            int j=k.top();
            k.pop();
            while(j--){
                s.top()+=res;
            }
            res=s.top();
            s.pop();
        }
    }
    return res;
}
int main()

{

    string str;

    getline(cin,str);

    string result=decodeString(str);

    cout<<result<<endl;
    return 0;
}

和至少为 K 的最短子数组

问题描述 :

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。

如果没有和至少为 K 的非空子数组,返回 -1 。

示例 1:

输入:A = [1], K = 1

输出:1

示例 2:

输入:A = [1,2], K = 4

输出:-1

示例 3:

输入:A = [2,-1,2], K = 3

输出:3

说明:

1 <= A.length <= 50000

-10 ^ 5 <= A[i] <= 10 ^ 5

1 <= K <= 10 ^ 9

输入说明 :

首先输入A数组元素的数目n

然后输入n个整数

最后输入k

输出说明 :

输出一个整数,表示结果

输入范例 :

在这里插入图片描述

//利用双端队列
#include<iostream>
#include<string>
#include<deque>
#include<vector>
using namespace std;
int shortestSubarray(vector <int> &A,int k){
    int n=A.size(),i;
    int res=n+1;
    vector<int> sum(n+1,0);
    for(i=0;i<n;i++){
        sum[i+1]=sum[i]+A[i];
    }
    i=0;
    deque<int> d;
    while(i<=n){
        while(!d.empty()&& sum[i] <= sum[d.back()]){
            d.pop_back();
        }
        while(!d.empty() && sum[i] - sum[d.front()]>=k){
            //res=i-d.front()>res ? i-d.front():res;
            res = min( res, i - d.front());
            d.pop_front();
        }
        d.push_back(i);
        i++;
    }
    if(res==n+1)
        return -1;
    else
        return res;
}
int main()

{

    vector<int> A;

    int n,data,k;

    cin>>n;

    for(int i=0; i<n; i++)

    {

        cin>>data;

        A.push_back(data);

    }

    cin>>k;

    int result=shortestSubarray(A,k);

    cout<<result<<endl;

    return 0;

}

任务调度器

问题描述 :

给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。

然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。

你需要计算完成所有任务所需要的最短时间。

示例 :

输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2

输出:8

解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B.

 在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。 

说明:

任务的总个数为 [1, 10000]。

n 的取值范围为 [0, 100]。
输入说明 :

首先输入任务的数目len

然后输入len个大写的 A - Z 字母,无空格、无引号

最后输入n

输出说明 :

输出一个整数,表示结果

输入范例 :
在这里插入图片描述

桶思想解答https://leetcode-cn.com/problems/task-scheduler/solution/tong-zi-by-popopop/

#include<iostream>
#include<vector>
using namespace std;
 int leastInterval(vector<char>& tasks, int m) {
        vector<int> num(26,0);
        int i,n;
        //统计各个字母出现的次数
        for(i=0;i<tasks.size();i++){
            num[tasks[i]-'A']++;
        }
        int max_count=0,sum=0;
        for(i=0;i<26;i++){
                sum+=num[i];
                //找到出现次数最多的
            if(num[i]>max_count){
                max_count=num[i];
                n=0;
            }
            //计算最大次数的个数
            if(num[i]==max_count){
                n++;
            }
        }
        return max((max_count-1)*(m+1)+n,sum);
    }
int main()

{

    vector<char> v;

    int len,m;

    char data;

    cin>>len;

    for(int i=0; i<len; i++)

    {

        cin>>data;

        v.push_back(data);

    }

    cin>>m;

    int result=leastInterval(v,m);

    cout<<result<<endl;

    return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值