第一题
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
class MinStack {
private:
stack<int> s;
stack<int> min_s;
public:
void push(int x) {
s.push(x);
if(min_s.empty())
{
min_s.push(x);
return;
}
if(min_s.top()>=x)//一定要大于等于,不然多个相同的最小值会出问题
{
min_s.push(x);
}
}
void pop() {
if(s.top()==min_s.top())
{
min_s.pop();
}
s.pop();
}
int top() {
return s.top();
}
int min() {
return min_s.top();
}
};
其实这里也可以不通过辅助栈来解决这个问题
只需要记录当前值与最小值之间差值和最小值
差值大于0,说明当前值不为最小值,不需要更新最小值
差值小于0,说明当前值是最小值,删除的时候我们需要更新最小值
数据溢出的问题
class MinStack {
private:
stack<long long> s;
long long Min;
public:
void push(int x) {
if (s.empty()) //初始化差值为0
{
s.push(0);
Min = x;
return;
}
s.push((long long)x - Min);//先算差值,再更新Min。
if (x < Min)
{
Min = x;
}
}
void pop() {
if (s.top() >= 0)
{
s.pop();
}
else
{
Min -= s.top();
s.pop();
}
}
int top() {
if(s.top()>=0)
{
return Min+s.top();
}
else
{
return Min;
}
}
int min()
{
return Min;
}
};
第二题
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
stack<int> s;
while(head!=nullptr)
{
s.push(head->val);
head=head->next;
}
vector<int> ret;
while(!s.empty())
{
ret.push_back(s.top());
s.pop();
}
return ret;
}
};
第三题
给定一个整数数组 asteroids,表示在同一行的小行星。
对于数组中的每一个元素,其绝对值表示小行星的大小,正负表示小行星的移动方向(正表示向右移动,负表示向左移动)。每一颗小行星以相同的速度移动。
找出碰撞后剩下的所有小行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/XagZNi
class Solution {
public:
//先找到第一个向右的星星,右行撞完,再继续找
vector<int> asteroidCollision(vector<int>& asteroids) {
vector<int> ret_aster; //用顺序表也能实现栈的操作
bool alive=true;
for(auto e:asteroids)
{
alive=true;
//如果栈顶的星星向右并且遇到了向左的星星,那么相撞
while(alive&&e < 0 && !ret_aster.empty() && ret_aster.back() > 0){
if(ret_aster.back()>(-e)){
alive=false;
}
else if(ret_aster.back()==(-e)) {
alive=false;
ret_aster.pop_back();
}
else{
ret_aster.pop_back();
}
}
if(alive)
{
ret_aster.push_back(e);
}
}
return ret_aster;
}
};
第四题
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
// if(pushed.empty())
// {
// return true;
// }
// stack<int> s;
// s.push(pushed[0]);
// while(!pushed.empty()){
// if(popped.front()==s.top())
// {
// popped.erase(popped.begin());
// s.pop();
// }
// s.push(pushed.front());
// pushed.erase(popped.begin());
// }
// while(popped.front()==s.top()&&!popped.empty())
// {
// popped.erase(popped.begin());
// s.pop();
// }
// return s.empty();
//先进栈再判断能不能出栈,不然要额外处理尾巴,会麻烦
stack<int> st; //模拟实现的话要确保全都进去了,所以可以通过遍历pushed序列来实现,头删效率太低,而且容易出错。
for (int i = 0, j = 0; i < pushed.size(); i++) {
st.push(pushed[i]);
while (!st.empty() && st.top() == popped[j]) {
st.pop();
j++;
}
}
return st.empty();
}
};
不判空会报错
第五题
给定两个 非空链表 l1
和 l2
来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表
/**
* 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* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1,s2;
while(l1!=nullptr)
{
s1.push(l1->val);
l1=l1->next;
}
while(l2!=nullptr)
{
s2.push(l2->val);
l2=l2->next;
}
int flag=0;
ListNode* ret=new ListNode(0);
ret->next=nullptr;
while(!s1.empty()||!s2.empty())
{
int a=s1.empty()?0:s1.top();
int b=s2.empty()?0:s2.top();
int total=a+b+flag;
flag=0;
if(!s1.empty()){
s1.pop();
}
if(!s2.empty()){
s2.pop();
}
if(total>9)
{
total%=10;
flag=1;
}
ListNode* new_node=new ListNode(total);
new_node->next=ret->next;
ret->next=new_node;
}
if(flag==1)
{
ListNode* new_node=new ListNode(1);
new_node->next=ret->next;
ret->next=new_node;
}
return ret->next;
}
};