记录算法基础题思路:
队列实现栈:核心在于出入顺序有差别,可以再入队之后,把队列里面的旧数据重新出队入队,就能和栈顺序一致;
栈实现队列:可以通过两个队列模拟,一个队列负责出数据,一个负责入数据,当需要出时,如果出队为空,把入队的数据送入出队;
包含min函数栈:1、新栈去记录每次最小值 2 使用变量min记录当前最小,如果入栈的变量更小就先把旧min入栈,然后刷新min,出栈的时候如果==min,就多pop一个值刷新min
合法出栈校验:利用空栈校验,连续入栈输入顺序,当和输出相等就pop,最后为空就说明合法;
简单计算器:一个栈记录符号,一个栈记录数值,当遇到)就开始 pop 符号栈和数据栈 开始计算直到 (,把结果入栈,到最后再计算一次 作为最终结果;
求第K大数:1、先排序再取值 2、构建一个size为k的小顶堆,如果遍历的发现堆size==k,只有当num > top时,再pop和push更新堆,堆顶为结果;
寻中位数:构造一个大顶堆(小的一半数) 和 小顶堆(大的一半数),每次先往数量少的一方加,如果加不进去,比如往大顶堆添加元素的时候,发现比小顶堆头大,就交换一下 把小顶头入大顶堆,然后原数入小顶堆;
step1:
队列实现栈:https://leetcode-cn.com/problems/implement-stack-using-queues/
使用队列实现栈的下列操作:
push(x) -- 元素 x 入栈
pop() -- 移除栈顶元素
top() -- 获取栈顶元素
empty() -- 返回栈是否为空
/** Push element x onto stack. */
void push(int x) {
unsigned int size = que.size();
que.push(x);
while (size > 0) {
que.push(que.front());
que.pop();
size--;
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int val = que.front();
que.pop();
return val;
}
/** Get the top element. */
int top() {
return que.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return que.empty();
}
栈实现队列:https://leetcode-cn.com/problems/implement-queue-using-stacks/
使用栈实现队列的下列操作:
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
/** Push element x to the back of queue. */
void push(int x) {
pushStack.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if (popStack.empty() == true) {
int size = pushStack.size();
while (size > 0) {
int val = pushStack.top();
pushStack.pop();
popStack.push(val);
size--;
}
}
if (popStack.empty() != true) {
int val = popStack.top();
popStack.pop();
return val;
}
return -1;
}
/** Get the front element. */
int peek() {
if (popStack.empty() == true) {
int size = pushStack.size();
while (size > 0) {
int val = pushStack.top();
pushStack.pop();
popStack.push(val);
size--;
}
}
if (popStack.empty() != true) {
int val = popStack.top();
return val;
}
return -1;
}
/** Returns whether the queue is empty. */
bool empty() {
if (pushStack.empty() == true && popStack.empty() == true) {
return true;
}
return false;
}
包含min函数栈:https://leetcode-cn.com/problems/min-stack/
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
void push(int x) {
if (x <= min) {
dataStack.push(min);
min = x;
}
dataStack.push(x);
}
void pop() {
int val = dataStack.top();
dataStack.pop();
if (val == min) {
min = dataStack.top();
dataStack.pop();
}
}
int top() {
return dataStack.top();
}
int getMin() {
if (dataStack.empty() == true) {
return -1;
}
return min;
}
合法出栈校验:https://leetcode-cn.com/problems/validate-stack-sequences/
给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
unsigned int pop_pos = 0;
for (unsigned int i = 0; i < pushed.size(); i++) {
dataStack.push(pushed[i]);
while ((dataStack.empty() != true) && (dataStack.top() == popped[pop_pos])) {
dataStack.pop();
pop_pos++;
}
}
return dataStack.empty() == true;
}
简单计算器:https://leetcode-cn.com/problems/basic-calculator/
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例:
输入: "1 + 1"
输出: 2
int calculate(string s) {
stack<char> opr;
stack<int> num;
num.push(0);
int idx = 0;
while(idx < s.size()){
if(s[idx] == ' ')
++idx;
else if(s[idx] == '(' || s[idx] == '+' || s[idx] == '-'){
opr.push(s[idx]);
++idx;
}
else if(s[idx] == ')'){
int sum = 0;
while(opr.top() != '('){
char op = opr.top();
opr.pop();
int n = num.top();
num.pop();
sum += op=='+'? n: -n;
}
sum += num.top();
num.pop();
num.push(sum);
opr.pop();
++idx;
}
else{
unsigned int val = 0;
while (s[idx] >= '0' && s[idx] <= '9') {
val = val * 10 + s[idx] - '0';
idx++;
}
num.push(val);
}
}
int sum = 0;
while(!opr.empty()){
char op = opr.top();
opr.pop();
int n = num.top();
num.pop();
sum += op=='+'? n: -n;
}
return sum + num.top();
}
求第K大数:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 :
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int,vector<int>,greater<int>> small_heap;
for(auto num:nums){
if(small_heap.size() < k) {
small_heap.push(num);
} else {
if (num > small_heap.top()) {
small_heap.pop();
small_heap.push(num);
}
}
}
return small_heap.top();
}
寻中位数:https://leetcode-cn.com/problems/find-median-from-data-stream/
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
/* 大顶堆 放小的一半,堆顶为最大值 */
priority_queue<int, vector<int>, less<int>> low_heap;
/* 小顶堆 放大的一半,堆顶为最小值 */
priority_queue<int, vector<int>, greater<int>> high_heap;
public:
// Adds a number into the data structure.
void addNum(int num)
{
if (low_heap.empty() == true) {
low_heap.push(num);
return;
}
if (low_heap.size() == high_heap.size()) {
/* 两堆数量一样多,按实际大小判断放哪一堆里面 */
if (num > low_heap.top()) {
high_heap.push(num);
} else {
low_heap.push(num);
}
} else if (high_heap.size() > low_heap.size()) {
/* 大的数比较多,优先放low堆,放不进去就把high的top换过来 */
if (num <= high_heap.top()) {
low_heap.push(num);
} else {
low_heap.push(high_heap.top());
high_heap.pop();
high_heap.push(num);
}
} else {
/* 小的数比较多,优先放high堆,放不进去就把low的top换过来 */
if (num >= low_heap.top()) {
high_heap.push(num);
} else {
high_heap.push(low_heap.top());
low_heap.pop();
low_heap.push(num);
}
}
}
double findMedian()
{
if (low_heap.size() == high_heap.size()) {
return (low_heap.top() + high_heap.top()) / 2.0;
} else if (low_heap.size() > high_heap.size()) {
return low_heap.top();
} else {
return high_heap.top();
}
}