由于之前看了牛客网的数据结构和算法的课程知道了左神,现在找到了这本书当作入门书做做吧,虽然书的题解都是java实现的,但好在用c++实现难度不大。
第一章 栈和队列
题目1:单调栈结构
给定一个不含有重复值数组arr找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。返回所有位置相应的信息。
方法一:无脑遍历时间复杂度O(n^2),每个位置分别向左和向右遍历一下,总可以确定
#include "stdafx.h"
#include<iostream>
#include <iomanip>
using namespace std;
int ** rightWay(int arr[] , int size)
{
//如果要返回二维数组,只能返回指向二维数组的指针,首先在栈中申请一个元素为一位数组的数组
int **res=new int*[size];
for (int i=0;i<size;++i)
{
//再在栈中为一位数组申请储存空间
res[i]=new int[2];
int leftIndex,rightIndex,lefti=i-1,righti=i+1;
if (i==0)
{
leftIndex=-1;
}
if (i==size-1)
{
rightIndex=-1;
}
for (;i!=0&&arr[lefti]>arr[i]&&lefti>=0;lefti--)
{
}
if (lefti==-1)
{
leftIndex=-1;
}
else{leftIndex=lefti;}
for (;i!=0&&arr[righti]>arr[i]&&righti<=6;righti++)
{
}
if (righti==7)
{
rightIndex=-1;
}
else{rightIndex=righti;}
res[i][0]=leftIndex;
res[i][1]=rightIndex;
}
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
int arr1[7]={3,4,1,5,6,2,7};
int**p=rightWay(arr1,7);
for (int A=0;A<7;++A)
{
std::cout<<"{";bool a=1;
for (int B=0;B<2;++B)
{
std::cout<<setw(2)<<p[A][B];
if (a)
{
cout<<",";a=0;
}
}
std::cout<<"}"<<std::endl;
}
return 0;
}
方法二:单调栈结构,关键在于生成所有位置的相应信息,时间复杂度做到O(n)
//由于会出现重复的元素,于是在栈中的元素从之前的int变成了queue<int>
#include "stdafx.h"
#include <iostream>
#include <stack>
#include <iomanip>
using namespace std;
int** MonotoneStackArchitecture1(int arr[],int size){
//如果要返回二维数组,只能返回指向二维数组的指针,首先在栈中申请一个元素为一位数组的数组
int**res=new int*[size];
stack<int>stack1;
for(int i=0;i<size;++i){
//再在栈中为一位数组申请储存空间
res[i]=new int[2];
}
for(int i=0;i<size;++i){
if(stack1.empty()||arr[stack1.top()]<arr[i]){
stack1.push(i);
}
else
{
while(!stack1.empty()&&arr[stack1.top()]>arr[i]){
int tmp=stack1.top();
stack1.pop();
if (stack1.empty())
{
res[tmp][0]=-1;
}
else
res[tmp][0]=stack1.top();
res[tmp][1]=i;
}
stack1.push(i);//之前数据一直不对,就是因为没有把元素右侧最近的元素位置压入栈中。
}
}
while(!stack1.empty()){
int tmp=stack1.top();
stack1.pop();
if (stack1.empty())
{
res[tmp][0]=-1;
}
else res[tmp][0]=stack1.top();
res[tmp][1]=-1;
}
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
int arr1[7]={3,4,1,5,6,2,7};
int**p=MonotoneStackArchitecture1(arr1,7);
for (int A=0;A<7;++A)
{
std::cout<<"{";bool a=1;
for (int B=0;B<2;++B)
{
std::cout<<setw(2)<<p[A][B];
if (a)
{
cout<<",";a=0;
}
}
std::cout<<"}"<<std::endl;
}
return 0;
}
题目1.1:单调栈结构(进阶)
给定一个含有重复值数组arr找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。返回所有位置相应的信息。
// 由于会出现重复的元素,于是将栈中的元素从int改成了queue<int>
#include "stdafx.h"
#include <iostream>
#include <stack>
#include <iomanip>
#include <queue>
using namespace std;
int** MonotoneStackArchitecture1(int arr[],int size){
int**res=new int*[size];
stack<queue<int> >stack1;
for(int i=0;i<size;++i){
res[i]=new int[2];
}
for(int i=0;i<size;++i){
if(stack1.empty()||arr[stack1.top().back()]<arr[i]){
queue<int> queue1;
queue1.push(i);
stack1.push(queue1);
}
else
{
while(!stack1.empty()&&arr[stack1.top().back()]>arr[i]){
queue<int> tmpQ=stack1.top();//总是用一个tmp来记录直接被弹出的单调栈的元素
stack1.pop();
if(stack1.empty())
{
while(!tmpQ.empty()){
int tmp=tmpQ.back();
tmpQ.pop();
res[tmp][0]=-1;
res[tmp][1]=i;
};
}
else{
while(!tmpQ.empty()){
int tmp=tmpQ.front();
tmpQ.pop();//原先一直有三个数据没有被赋值,错在tmpQ.pop()这里pop出去的元素并不是t.back(),而是tmpQ.front()
res[tmp][0]=stack1.top().back();
res[tmp][1]=i;
};
}
}
if (!stack1.empty()&&!stack1.top().empty()&&arr[stack1.top().back()]==arr[i])//判断条件之前没加 !stack1.empty()&&!stack1.top().empty() 然后报错
{
cout<<1<<endl;
stack1.top().push(i);//之前数据一直不对,就是因为没有把元素右侧最近的元素位置压入栈中。
}
else{
queue<int> queue1;
queue1.push(i);
stack1.push(queue1);
}
}
}
while(!stack1.empty()){
queue<int> tmpQ=stack1.top();
stack1.pop();
if(stack1.empty())
{
while(!tmpQ.empty()){
int tmp=tmpQ.front();//原先一直有三个数据没有被赋值,错在tmpQ.pop()这里pop出去的元素并不是t.back(),而是tmpQ.front()
tmpQ.pop();
res[tmp][0]=-1;
res[tmp][1]=-1;
};
}
else{
while(!tmpQ.empty()){
int tmp=tmpQ.front();//原先一直有三个数据没有被赋值,错在tmpQ.pop()这里pop出去的元素并不是t.back(),而是tmpQ.front()
tmpQ.pop();
res[tmp][0]=stack1.top().back();
res[tmp][1]=-1;
};
}
}
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
int arr1[9]={3,1,3,4,3,5,3,2,2};
int**p=MonotoneStackArchitecture1(arr1,9);
for (int A=0;A<9;++A)
{
std::cout<<"{";bool a=1;
for (int B=0;B<2;++B)
{
std::cout<<setw(2)<<p[A][B];
if (a)
{
cout<<",";a=0;
}
}
std::cout<<"}"<<std::endl;
}
delete p;
return 0;
}