1. 设计一个具有getMin功能的栈
要求:pop、push、getMin等函数的功能的时间复杂度都是O(1)。
思路:用两个标准栈来实现。其中一个栈用于存储数据(称为数据栈,stackData),另一个栈用于存储当前数据栈中的最小值(称为最小栈,stackMin)。
入栈规则:
假设入栈的数据为 num,则将其压入stackData中,然后判断stackMin是否为空。
- 如果stackMin 为空,则将num 也压入stackMin中。
- 如果stackMin 不为空,则比较 num 与 stackMin 栈顶元素的大小。
- 如果num 小于等于 stackMin 栈顶元素,则将num 压入stackMin中。
- 如果num 大于 stackMin 栈顶元素,则stackMin不做操作。
出栈规则:
将stackData的栈顶元素出栈,如该元素等于stackMin的栈顶元素,则stackMin将栈顶元素出栈。如该元素大于stackMin的栈顶元素,则stackMin不做操作。
获取栈中最小元素时,只需要输出stackMin的栈顶元素。
具体代码为:
class New_stack
{
public:
New_stack();
~New_stack();
void push(int n);
void pop();
int top();
int getMin();
private:
stack<int> stack_data;
stack<int> stack_min;
};
New_stack::New_stack()
{
}
New_stack::~New_stack()
{
}
void New_stack::push(int n)
{
stack_data.push(n);
if (stack_min.empty())
stack_min.push(n);
else if (n <= stack_min.top())
stack_min.push(n);
}
int New_stack::top()
{
return stack_data.top();
}
void New_stack::pop()
{
if (stack_data.empty())
cout << "The stack is empty !" << endl;
if (stack_data.top() == stack_min.top())
stack_min.pop();
stack_data.pop();
}
int New_stack::getMin()
{
if (stack_data.empty())
cout << "The stack is empty !" << endl;
return stack_min.top();
}
测试代码:
int main()
{
cout <<"the stack who has getMin functon " << endl;
New_stack stack_min;
stack_min.push(10);
stack_min.push(12);
stack_min.push(5);
stack_min.push(3);
stack_min.push(54);
for (int i = 0; i < 5; ++i)
{
cout << "the stack min value: " << stack_min.getMin() << endl;
stack_min.pop();
}
return 0;
}
测试结果:
2. 用一个栈实现另一栈的排序
要求:一个栈中的元素为整型,现在将栈从顶到底按从大到小的顺序排序。只允许申请一个栈。除此之外,可以申请新的变量,但是不允许使用其他的数据结构。
思路:申请一个栈用于存储临时的排序结果(记为temp_stack),申请一个变量用于记录排序栈的栈顶元素(记为cur)。如果temp_stack为空,则将cur压人temp_stack中;如果temp_stack不为空且cur 小于等于temp_stack的栈顶元素,则将压入temp_stack中;如果temp_stack不为空且cur 大于temp_stack的栈顶元素,则需要将temp_stack栈中的元素压入排序栈中,直到cur值小于等于temp_stack的元素或temp_stack为空。用这种方式排序后,temp_stack栈从顶到底的元素顺序为从小到大的顺序。因此,还需要将temp_stack栈中的元素压入原始栈中。从而实现栈从顶到底按从大到小的顺序排序。
代码:
void sortStackbyStack(stack<int> &s)
{
stack<int> temp_stack;
int cur = 0;
while (!s.empty())
{
cur = s.top();
s.pop();
while (!temp_stack.empty() && temp_stack.top() < cur)
{
s.push(temp_stack.top());
temp_stack.pop();
}
temp_stack.push(cur);
}
while (!temp_stack.empty())
{
s.push(temp_stack.top());
temp_stack.pop();
}
}
测试代码:
int main()
{
stack<int> s;
cout << endl <<"用栈将另一个栈排序: " << endl;
cout <<" 原始栈: " ;
s.push(1); s.push(5); s.push(6); s.push(4); s.push(7);
for (int i = 0; i < 5; ++i)
{
cout << s.top() << " ";
s.pop();
}
cout << endl;
cout << " 排序栈: ";
s.push(1); s.push(5); s.push(6); s.push(4); s.push(7);
sortStackbyStack(s);
for (int i = 0; i < 5; ++i)
{
cout << s.top() << " ";
s.pop();
}
cout << endl;
return 0;
}
测试结果:
3.Next Greater Node In Linked List
该题是查找链表中当前元素后面第一个大于当前元素值的元素。用暴力法解决该问题时间复杂度是O(n^2)。但是这种做法肯定难以让人满意。所以需要寻找一种更好的方法。
该问题的最优解是用栈来处理。具体思路为:
栈内存放的是 结点的编号。 每压入一个编号前,先检查该编号对应元素是否大于栈顶的编号对应元素,、如果大于,则栈顶编号出列,且栈顶编号对应元素的greater为 当前编号对应元素。如果不大于,则继续压栈。
这样做的目的是 用栈来记录哪些节点未找到它的目标节点。没找到目标节点的节点就保留在栈中,那些找到目标节点的节点则记录它的目标节点然后出栈。
具体代码为:
vector<int> nextLargerNodes(ListNode* head) {
stack<int> hole;
vector<int> values;
for (auto node = head; node; node = node->next)//获取链表中节点的值,将其保存在values中,以便进行处理。
{
values.push_back(node->val);
}
vector<int> res(values.size(), 0);
for (auto i = 0; i < values.size(); ++i)
{
//查找目标值的过程
while (!hole.empty() && values[i] > values[hole.top()])
{
res[hole.top()] = values[i];
hole.pop();
}
hole.push(i);
}
return res;
}
运行结果为: