目录
- 前言
- 1.杭电oj——Bitset
- 2.杭电oj——进制转换
- [3.力扣——LCR 123. 图书整理 I](https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/description/)
- [4.力扣——LCR 027. 回文链表](https://leetcode.cn/problems/aMhZSa/)
- [5.力扣——1614. 括号的最大嵌套深度](https://leetcode.cn/problems/maximum-nesting-depth-of-the-parentheses/description/)
- 6.力扣——20.有效的括号
- [7.力扣——739. 每日温度](https://leetcode.cn/problems/daily-temperatures/description/)
- [8.力扣——2487. 从链表中移除节点](https://leetcode.cn/problems/remove-nodes-from-linked-list/)
- 结语
前言
在上一期作品 (蓝色字体可以点进去看上期作品) 我们对栈有了初步的了解,这期我们来进行实战,做一些栈相关的题。
1.杭电oj——Bitset
(蓝色字体点进去看原题)
#include<iostream>
#include<stdexcept>
#include<stack>
using namespace std;
template<typename T>
class Stack {
private:
struct Node{
T data;
Node* next;
Node(T x):data(x),next(NULL){}
};
Node* head;
int size;
public:
Stack():size(0),head(NULL){}
~Stack();
void push(T x);
T top() const;
T pop();
bool empty();
int getSize();
};
template<typename T>
Stack<T>::~Stack() {
while (head) {
Node* t = head;
head = head->next;
delete t;
}
}
template<typename T>
void Stack<T>::push(T x) {//插入操作用头插法,即头节点为栈顶
Node* newNode = new Node(x);
newNode->next = head;
head = newNode;
size++;
}
template<typename T>
T Stack<T>::top() const {
if (!head) {
throw std::underflow_error("Stack is empty!");
}
return head->data;
}
template<typename T>
T Stack<T>::pop() {
if (!head) {
throw std::underflow_error("Stack is empty!");
}
T result = head->data;
Node* t = head;
head = head->next;
delete t;
size--;
return result;
}
template<typename T>
int Stack<T>::getSize() {
return size;
}
template<typename T>
bool Stack<T>::empty() {
return size == 0 ? 1 : 0;
}
int main() {
int n;
while (cin >> n) {
Stack<int>s;
while (n) {
s.push(n % 2);
n /= 2;
}
while (!s.empty()) {
int x = s.pop();
cout << x;
}
cout << endl;
}
return 0;
}
2.杭电oj——进制转换
(蓝色字体点进去看原题)
#include<iostream>
#include<exception>
using namespace std;
template<typename T>//定制栈里面的元素,就像vector一样
class Stack {
private:
int size;//既为栈元素个数又为栈顶位置
int capacity;
T* data;
void resize();
public:
Stack():data(new T[capacity]),size(0),capacity(10){}//构造函数,申请类型为T容量为capacity的内存空间,相当于数组
~Stack();
void push(T x);
T top() const;
T pop();
int getSize() const;
bool empty() const;
};
template<typename T>
void Stack<T>::resize() {//顺序栈扩容
int newCapacity = 2 * capacity;
T* newData = new T[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
delete[]data;
data = newData;
capacity = newCapacity;
}
template<typename T>
Stack<T>::~Stack() {
delete[]data;
}
template<typename T>
void Stack<T>::push(T x) {
if (size == capacity) {
resize();
}
data[size++] = x;
}
template<typename T>
T Stack<T>::top() const {
if (!size) {
throw std::underflow_error("Stack is empty");//如果栈为空即为非法状态,抛出异常
}
return data[size - 1];//注意栈元素序号从零开始
}
template<typename T>
T Stack<T>::pop(){
if (!size) {
throw std::underflow_error("Stack is empty");
}
return data[--size];
}
template<typename T>
int Stack<T>::getSize() const {
return size;
}
template<typename T>
bool Stack<T>::empty() const {
return size == 0 ? 1 : 0;
}
int main() {
int n,base;
while (cin >> n >> base) {
if (!n) {//如果进制数为0那么结果自然为零
cout << 0 << endl;
continue;
}
if (n < 0) {//如果是负数就输出个负号
cout << "-";
n = -n;
}
Stack<int>s;
while (n) {
s.push(n % base);
n /= base;
}
while (!s.empty()) {
int x = s.pop();
if (x < 10)cout << x;//小于零就直接输出这个数
else {
printf("%c", 'A' + x - 10);//大于零就输出字符,记住这个转换公式'A'+x-10
}
}
cout << endl;
}
return 0;
}
3.力扣——LCR 123. 图书整理 I
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
vector<int> reverseBookList(ListNode* head) {//这一题就是反转链表,也就是逆序输出链表
stack<int> s;
while(head){
s.push(head->val);
head=head->next;
}
vector<int>ans;
while(!s.empty()){
ans.push_back(s.top());
s.pop();
}
return ans;
}
};
4.力扣——LCR 027. 回文链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode*curr=head;
stack<int>s;
while(curr){
s.push(curr->val);
curr=curr->next;
}
while(head){
if(head->val!=s.top())return false;
s.pop();
head=head->next;
}
return true;
}
};
5.力扣——1614. 括号的最大嵌套深度
class Solution {
public:
int maxDepth(string s) {//思路:如果是(进栈在cnt++,如果是)出栈cnt--,每次用ret与cnt比较,就可以得到最大值
stack<char>st;
int cnt=0,ret=0;
for(int i=0;i<s.size();i++){
if(s[i]=='('){
st.push(s[i]);
cnt++;
}
if(s[i]==')'){
st.pop();
cnt--;
}
ret=max(ret,cnt);
}
return ret;
}
};
6.力扣——20.有效的括号
class Solution {
bool isLeft(char s){
return s == '(' || s == '{'|| s == '[';
}
bool isMatch(char l, char r){
return l == '(' && r == ')' ||
l == '{' && r == '}' ||
l == '[' && r == ']';
}
public:
bool isValid(string s) {
stack<char> stk;
for(int i=0;i<s.size();i++){
if(isLeft(s[i])){//如果是左括号都入栈
stk.push(s[i]);
}
else{
if(stk.empty())return false;//如果不是左括号并且这时候栈为空就说明没有与之匹配的括号
if(!isMatch(stk.top(), s[i]))return false;//如果不匹配就返回空
stk.pop();
}
}
if(!stk.empty())return false;//遍历完以后如果栈不为空那么就是说还有左括号没匹配
return true;
}
};
7.力扣——739. 每日温度
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& t) {
vector<int>ans;//用于保存结果
vector<int>stk;//这个vector当做栈用,用于记录t的位置
for(int i=0;i<t.size();i++){
ans.push_back(0);//给结果数组初始化为0
}
for(int i = 0; i < t.size(); i++){
while(stk.size() && t[ stk.back() ] < t[i]){
ans[ stk.back() ] = i - stk.back();
stk.pop_back();
}
stk.push_back(i);//如果栈为空并且t[ stk.back() ] > t[i],就插入当前位置
}
return ans;
}
};
8.力扣——2487. 从链表中移除节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNodes(ListNode* head) {
vector<ListNode*> s;//用vector当做栈使用,存储单调不减的结果链表
ListNode* dummy = new ListNode(1000000,head);//利用这个虚拟头结点返回结果链表,赋值一个比链表所有值都大的数,dummy->next=head
ListNode*now = head;
s.push_back(dummy);
while(now){
while(s.back()->val < now -> val){//如果遍历到当前数大于栈顶值,就弹栈,直到不大于为止
s.pop_back();
}
s.push_back(now);
now=now->next;
}
for(int i=0;i<s.size()-1;i++){
s[i]->next=s[i+1];//改变栈元素节点的指向形成新链表,即为结果链表
}
s.back()->next=NULL;//尾结点下一个节点必然为空
return dummy->next;//dummy就是结果链表
}
};
结语
想必做过这个题库的帅哥对栈的理解与应用有了提升,那么对初级数据结构——栈的学习就告一段落,下个作品我会与大家深入对初级数据结构——队列学习。
想看更多内容可以关注我,看我作品,关注我让我们一起学习编程,希望大家能点赞关注支持一下,让我有持续更新的动力,谢谢大家