描述
给定一个长度为n(n<=10^6)的数组。有一个大小为k的滑动窗口从数组的最左端移动到最右端。你可以看到窗口中的k个数字。窗口每次向右滑动一个数字的距离。
下面是一个例子:
数组是 [1 3 -1 -3 5 3 6 7], k = 3。
窗口位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7
你的任务是得到滑动窗口在每个位置时的最大值和最小值。
输入
输入包括两行。
第一行包括n和k,分别表示数组的长度和窗口的大小。
第二行包括n个数字。
输出
输出包括两行。
第一行包括窗口从左至右移动的每个位置的最小值。
第二行包括窗口从左至右移动的每个位置的最大值。
样例输入
8 3
1 3 -1 -3 5 3 6 7
样例输出
-1 -3 -3 -3 3 3
3 3 5 5 6 7
#include
#include
#include
using namespace std;
int n, k, tmp;
deque<int>p;
deque<int>q;
vector<int>arr;
vector<int>MyMax;
vector<int>MyMin;
int main() {
cin >> n >> k;
for(int i = 0; i < n; ++i){
scanf("%d", &tmp);
arr.push_back(tmp);
}
for(int i = 0; i < n; ++i){
if(!p.empty() && p.front() == i - k)//把窗口划过部分的序号删掉
p.pop_front();
while(!p.empty() && arr[p.back()] < arr[i])//删去队尾比当前元素小的,肯定用不到他们
p.pop_back();
p.push_back(i);//当前元素入队
if (i >= k - 1)//从k-1开始记录(第一个窗口
MyMax.push_back(arr[p.front()]);
}
for(int i = 0; i < n; ++i){
if(!q.empty() && q.front() == i - k)
q.pop_front();
while(!q.empty() && arr[q.back()] > arr[i])
q.pop_back();
q.push_back(i);
if (i >= k - 1)
MyMin.push_back(arr[q.front()]);
}
for(int i = 0; i <= n - k; ++i)
cout << MyMin[i] << ' ';
cout << endl;
for(int i = 0; i <= n - k; ++i)
cout << MyMax[i] << ' ';
return 0;
}
总时间限制: 200ms 内存限制: 1024kB
描述
人们熟悉的四则运算表达式称为中缀表达式,例如(23+34*45/(5+6+7))。在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。
给定一个中缀表达式,编写程序,利用堆栈的方法,计算表达式的值。
输入
第一行为测试数据的组数N
接下来的N行,每行是一个中缀表达式。表达式中只含数字、四则运算符和圆括号,操作数都是正整数,数和运算符、括号之间没有空格。中缀表达式的字符串长度不超过600。
输出
对每一组测试数据输出一行,为表达式的值
样例输入
3
3+5*8
(3+5)8
(23+3445/(5+6+7))
样例输出
43
64
108
提示
注意:运算过程均为整数运算(除法运算’/'即按照C++定义的int除以int的结果,测试数据不会出现除数为0的情况),输出结果也为整数(可能为负)。
中间计算结果可能为负。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int t = 0;
int main() {
cin >> t;
cin.get();
char tmp = 0;
int opnum = 0;
while(t--){
stack<char>s;
stack<int>pos;
char line[610] = {};
string posExpression = "";
stringstream ss;
cin.getline(line, 609, '\n');
int i = 0;
while(line[i] && i < 610){
if(line[i] == '('){
s.push('(');
++i;
}
else if(line[i] >= '1' && line[i] <= '9'){
posExpression += line[i];
++i;
while(line[i] >= '0' && line[i] <= '9'){
posExpression += line[i];
++i;
}
posExpression += " ";
}
else if(line[i] == ')'){
while(s.top() != '('){
posExpression += s.top();
posExpression += " ";
s.pop();
}
s.pop();
++i;
}
else{
while((!s.empty()) && (s.top() != '(') && (((s.top() == '+' || s.top() == '-' )&&(line[i] == '+' || line[i] == '-' )) || (s.top() == '*' || s.top() == '/'))){
posExpression += s.top();
posExpression += " ";
s.pop();
}
s.push(line[i++]);
}
}
while(!s.empty()){
posExpression += s.top();
posExpression += " ";
s.pop();
}
ss.clear();
ss << posExpression;
//cout << posExpression << endl;
while(ss >> tmp){
if(tmp >= '1' && tmp <= '9'){
ss.putback(tmp);
ss >> opnum;
pos.push(opnum);
}
else{
int opnum1 = pos.top();
pos.pop();
int opnum2 = pos.top();
pos.pop();
switch(tmp){
case '+':
pos.push(opnum1 + opnum2);
break;
case '-':
pos.push(opnum2 - opnum1);
break;
case '*':
pos.push(opnum1 * opnum2);
break;
case '/':
pos.push(opnum2 / opnum1);
break;
}
}
}
cout << pos.top() << endl;
pos.pop();
}
return 0;
}
总时间限制: 1000ms 内存限制: 65535kB
描述
依次读入序列元素1,2,…,n进栈,每进一个元素,机器可要求下一个元素进栈或弹栈,如此进行。给定一个输入序列,判断栈空时弹出的元素构成的序列是否可能等于给定的序列,如果是则输出栈的操作过程,否则输出“NO”。
输入
输入分两行
第一行为n的值(即序列元素个数)
第二行为给定的输入序列(序列元素均为整型)
输出
如果输入序列能够由题目规定的操作得到,则输出对栈的操作过程
否则直接输出“NO”
样例输入
7
4 5 3 6 2 7 1
样例输出
PUSH 1
PUSH 2
PUSH 3
PUSH 4
POP 4
PUSH 5
POP 5
POP 3
PUSH 6
POP 6
POP 2
PUSH 7
POP 7
POP 1
提示
给定序列中有可能有不在1…n之间的数字
思路:先判断是否合法,再写步骤(同时进行时空间超了,这波是用时间换空间
#include
#include
#include
#include
#include
using namespace std;
int n = 0;
vector<int>v;
stack<int>s;
bool appear[1000001] = {};
bool isLegal(vector<int> & q){
int pop_idx = 0, idx = 0;
for(;idx < n; ++idx){
s.push(idx + 1);
while(!s.empty() && s.top() == q[pop_idx]){
s.pop();
++pop_idx;
}
}
return s.empty() && pop_idx == n;
//模拟过后栈s应该是空的,同时进栈元素数idx和出栈元素数pop_idx应该相等
}
int main() {
cin >> n;
for(int i = 0; i < n; ++i){
int tmp;
cin >> tmp;
if(tmp > n || tmp <= 0 || appear[tmp]){
cout << "NO" << endl;
return 0;
}
appear[tmp] = 1;
v.push_back(tmp);
}
if(!isLegal(v)){
cout << "NO" << endl;
return 0;
}
int i = 1, j = 0;
while(!s.empty())
s.pop();
while(j < n){
if(s.empty() || s.top() != v[j]){
cout << "PUSH " << i << endl;
s.push(i);
++i;
}
else{
cout << "POP " << s.top() << endl;
s.pop();
j++;
}
}
return 0;
};