1、leecode232 用栈实现队列
使用栈模拟队列的行为,仅使用一个栈是不行的,所以需要两个栈,一个是输入栈,一个是输出栈。
#include
#include
#include
#include
#include
using namespace std;
class MyQueue {
private:
stack stack_in;
stack stack_out;
public:
void push(int value) {
stack_in.push(value);
}
int pop() {
if (stack_out.empty()) {
while (!stack_in.empty()) {
stack_out.push(stack_in.top());
stack_in.pop();
}
}
int result = stack_out.top();
stack_out.pop();
return result;
}
int top() {
if (stack_out.empty()) {
while (!stack_in.empty()) {
stack_out.push(stack_in.top());
stack_in.pop();
}
}
int result = stack_out.top();
return result;
}
bool empty() {
return stack_in.empty() && stack_out.empty();
}
};
void main() {
MyQueue queue;
queue.push(1);
queue.push(2);
queue.push(3);
cout << "the first value: " << queue.pop() << endl;
cout << "the next value: " << queue.pop() << endl;
cout << "the next value: " << queue.pop() << endl;
cout << "hello world" << endl;
}
2、用队列实现栈。 leetcode225
队列的规则是先进先出,把一个队列中的数据导入另一个队列,数据的顺序并没有变。所以用栈实现队列和用队列实现栈的思路是不一样的,取决于这两个数据结构的性质。如果用两个对列实现栈,那么两个队列就没有输入队列和输出队列的关系,另一个队列完全是用来备份的。
#include
#include
#include
#include
#include
using namespace std;
class MyStack {
private:
queue queue_fir;
queue queue_sec;
public:
void push(int val) {
queue_fir.push(val);
}
int pop() {
int size = queue_fir.size();
size--;
while (size--) {
queue_sec.push(queue_fir.front());
queue_fir.pop();
}
int result = queue_fir.front();
queue_fir.pop();
queue_fir = queue_sec;
while (!queue_sec.empty()) {
queue_sec.pop();
}
return result;
}
int top() {
return queue_fir.back();
}
bool empty() {
return queue_fir.empty();
}
};
void main() {
MyStack stack;
stack.push(1);
stack.push(2);
stack.push(3);
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << "hello world" << endl;
}
3、匹配括号 leetcode20
这里有三种不匹配的情况
(1)、第一种情况,字符串中左方向的括号多余了,所以不匹配。
第一种情况:已经遍历了字符串,但是栈不为空,说明有相应的左括号,但没有右括号,所以返回错误。
(2)、第二种情况,括号没有多余,但是括号的类型不匹配。
在遍历字符串的过程中,发现栈中没有要匹配的字符,返回错误。
(3)、第三种情况,字符串中右方向的括号多余了,所以不匹配。
在遍历字符串的过程中栈已经为空,没有匹配的字符了,说明右括号没有找到对应的左括号,返回错误。
那么什么时候说明左括号和右括号全部匹配了呢?如果遍历字符串之后,栈是空的,则说明全都匹配了。
#include
#include
#include
#include
#include
using namespace std;
class Solution {
private:
stack st;
public:
bool IsValid(string& s) {
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') {
st.push(')');
}
else if (s[i] == '{') {
st.push('}');
}
else if (s[i] == '[') {
st.push(']');
}
else if (st.empty() || st.top() != s[i]) {
return false;
}
else {
st.pop();
}
}
return st.empty();
}
};
void main() {
string s = "(){}[]{[]}";
Solution slo;
slo.IsValid(s);
cout << "hello world" << endl;
}
4、滑动窗口最大值 leetcode239
一个大小为k的滑动窗口,从前向后在数组nums上移动,返回滑动窗口每移动一次时窗口中的最大值。
(1)、设计单调对列,设计的时候,pop和push操作保持如下规则:
pop():如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不进行任何操作。
push():如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于或等于队列入口元素的数值。
基于以上规则,每次窗口移动的时候,只要调用que.front()就可以返回当前窗口的最大值。
#include
#include
#include
#include
#include
#include
using namespace std;
//单调队列,从大到小
class MyQueue {
private:
deque que;
//使用deque实现单调队列
public:
//每次弹出元素时,比较当前要弹出元素的数值是否等于队列出口元素的数值,如果相等则弹出。
//弹出元素之前,需要判断队列当前是否为空
void pop(int value) {
if (!que.empty() && value == que.front()) {
que.pop_front();
}
}
//如果要push的数组大于入口元素的数值,那么就将队列入口元素弹出,知道push的数值小于或等于对列入口元素的数值。
//这样就保持了队列中的数值是从大到小的单调递减了。
void push(int value) {
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value);
}
int front() {
return que.front();
}
};
void main() {
cout << "hello world" << endl;
}
这样就用deque实现了一个单调队列,接下来解决求滑动窗口最大值的问题就简单了。
#include
#include
#include
#include
#include
#include
using namespace std;
class Slotuion {
private:
//单调队列,从大到小
class MyQueue {
private:
deque que;
//使用deque实现单调队列
public:
//每次弹出元素时,比较当前要弹出元素的数值是否等于队列出口元素的数值,如果相等则弹出。
//弹出元素之前,需要判断队列当前是否为空
void pop(int value) {
if (!que.empty() && value == que.front()) {
que.pop_front();
}
}
//如果要push的数组大于入口元素的数值,那么就将队列入口元素弹出,知道push的数值小于或等于对列入口元素的数值。
//这样就保持了队列中的数值是从大到小的单调递减了。
void push(int value) {
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value);
}
int front() {
return que.front();
}
};
private:
MyQueue que;
public:
vector MaxSlidingWindow(vector &input,int k) {
vector result;
for (int i = 0; i < k; i++) {
que.push(input[i]);
}
result.push_back(que.front());
for (int i = k; i < input.size(); i++) {
que.push(input[i]);
que.pop(input[i - k]);
result.push_back(que.front());
}
return result;
}
};
void main() {
vector input = { 2,4,-2,-4,3,1,5 };
int k = 4;
Slotuion slo;
slo.MaxSlidingWindow(input, k);
cout << "hello world" << endl;
}
5、前K个高频元素 leetcode347
在一个数组中找到出现频率前k高的元素。
这道题目主要涉及如下三个部分:
(1)、统计元素出现的次数;
(2)、对次数进行排序;
(3)、找出前k个高频元素。
首先统计元素出现的次数,可以使用map进行统计。然后对次数进行排序,这里可以使用一种容器适配器即优先级对列。
优先级队列是一个拥有权值的queue,其内部元素按照元素的权值排列。权值较高者排在最前优先出队。其中缺省情况下系统是通过一个max-heap以堆实现完成排序特性,表现为一个vector表现的完全二叉树。
这是一个queue,所以只允许在底端加入元素,并从顶端取出元素。
但是优先级队列中的元素并非依照被推入队列的顺序排列。而是自动依照元素的权值排列。权值最高者排在最前面。
缺省的情况下维护的是一个大堆,即权值以从高到低排列。
其中Type代表数据类型,Container代表容器类型,缺省状态为vector; Functional是比较方式,默认采用的是大顶堆(less<>)。
#include
#include
#include
#include
#include
using namespace std;
class Solution {
public:
class MyCompare {
public:
bool operator()(const pair& lhs, const pair& rhs) {
return lhs.second > rhs.second;
}
};
vector TopKFrequent(vector& input, int k) {
unordered_map map;
for (int i = 0; i < input.size(); i++) {
map[input[i]]++;
}
priority_queue,vector>, MyCompare> pri_que;
for (auto iter = map.begin(); iter != map.end(); iter++) {
pri_que.push(*iter);
if (pri_que.size() > k) {
pri_que.pop();
}
}
vectorresult(k);
for (int i = k - 1; i >= 0; i--) {
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};
void main() {
vector input = { 2,2,2,2,2,3,3,3,1 };
int k = 2;
Solution slo;
slo.TopKFrequent(input, k);
cout << "hello world" << endl;
}