目录
225.用队列实现栈
思考:队列的特性先进先出,栈后进先出,所以用一个临时temp_queue来添加新的元素,再把所有元素都导入到原始的queue之中,那么删除就正好是最新插入的元素了。
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
queue<int> obj;
/** Push element x onto stack. */
void push(int x) {
queue<int> temp_queue;
temp_queue.push(x);
while(!obj.empty()){
temp_queue.push(obj.front());
obj.pop();
//一开始没有pop导致超时了,把栈和队列想的和链表一样
//以为会覆盖值,后来想想不一样,它直接向后继续添加了。
}
while(!temp_queue.empty()){
obj.push(temp_queue.front());
temp_queue.pop();
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int x = obj.front();
obj.pop();
return x;
}
/** Get the top element. */
int top() {
return obj.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return obj.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* bool param_4 = obj.empty();
*/
232.用栈实现队列
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
stack<int> data;
stack<int> temp_stack;
/** Push element x to the back of queue. */
void push(int x) {
while(!data.empty()){
temp_stack.push(data.top());
data.pop();
}
temp_stack.push(x);
while(!temp_stack.empty()){
data.push(temp_stack.top());
temp_stack.pop();
}
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int x = data.top();
data.pop();
return x;
}
/** Get the front element. */
int peek() {
return data.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return data.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* bool param_4 = obj.empty();
*/
155.最小栈
思考:如果用一个元素minOfStack来存储最小值,在添加的时候没有问题;可是在删除的时候就会存在恰好是最小的那个元素呗删除了,那么此时最小值仍然是被删除的元素就发生了错误。并且如果是用遍历栈来查询最小值,那么时间复杂度就不是O(1)。所以可以构造一个临时存储最小值的栈,栈中每一个位正好对应当前情况下栈的最小值。
编程的技巧:当一个操作无论在条件发生不发生的时候都会执行,可以放在条件语句之外。
例如:当前添加元素x如果大于min_stack_top,就把x赋值为min_stack_top;如果小于则直接添加;因为无论小于还是大于都要添加一个新的元素到min_stack_top。
class MinStack {
public:
/** initialize your data structure here. */
MinStack() {
}
stack<int> stack_data;
stack<int> min_stack;
void push(int x) {
stack_data.push(x);
if(min_stack.empty()){
min_stack.push(x);
}
else{
if(x > min_stack.top()){
x = min_stack.top() ; //关键!
}
min_stack.push(x);
}
}
void pop() {
stack_data.pop();
min_stack.pop();
}
int top() {
return stack_data.top();
}
int getMin() {
return min_stack.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
例题4.合法的出栈序列
思考:使用栈和队列来模拟入栈和出栈的过程。
用队列来存储出栈序列,然后用栈来模拟出栈入栈的过程,因为出战序列的第一位肯定是栈中的top元素,所以每次只用对比top元素和出战序列的front,两者相等就同时弹出,否则就再入栈。
#include<stack>
#include<queue>
bool check_is_valid_order(queue<int> &order)
{
stack<int> s;
int num = order.size();
for(int i =1 ;i <= num;i++){
s.push(i);
// while(order.front()==s.top()) 如果栈已经弹空了,队列也是空了,都是NULL,继续弹出就会出错,所以修改下列。
while(order.front()==s.top()&&!s.empty()){
s.pop();
oder.pop();
}
}
if(!s.empty()){
return false;
}
return true;
}
224.基础计数器
思考:画出有穷状态机就可以解决了。
class Solution {
public:
void compute(stack<int> &numbers,stack<char> &operation){
if(numbers.size()<2){
return ;
}
int num2 = numbers.top();
numbers.pop();
int num1 = numbers.top();
numbers.pop();
if(operation.top() == '+'){
numbers.push(num1 + num2);
}
else if(operation.top() == '-') {
numbers.push(num1 - num2);
}
operation.pop();
}
int calculate(string s) {
static const int BEGIN_STATE = 0;
static const int NUMBER_STATE = 1;
static const int OPERATOR_STATE = 2;
stack<int> numbers_stack;
stack<char> operation_stack;
int number = 0;
int STATE = BEGIN_STATE;
int compute_flag = 0;
//遇到数字和+-的时候才有用 才需要推格操作
for(int i = 0;i<s.size();i++){
if(s[i] == ' '){
continue;
}
switch(STATE){
case BEGIN_STATE:
if(s[i]>='0' && s[i]<='9'){
STATE = NUMBER_STATE;
}
else{
STATE = OPERATOR_STATE;
}
i--;
break;
case NUMBER_STATE:
if(s[i]>='0' && s[i]<='9'){
number = number * 10 + s[i] - '0';
}
//'123'字符串在把他变成了数字之后状态仍然没有改变。
//所以判断compute_flag
else{
numbers_stack.push(number);
if(compute_flag==1){
compute(numbers_stack,operation_stack);
}
//如果字符串第一个'123'此时compute_flag = 0 前面没有数字不能计算。
number = 0;
i--;
STATE = OPERATOR_STATE;
}
break;
case OPERATOR_STATE:
if(s[i]== '+'||s[i] == '-'){
operation_stack.push(s[i]);
compute_flag = 1;
}
else if(s[i]=='('){
STATE = NUMBER_STATE;
compute_flag = 0;
}
else if(s[i]>='0' && s[i]<='9'){
STATE = NUMBER_STATE;
i--;
}
else if(s[i]==')'){
compute(numbers_stack,operation_stack);
}
break;
}
}
if(number!=0){
numbers_stack.push(number);
compute(numbers_stack,operation_stack);
}
if(number==0 && numbers_stack.empty()){
return 0;
}
return numbers_stack.top();
}
};
STL优先级队列构造堆
priority_queue<int> heap; //构造默认堆
priority_queue<int,vector<int>,greater<int>> small_heap; //构造默认最小堆
priority_queue<int,vector<int>,less<int>> big_heap; //构造默认最大堆
int test[] = {61,2,4,5,6,7,9,0};
vector<int> vec(test,test+8);
for( unsigned int i = 0;i < vec.size();i++){
big_heap.push(vec.at(i));
}
for(unsigned int i = 0;i < vec.size();i++){
cout<<big_heap.top()<<endl;
big_heap.pop();
}
遇到的问题和积累:
1error “<”: 有符号/无符号不匹配
答:”detector 是一个Vector容器 ,detecot.size() 在容器说明中 被定义为: unsigned int 类型, 而j是int 类型,所以会出现: 有符号/无符号不匹配警告,修改int i -->> unsigned int / size_t
2.error: error C2065: “cout”: 未声明的标识符 error C2065: “endl”: 未声明的标识符
答:没#include<iostream> ,之后再using namespace std
3.vector 两种访问 1、数组 2、 vec.at(i) //这种会检测访问越界
4.big_heap[8](61,6,9,2,5,4,7,0) 这个排序和按照二叉树 而不是数组的排序 pop()检查过才知道
215.数组中第K个最大的元素
思考: 第k大 用最小堆来处理,直接输出堆顶元素,保证最小堆有k个元素,那么堆顶元素是第k个元素中最小的,就是整个vector中第k大的。这里我一开始写的想用两个for循环,第一次是存储k个元素的堆;第二次是和堆顶元素进行比较。后来看了别人的代码,哇,深感自己太不会变通了。直接一次循环就可以了!~
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int,vector<int>,greater<int>> small_heap;
for(int i = 0; i <nums.size();i++){
if(i<k){
small_heap.push(nums[i]);
}
else if(nums[i] > small_heap.top()){
small_heap.pop();
small_heap.push(nums[i]);
}
}
return small_heap.top();
}
};
295.数据流的中位数
思考:
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {
}
//如果你用了else if 语句,当你条件满足时就不会再往下继续判断条件了;
//而if语句会把每一个条件都判断一下。
//两个约束:1、最大堆的堆顶小于最小堆的堆顶,这样就把数据流中间的数字找到了
//2、两个堆之间的数目相差不超过1
void addNum(int num) {
if(big_heap.empty()){
big_heap.push(num);
return ;
}
if(small_heap.size()==big_heap.size()){
//既然要存储到big_heap,那么肯定是和big_heap的堆顶比较,只要小于就说明属于这一半。
if(num < big_heap.top()){
big_heap.push(num);
}
else {
small_heap.push(num);
}
}
else if(small_heap.size() > big_heap.size()){
if(num >= small_heap.top()){
big_heap.push(small_heap.top());
small_heap.pop();//又当做链表直接覆盖了,这里如果你不把top()弹出来,
//那么你这个堆里面就多了一个元素呀。
small_heap.push(num);
}
else{
big_heap.push(num);
}
}
else if(small_heap.size() < big_heap.size()){
if(num <=big_heap.top()){
small_heap.push(big_heap.top());
big_heap.pop();
big_heap.push(num);
}
else{
small_heap.push(num);
}
}
}
double findMedian() {
if(small_heap.size()==big_heap.size()){
return (small_heap.top() + big_heap.top())/2;
}
else if(small_heap.size() > big_heap.size()){
return small_heap.top();
}
return big_heap.top();
}
priority_queue<double,vector<double>,greater<double>> small_heap;
priority_queue<double,vector<double>,less<double> > big_heap;
//最小堆和最大堆定义反了!!!debug半天!
};
总结:这个代码真调了无数次。。。
1、第一个错误,当small_heap 和 big_heap 中的数 相等的时候,就只用判断num和small_heap.top()和big_heap.top()大小,如果大于small_heap.top(),肯定属于small_heap,直接插入,反之亦然。
2、优先队列 priority_queue<double,vector<double>,greater<double>> small_heap;定义的时候出错了,第一个把数据类型弄成了int,导致输出的中位数出错了;第二个是排序错了,把两个正好弄反了,应该是最大堆,对应的递减啊!最小堆对应的递增啊!想下就清楚了!~!~